This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
Matt Williamson (author)
Tue May 26 07:48:34 -0700 2009
erl_bdb_sample / priv / bdb_drv.c
| 8045eea9 » | Matt Williamson | 2009-05-22 | 1 | #include "bdb_drv.h" | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 2 | ||
| 3 | static ErlDrvEntry basic_driver_entry = { | ||||
| 4 | NULL, /* init */ | ||||
| 5 | start, /* startup */ | ||||
| 6 | stop, /* shutdown */ | ||||
| 7 | NULL, /* output */ | ||||
| 8 | NULL, /* ready_input */ | ||||
| 9 | NULL, /* ready_output */ | ||||
| 10 | "bdb_drv", /* the name of the driver */ | ||||
| 11 | NULL, /* finish */ | ||||
| 12 | NULL, /* handle */ | ||||
| 13 | NULL, /* control */ | ||||
| 14 | NULL, /* timeout */ | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 15 | outputv, /* outputv */ | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 16 | NULL, /* ready_async */ | |
| 17 | NULL, /* flush */ | ||||
| 18 | NULL, /* call */ | ||||
| 19 | NULL, /* event */ | ||||
| 20 | ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */ | ||||
| 21 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */ | ||||
| 22 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */ | ||||
| 23 | ERL_DRV_FLAG_USE_PORT_LOCKING /* ERL_DRV_FLAGs */ | ||||
| 24 | }; | ||||
| 25 | |||||
| 26 | DRIVER_INIT(basic_driver) { | ||||
| 27 | return &basic_driver_entry; | ||||
| 28 | } | ||||
| 29 | |||||
| 30 | static ErlDrvData start(ErlDrvPort port, char* cmd) { | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 31 | bdb_drv_t* retval = (bdb_drv_t*) driver_alloc(sizeof(bdb_drv_t)); | |
| ff218941 » | Matt Williamson | 2009-05-22 | 32 | u_int32_t open_flags = DB_CREATE | DB_THREAD; | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 33 | DB *db; | |
| f70d9a31 » | Matt Williamson | 2009-05-22 | 34 | int status; | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 35 | ||
| 36 | db_create(&db, NULL, 0); | ||||
| f300711b » | Matt Williamson | 2009-05-26 | 37 | status = db->open(db, NULL, DB_PATH, NULL, DB_BTREE, open_flags, 0); | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 38 | ||
| f6c097bf » | Matt Williamson | 2009-05-26 | 39 | if(status != 0) { | |
| 40 | char *error_reason; | ||||
| 41 | |||||
| 42 | switch(status){ | ||||
| 43 | case DB_OLD_VERSION: | ||||
| 44 | error_reason = "the file was created with a different version."; | ||||
| 45 | break; | ||||
| 46 | |||||
| 47 | case EINVAL: | ||||
| 48 | error_reason = "the file was opened with incorrect flags. Perhaps the system does not support the DB_THREAD flag?"; | ||||
| 49 | break; | ||||
| 50 | |||||
| 51 | case DB_RUNRECOVERY: | ||||
| 52 | error_reason = "the file needs to be recovered, it may be corrupt."; | ||||
| 53 | break; | ||||
| 54 | default: | ||||
| 55 | error_reason = "of an unkown reason."; | ||||
| 56 | } | ||||
| 57 | |||||
| 58 | fprintf(stderr, "Unabled to open file: %s because %s\n\n", DB_PATH, error_reason); | ||||
| 59 | } | ||||
| 60 | |||||
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 61 | retval->port = port; | |
| 62 | retval->db = db; | ||||
| 63 | |||||
| 64 | return (ErlDrvData) retval; | ||||
| 65 | } | ||||
| 66 | |||||
| 67 | static void stop(ErlDrvData handle) { | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 68 | bdb_drv_t* driver_data = (bdb_drv_t*) handle; | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 69 | ||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 70 | driver_data->db->close(driver_data->db, 0); | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 71 | driver_free(driver_data); | |
| 72 | } | ||||
| 73 | |||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 74 | static void outputv(ErlDrvData handle, ErlIOVec *ev) { | |
| 75 | bdb_drv_t* driver_data = (bdb_drv_t*) handle; | ||||
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 76 | ErlDrvBinary* data = ev->binv[1]; | |
| 77 | int command = data->orig_bytes[0]; | ||||
| 78 | |||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 79 | switch(command) { | |
| 80 | case CMD_PUT: | ||||
| 81 | put(driver_data, ev); | ||||
| 82 | break; | ||||
| 83 | |||||
| 84 | case CMD_GET: | ||||
| 85 | get(driver_data, ev); | ||||
| 86 | break; | ||||
| 87 | |||||
| ff218941 » | Matt Williamson | 2009-05-22 | 88 | case CMD_DEL: | |
| 89 | del(driver_data, ev); | ||||
| 90 | break; | ||||
| 91 | |||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 92 | default: | |
| 93 | unkown(driver_data, ev); | ||||
| 94 | } | ||||
| 95 | } | ||||
| 96 | |||||
| 97 | static void put(bdb_drv_t *bdb_drv, ErlIOVec *ev) { | ||||
| f70d9a31 » | Matt Williamson | 2009-05-22 | 98 | ErlDrvBinary* input = ev->binv[1]; | |
| 99 | char *bytes = input->orig_bytes; | ||||
| f300711b » | Matt Williamson | 2009-05-26 | 100 | char *key_bytes = bytes+1; | |
| 101 | char *value_bytes = bytes+1+KEY_SIZE; | ||||
| 102 | int value_size = input->orig_size - 1 - KEY_SIZE; | ||||
| ff218941 » | Matt Williamson | 2009-05-22 | 103 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 104 | DB *db = bdb_drv->db; | |
| 8045eea9 » | Matt Williamson | 2009-05-22 | 105 | DBT key; | |
| f300711b » | Matt Williamson | 2009-05-26 | 106 | DBT value; | |
| 107 | int status; | ||||
| 108 | |||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 109 | bzero(&key, sizeof(DBT)); | |
| f300711b » | Matt Williamson | 2009-05-26 | 110 | bzero(&value, sizeof(DBT)); | |
| 8045eea9 » | Matt Williamson | 2009-05-22 | 111 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 112 | key.data = key_bytes; | |
| 8045eea9 » | Matt Williamson | 2009-05-22 | 113 | key.size = KEY_SIZE; | |
| 114 | |||||
| f300711b » | Matt Williamson | 2009-05-26 | 115 | value.data = value_bytes; | |
| 116 | value.size = value_size; | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 117 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 118 | status = db->put(db, NULL, &key, &value, 0); | |
| f70d9a31 » | Matt Williamson | 2009-05-22 | 119 | db->sync(db, 0); | |
| f300711b » | Matt Williamson | 2009-05-26 | 120 | ||
| 121 | if(status == 0) { | ||||
| 122 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")}; | ||||
| 123 | |||||
| 124 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 125 | } else { | ||||
| 126 | char * error_reason; | ||||
| 127 | |||||
| 128 | switch(status) { | ||||
| 129 | case DB_LOCK_DEADLOCK: | ||||
| 130 | error_reason = "deadlock"; | ||||
| 131 | break; | ||||
| 132 | case EACCES: | ||||
| 133 | error_reason = "readonly"; | ||||
| 134 | break; | ||||
| 135 | case EINVAL: | ||||
| 136 | error_reason = "badflag"; | ||||
| 137 | break; | ||||
| 138 | case ENOSPC: | ||||
| 139 | error_reason = "btree_max"; | ||||
| 140 | break; | ||||
| 141 | case DB_RUNRECOVERY: | ||||
| 142 | error_reason = "run_recovery"; | ||||
| 143 | break; | ||||
| 144 | default: | ||||
| 145 | error_reason = "unkown"; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), | ||||
| 149 | ERL_DRV_ATOM, driver_mk_atom(error_reason), | ||||
| 150 | ERL_DRV_TUPLE, 2}; | ||||
| 151 | |||||
| 152 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 153 | } | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 154 | } | |
| 155 | |||||
| f300711b » | Matt Williamson | 2009-05-26 | 156 | static void get(bdb_drv_t *bdb_drv, ErlIOVec *ev) { | |
| 157 | ErlDrvBinary* input = ev->binv[1]; | ||||
| 158 | ErlDrvBinary *output_bytes; | ||||
| 159 | char *bytes = input->orig_bytes; | ||||
| 160 | char *key_bytes = bytes+1; | ||||
| 161 | |||||
| 162 | DB *db = bdb_drv->db; | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 163 | DBT key; | |
| f300711b » | Matt Williamson | 2009-05-26 | 164 | DBT value; | |
| 165 | int status; | ||||
| 8045eea9 » | Matt Williamson | 2009-05-22 | 166 | ||
| 167 | bzero(&key, sizeof(DBT)); | ||||
| f300711b » | Matt Williamson | 2009-05-26 | 168 | bzero(&value, sizeof(DBT)); | |
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 169 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 170 | key.data = key_bytes; | |
| 8045eea9 » | Matt Williamson | 2009-05-22 | 171 | key.size = KEY_SIZE; | |
| 172 | |||||
| f300711b » | Matt Williamson | 2009-05-26 | 173 | value.flags = DB_DBT_MALLOC; // Don't forget to free | |
| 8045eea9 » | Matt Williamson | 2009-05-22 | 174 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 175 | status = db->get(db, NULL, &key, &value, 0); | |
| f70d9a31 » | Matt Williamson | 2009-05-22 | 176 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 177 | if(status == 0) { | |
| 178 | output_bytes = driver_alloc_binary(value.size); | ||||
| 179 | output_bytes->orig_size = value.size; | ||||
| 180 | // TODO:Figure out if we can somehow use this original memory | ||||
| 181 | //binary->orig_bytes = (char *)&data.data; | ||||
| 182 | memcpy(output_bytes->orig_bytes, value.data, value.size); | ||||
| 183 | free(value.data); | ||||
| 184 | |||||
| 185 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"), | ||||
| 186 | ERL_DRV_BINARY, (ErlDrvTermData) output_bytes, output_bytes->orig_size, 0, | ||||
| 187 | ERL_DRV_TUPLE, 2}; | ||||
| 188 | |||||
| 189 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 190 | driver_free_binary(output_bytes); | ||||
| 191 | } else { | ||||
| 192 | char *error_reason; | ||||
| f70d9a31 » | Matt Williamson | 2009-05-22 | 193 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 194 | switch(status) { | |
| 195 | case DB_LOCK_DEADLOCK: | ||||
| 196 | error_reason = "deadlock"; | ||||
| 197 | break; | ||||
| 198 | case DB_SECONDARY_BAD: | ||||
| 199 | error_reason = "bad_secondary_index"; | ||||
| 200 | break; | ||||
| 201 | case ENOMEM: | ||||
| 202 | error_reason = "insufficient_memory"; | ||||
| 203 | break; | ||||
| 204 | case EINVAL: | ||||
| 205 | error_reason = "bad_flag"; | ||||
| 206 | break; | ||||
| 207 | case DB_RUNRECOVERY: | ||||
| 208 | error_reason = "run_recovery"; | ||||
| 209 | break; | ||||
| 210 | default: | ||||
| 211 | error_reason = "unknown"; | ||||
| 212 | } | ||||
| 213 | |||||
| 214 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), | ||||
| 215 | ERL_DRV_ATOM, driver_mk_atom(error_reason), | ||||
| 216 | ERL_DRV_TUPLE, 2}; | ||||
| 217 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 218 | } | ||||
| f7d2dcc4 » | Matt Williamson | 2009-05-19 | 219 | } | |
| ff218941 » | Matt Williamson | 2009-05-22 | 220 | ||
| f300711b » | Matt Williamson | 2009-05-26 | 221 | static void del(bdb_drv_t *bdb_drv, ErlIOVec *ev) { | |
| 222 | ErlDrvBinary* data = ev->binv[1]; | ||||
| 223 | char *bytes = data->orig_bytes; | ||||
| 224 | char *key_bytes = bytes+1; | ||||
| 225 | |||||
| 226 | DB *db = bdb_drv->db; | ||||
| ff218941 » | Matt Williamson | 2009-05-22 | 227 | DBT key; | |
| f300711b » | Matt Williamson | 2009-05-26 | 228 | int status; | |
| ff218941 » | Matt Williamson | 2009-05-22 | 229 | ||
| 230 | bzero(&key, sizeof(DBT)); | ||||
| 231 | |||||
| f300711b » | Matt Williamson | 2009-05-26 | 232 | key.data = key_bytes; | |
| ff218941 » | Matt Williamson | 2009-05-22 | 233 | key.size = KEY_SIZE; | |
| 234 | |||||
| 235 | status = db->del(db, NULL, &key, 0); | ||||
| f300711b » | Matt Williamson | 2009-05-26 | 236 | db->sync(db, 0); | |
| 237 | |||||
| 238 | if(status == 0) { | ||||
| 239 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")}; | ||||
| 240 | |||||
| 241 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 242 | |||||
| 243 | } else { | ||||
| 244 | char *error_reason; | ||||
| 245 | |||||
| 246 | switch(status) { | ||||
| 247 | case DB_NOTFOUND: | ||||
| 248 | error_reason = "not_found"; | ||||
| 249 | break; | ||||
| 250 | case DB_LOCK_DEADLOCK: | ||||
| 251 | error_reason = "deadlock"; | ||||
| 252 | break; | ||||
| 253 | case DB_SECONDARY_BAD: | ||||
| 254 | error_reason = "bad_secondary_index"; | ||||
| 255 | break; | ||||
| 256 | case EINVAL: | ||||
| 257 | error_reason = "bad_flag"; | ||||
| 258 | break; | ||||
| 259 | case EACCES: | ||||
| 260 | error_reason = "readonly"; | ||||
| 261 | break; | ||||
| 262 | case DB_RUNRECOVERY: | ||||
| 263 | error_reason = "run_recovery"; | ||||
| 264 | break; | ||||
| 265 | default: | ||||
| 266 | error_reason = "unknown"; | ||||
| 267 | } | ||||
| 268 | |||||
| 269 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), | ||||
| 270 | ERL_DRV_ATOM, driver_mk_atom(error_reason), | ||||
| 271 | ERL_DRV_TUPLE, 2}; | ||||
| 272 | |||||
| 273 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| 274 | } | ||||
| 275 | } | ||||
| 276 | |||||
| 277 | static void unkown(bdb_drv_t *bdb_drv, ErlIOVec *ev) { | ||||
| 278 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), | ||||
| 279 | ERL_DRV_ATOM, driver_mk_atom("uknown_command"), | ||||
| 280 | ERL_DRV_TUPLE, 2}; | ||||
| 281 | driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); | ||||
| ff218941 » | Matt Williamson | 2009-05-22 | 282 | } | |







