summaryrefslogtreecommitdiff
path: root/c_src/permdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/permdb.c')
-rw-r--r--c_src/permdb.c139
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));