diff options
author | Magnus Ahltorp <map@kth.se> | 2016-02-13 23:52:09 +0100 |
---|---|---|
committer | Linus Nordberg <linus@nordu.net> | 2016-04-25 13:14:11 +0200 |
commit | 710ec7475247064d2420a5ebae602883b81a0f14 (patch) | |
tree | dea403006fccea6cd946b0f1337f1df1e67f880a /c_src/permdb.c | |
parent | 642ac505182749e009934f66b40c32d4033dff38 (diff) |
Convert halfway to uthash
Diffstat (limited to 'c_src/permdb.c')
-rw-r--r-- | c_src/permdb.c | 139 |
1 files changed, 86 insertions, 53 deletions
diff --git a/c_src/permdb.c b/c_src/permdb.c index 7550db4..bdb8f39 100644 --- a/c_src/permdb.c +++ b/c_src/permdb.c @@ -21,6 +21,8 @@ #include "filebuffer.h" #include "util.h" +#include "uthash.h" + #define INDEX_COMMIT_TRAILER_SIZE (sizeof(uint64_t) + SHA256_DIGEST_SIZE + sizeof(index_commit_cookie)) static const int bitsperlevel = 2; @@ -28,7 +30,7 @@ static const int keylen = 32; struct permdb_object { Hashtab *nodecache; - Hashtab *dirtynodes; + struct nodecache *dirtynodes; buffered_file *datafile; buffered_file *indexfile; char *error; @@ -44,7 +46,8 @@ static const node_object errornode = {{NODE_ENTRY_ERROR_NODE, struct nodecache { node_object value; - char key[]; + char *key; + UT_hash_handle hh; }; static int @@ -82,8 +85,8 @@ get_node_from_cache(permdb_object *state, const char *key) #if DEBUG_CACHE fprintf(stderr, "getting cache key %s, ", key); #endif - struct nodecache *lookupnode = malloc(sizeof(struct nodecache) + strlen(key) + 1); - strcpy(lookupnode->key, key); + struct nodecache *lookupnode = malloc(sizeof(struct nodecache)); + lookupnode->key = strdup(key); //fprintf(stderr, "sending in lookup node %p: ", lookupnode); //print_hex(lookupnode, sizeof(struct nodecache) + strlen(key) + 1); struct nodecache *node = (struct nodecache *)hashtabsearch(state->nodecache, lookupnode); @@ -96,7 +99,7 @@ get_node_from_cache(permdb_object *state, const char *key) } #if DEBUG_CACHE fprintf(stderr, "got cache key %s: ", node->key); - print_hex(&node->value, sizeof(struct nodecache)); + print_hex(&node->value, sizeof(struct node_object)); #endif return node->value; } @@ -107,12 +110,15 @@ get_node_from_dirtynodes(permdb_object *state, const char *key) #if DEBUG_CACHE fprintf(stderr, "getting key %s, ", key); #endif - struct nodecache *lookupnode = malloc(sizeof(struct nodecache) + strlen(key) + 1); - strcpy(lookupnode->key, key); + //struct nodecache *lookupnode = malloc(sizeof(struct nodecache) + strlen(key) + 1); + //strcpy(lookupnode->key, key); //fprintf(stderr, "sending in lookup node %p: ", lookupnode); //print_hex(lookupnode, sizeof(struct nodecache) + strlen(key) + 1); - struct nodecache *node = (struct nodecache *)hashtabsearch(state->dirtynodes, lookupnode); - free(lookupnode); + + struct nodecache *node; + HASH_FIND(hh, state->dirtynodes, key, strlen(key), node); + //struct nodecache *node = (struct nodecache *)hashtabsearch(state->dirtynodes, lookupnode); + //free(lookupnode); if (node == NULL) { #if DEBUG_CACHE fprintf(stderr, "found nothing\n"); @@ -121,7 +127,7 @@ get_node_from_dirtynodes(permdb_object *state, const char *key) } #if DEBUG_CACHE fprintf(stderr, "got key %s: ", node->key); - print_hex(&node->value, sizeof(struct nodecache)); + print_hex(&node->value, sizeof(struct node_object)); #endif return node->value; } @@ -133,8 +139,8 @@ put_node_in_cache(permdb_object *state, const char *key, node_object value) fprintf(stderr, "putting cache key %s: ", key); print_hex(&value, sizeof(node_object)); #endif - struct nodecache *node = malloc(sizeof(struct nodecache) + strlen(key) + 1); - strcpy(node->key, key); + struct nodecache *node = malloc(sizeof(struct nodecache)); + node->key = strdup(key); node->value = value; hashtabaddreplace(state->nodecache, node); } @@ -146,10 +152,19 @@ put_node_in_dirtynodes(permdb_object *state, const char *key, node_object value) fprintf(stderr, "putting key %s: ", key); print_hex(&value, sizeof(node_object)); #endif - struct nodecache *node = malloc(sizeof(struct nodecache) + strlen(key) + 1); - strcpy(node->key, key); + struct nodecache *node; + HASH_FIND(hh, state->dirtynodes, key, strlen(key), node); + if (node) { + node->value = value; + return; + } + + node = malloc(sizeof(struct nodecache)); + //strcpy(node->key, key); node->value = value; - hashtabaddreplace(state->dirtynodes, node); + node->key = strdup(key); + HASH_ADD(hh, state->dirtynodes, key[0], strlen(node->key), node); + //hashtabaddreplace(state->dirtynodes, node); } static int @@ -175,8 +190,14 @@ delete_all_nodes_in_cache(permdb_object *state) static void delete_all_dirty_nodes(permdb_object *state) { - hashtabforeach(state->dirtynodes, free_hash_node, NULL); - hashtabcleantab(state->dirtynodes, true_cond, NULL); + struct nodecache *node, *tmp; + HASH_ITER(hh, state->dirtynodes, node, tmp) { + HASH_DEL(state->dirtynodes, node); + free(node->key); + free(node); + } + //hashtabforeach(state->dirtynodes, free_hash_node, NULL); + //hashtabcleantab(state->dirtynodes, true_cond, NULL); } static const uint64_t index_file_cookie = 0xb7e16b02ba8a6d1b; @@ -214,11 +235,12 @@ datafile_add_header(buffered_file *file) void initial_node(permdb_object *state) { - char *key = ""; - struct nodecache *node = malloc(sizeof(struct nodecache) + strlen(key) + 1); - strcpy(node->key, key); - node->value = nullnode; - hashtabaddreplace(state->dirtynodes, node); + //char *key = ""; + put_node_in_dirtynodes(state, "", nullnode); + //struct nodecache *node = malloc(sizeof(struct nodecache) + strlen(key) + 1); + //strcpy(node->key, key); + //node->value = nullnode; + //hashtabaddreplace(state->dirtynodes, node); } int @@ -437,7 +459,7 @@ permdb_alloc(const char *dbpath) free(idxpath); state->nodecache = hashtabnewf(1000000, comparenodes, hashnode, HASHTAB_GROW); - state->dirtynodes = hashtabnewf(1000000, comparenodes, hashnode, HASHTAB_GROW); + state->dirtynodes = NULL;//hashtabnewf(1000000, comparenodes, hashnode, HASHTAB_GROW); state->error = NULL; if (bf_total_length(state->datafile) == 0 && bf_total_length(state->indexfile) == 0) { #if DEBUG_WRITE @@ -477,7 +499,7 @@ permdb_free(permdb_object *state) bf_close(state->indexfile); delete_all_nodes_in_cache(state); delete_all_dirty_nodes(state); - hashtabrelease(state->dirtynodes); + //hashtabrelease(state->dirtynodes); hashtabrelease(state->nodecache); free(state); } @@ -1074,6 +1096,7 @@ struct keylist { int pos; }; +#if 0 static int add_entry_to_keylist(void *ptr, void *arg) { @@ -1084,13 +1107,12 @@ add_entry_to_keylist(void *ptr, void *arg) list->pos++; return 0; } +#endif static int -string_length_comparison(const void *a_v, const void *b_v) { - char * const *a = (char * const *) a_v; - char * const *b = (char * const *) b_v; - size_t a_len = strlen(*a); - size_t b_len = strlen(*b); +string_length_comparison(struct nodecache *a, struct nodecache *b) { + size_t a_len = strlen(a->key); + size_t b_len = strlen(b->key); if (b_len > a_len) { return 1; } else if (b_len == a_len) { @@ -1100,6 +1122,7 @@ string_length_comparison(const void *a_v, const void *b_v) { } } +#if 0 static char ** sorted(permdb_object *state, unsigned int ndirtynodes) { @@ -1124,7 +1147,9 @@ sorted(permdb_object *state, unsigned int ndirtynodes) #endif return keylist.keys; } +#endif +#if 0 static int count_entry(void *ptr, void *arg) { @@ -1132,55 +1157,63 @@ count_entry(void *ptr, void *arg) *flag += 1; return 0; } +#endif int committree(permdb_object *state) { get_node_from_dirtynodes(state, ""); - unsigned int ndirtynodes = 0; - hashtabforeach(state->dirtynodes, count_entry, &ndirtynodes); - if (ndirtynodes == 0) { + //unsigned int ndirtynodes = 0; + //hashtabforeach(state->dirtynodes, count_entry, &ndirtynodes); + //fprintf(stderr, "committree: first node %p\n", state->dirtynodes); + if (state->dirtynodes == NULL) { return 0; } - char **commitlist = sorted(state, ndirtynodes); + HASH_SORT(state->dirtynodes, string_length_comparison); + //fprintf(stderr, "committree: sorted nodes\n"); + //char **commitlist = sorted(state, ndirtynodes); - char *lastobject = commitlist[ndirtynodes - 1]; - if (lastobject[0] != '\0') { + struct nodecache *lastobject = ELMT_FROM_HH(state->dirtynodes->hh.tbl, state->dirtynodes->hh.tbl->tail); + //fprintf(stderr, "committree: last object key: %s\n", lastobject->key); + if (lastobject->key[0] != '\0') { fprintf(stderr, "sorted list doesn't end with root node\n"); - free(commitlist); return -1; } - unsigned int ncommits = ndirtynodes; - unsigned int i; + //unsigned int ncommits = ndirtynodes; +// unsigned int i; #if DEBUG_WRITE fprintf(stderr, "committing %d dirty nodes at offset %llu\n", ncommits, bf_total_length(state->indexfile)); #endif - for (i = 0; i < ncommits; i++) { - get_node_from_dirtynodes(state, ""); - char *key = commitlist[i]; - node_object node = get_node_from_dirtynodes(state, key); - assert(get_entry_in_node(node, 0) != NODE_ENTRY_DIRTY_NODE); - assert(get_entry_in_node(node, 1) != NODE_ENTRY_DIRTY_NODE); - assert(get_entry_in_node(node, 2) != NODE_ENTRY_DIRTY_NODE); - assert(get_entry_in_node(node, 3) != NODE_ENTRY_DIRTY_NODE); - node_offset offset = writenode(state, node, key); - size_t keylength = strlen(key); + struct nodecache *node, *tmp; + HASH_ITER(hh, state->dirtynodes, node, tmp) { +#if 0 + fprintf(stderr, "committree: iterate node %s: ", node->key); + fprintf(stderr, "%016llx %016llx %016llx %016llx\n", + node->value.data[0], + node->value.data[1], + node->value.data[2], + node->value.data[3]); +#endif + assert(get_entry_in_node(node->value, 0) != NODE_ENTRY_DIRTY_NODE); + assert(get_entry_in_node(node->value, 1) != NODE_ENTRY_DIRTY_NODE); + assert(get_entry_in_node(node->value, 2) != NODE_ENTRY_DIRTY_NODE); + assert(get_entry_in_node(node->value, 3) != NODE_ENTRY_DIRTY_NODE); + node_offset offset = writenode(state, node->value, node->key); + size_t keylength = strlen(node->key); if (keylength != 0) { - get_node_from_dirtynodes(state, ""); - char *parent = strdup(key); + char *parent = strdup(node->key); parent[keylength - 1] = '\0'; - unsigned int entrynumber = (unsigned int) (key[keylength - 1] - '0'); + unsigned int entrynumber = (unsigned int) (node->key[keylength - 1] - '0'); node_object parentnode = get_node_from_dirtynodes(state, parent); overwriteentry(&parentnode, entrynumber, offset); put_node_in_dirtynodes(state, parent, parentnode); free(parent); } - free(key); } - free(commitlist); + //free(commitlist); #if DEBUG_WRITE fprintf(stderr, "writing data commit trailer at offset %llu\n", bf_total_length(state->datafile)); |