int db_walk(void *dbh, int (*walk_func)(char *key, void *data, int len)) { DBT key, data; DBC *dbc; int rc = 0; GET_DB(dbh); if (!walk_func) return -EINVAL; if ((rc = db->cursor(db, NULL, &dbc, 0))) { db->close(db, 0); return rc; } memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); while (dbc->c_get(dbc, &key, &data, DB_NEXT) == 0) if ((rc = walk_func(key.data, data.data, data.size))) break; dbc->c_close(dbc); return rc; }
int db_close(void *dbh) { GET_DB(dbh); if (db == global_db) db_close_global(); else db->close(db, 0); return 0; }
int db_del(void *dbh, char *keystr) { DBT key; GET_DB(dbh); memset(&key, 0, sizeof(key)); key.data = keystr; key.size = strlen(key.data) + 1; return db->del(db, NULL, &key, 0); }
/* Returns 0 on success */ int db_put(void *dbh, char *keystr, void *val, int len, unsigned flags) { DBT key, data; GET_DB(dbh); memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.data = keystr; key.size = strlen(keystr) + 1; if (len) { data.data = val; data.size = len; } return db->put(db, NULL, &key, &data, flags); }
/* Returns val len on success */ int db_get(void *dbh, char *keystr, void *val, int len) { DBT key, data; GET_DB(dbh); memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.data = keystr; key.size = strlen(keystr) + 1; int rc = db->get(db, NULL, &key, &data, 0); if (rc) return rc < 0 ? rc : -rc; if (len > data.size) len = data.size; memcpy(val, data.data, len); return len; }
/** * Called by kernel for each new netlink socket message receieved */ static void kr_nl_recv(struct sk_buff *skb) { struct nlmsghdr * nlh = (struct nlmsghdr *)skb->data; kr_dataptr data = nlmsg_data(nlh); int size = nlmsg_len(nlh); int pid = nlh->nlmsg_pid; int seq = nlh->nlmsg_seq; KrDb* db = NULL; /* used differently by all switch cases */ KrOutbuf outbuf = kr_outbuf(sizeof(u64)); /* helper macros for reading message data */ #define NEXT_U8() (*(u8* )((data += sizeof(u8)) - sizeof(u8))) #define NEXT_U64() (*(u64*)((data += sizeof(u64)) - sizeof(u64))) #define NEXT_PTR(len) ((data += len) - len) #define GET_DB() do { \ db = kr_db_from_id(NEXT_U8()); \ if (!db) { \ printk(KERN_INFO "GET_DB WITH INVALID ID\n"); \ return; \ } \ } while (0) /* -------------- command type switch */ switch (nlh->nlmsg_type) { //-------------------------------------------------- // Command: OPEN //-------------------------------------------------- case KR_COMMAND_OPEN: { const char * path = (const char *)data; printk(KERN_INFO "KR_COMMAND_OPEN - \"%s\"\n", path); kr_db_open(&db, path); kr_nl_send(pid, seq, KR_COMMAND_OPEN, &db->id, sizeof(db->id)); break; } //-------------------------------------------------- // Command: Close //-------------------------------------------------- case KR_COMMAND_CLOSE: { GET_DB(); //kr_db_close(db); break; } //-------------------------------------------------- // Command: PUT //-------------------------------------------------- case KR_COMMAND_PUT: { KrSlice key, val; GET_DB(); key.size = NEXT_U64(); key.data = NEXT_PTR(key.size); val.size = NEXT_U64(); val.data = NEXT_PTR(val.size); kr_db_put(db, key, val); break; } //-------------------------------------------------- // Command: GET //-------------------------------------------------- case KR_COMMAND_GET: { u64 size; KrSlice key; GET_DB(); key.size = NEXT_U64(); key.data = NEXT_PTR(key.size); kr_db_get(db, key, &outbuf, &size); *(u64 *)outbuf.data = size; kr_nl_send(pid, seq, KR_COMMAND_GET, outbuf.data, sizeof(u64) + size); break; } //-------------------------------------------------- // Command: BENCH //-------------------------------------------------- case KR_COMMAND_BENCH: { GET_DB(); printk(KERN_INFO "Running kr_bench(\"%s\")...\n", db->path); kr_bench(db); printk(KERN_INFO "...done.\n"); } case KR_COMMAND_NOP: default: printk(KERN_INFO "Received unknown command\n"); break; } }