diff options
Diffstat (limited to 'src/dbutil.c')
-rw-r--r-- | src/dbutil.c | 180 |
1 files changed, 163 insertions, 17 deletions
diff --git a/src/dbutil.c b/src/dbutil.c index 407593a..535b665 100644 --- a/src/dbutil.c +++ b/src/dbutil.c @@ -22,18 +22,20 @@ #include <assert.h> #include <time.h> +#include <zlib.h> + #include "dbutil.h" #include "util.h" -int get_meta_by_name_md(struct syrep_db_context *c, const struct syrep_name*name, const struct syrep_md *md, struct syrep_meta *meta) { +int get_meta_by_nrecno_md(struct syrep_db_context *c, const struct syrep_nrecno*nrecno, const struct syrep_md *md, struct syrep_meta *meta) { int ret; struct syrep_id id; DBT key, data; - assert(c && c->db_id_meta && name); + assert(c && c->db_id_meta && nrecno); memset(&id, 0, sizeof(id)); - memcpy(&id.name, name, sizeof(struct syrep_name)); + memcpy(&id.nrecno, nrecno, sizeof(struct syrep_nrecno)); memcpy(&id.md, md, sizeof(struct syrep_md)); memset(&key, 0, sizeof(key)); @@ -59,7 +61,7 @@ int get_meta_by_name_md(struct syrep_db_context *c, const struct syrep_name*name } -int get_current_name_by_md(struct syrep_db_context *c, const struct syrep_md *md, struct syrep_name *name) { +int get_current_nrecno_by_md(struct syrep_db_context *c, const struct syrep_md *md, struct syrep_nrecno *nrecno) { int ret, f; struct syrep_meta meta; DBT key, data; @@ -69,17 +71,17 @@ int get_current_name_by_md(struct syrep_db_context *c, const struct syrep_md *md key.data = (void*) md; key.size = sizeof(struct syrep_md); - if ((ret = c->db_md_lastname->get(c->db_md_lastname, NULL, &key, &data, 0))) { + if ((ret = c->db_md_lastnrecno->get(c->db_md_lastnrecno, NULL, &key, &data, 0))) { if (ret == DB_NOTFOUND) return 0; - c->db_md_lastname->err(c->db_md_lastname, ret, "md_lastname::get()"); + c->db_md_lastnrecno->err(c->db_md_lastnrecno, ret, "md_lastnrecno::get()"); return -1; } assert(data.data); - if ((f = get_meta_by_name_md(c, (struct syrep_name*) data.data, md, &meta)) < 0) + if ((f = get_meta_by_nrecno_md(c, (struct syrep_nrecno*) data.data, md, &meta)) < 0) return -1; if (!f) { @@ -90,28 +92,28 @@ int get_current_name_by_md(struct syrep_db_context *c, const struct syrep_md *md if (meta.last_seen != c->version) return 0; - if (name) - memcpy(name, data.data, sizeof(struct syrep_name)); + if (nrecno) + memcpy(nrecno, data.data, sizeof(struct syrep_nrecno)); return 1; } -int get_last_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, struct syrep_md *md) { +int get_last_md_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, struct syrep_md *md) { int ret; DBT key, data; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - key.data = (void*) name; - key.size = sizeof(struct syrep_name); + key.data = (void*) nrecno; + key.size = sizeof(struct syrep_nrecno); - if ((ret = c->db_name_lastmd->get(c->db_name_lastmd, NULL, &key, &data, 0))) { + if ((ret = c->db_nrecno_lastmd->get(c->db_nrecno_lastmd, NULL, &key, &data, 0))) { if (ret == DB_NOTFOUND) { return 0; } - c->db_name_lastmd->err(c->db_name_lastmd, ret, "name_lastmd::get()"); + c->db_nrecno_lastmd->err(c->db_nrecno_lastmd, ret, "nrecno_lastmd::get()"); return -1; } @@ -124,18 +126,18 @@ int get_last_md_by_name(struct syrep_db_context *c, const struct syrep_name *nam } -int get_current_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, struct syrep_md *md) { +int get_current_md_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, struct syrep_md *md) { struct syrep_md lmd; struct syrep_meta meta; int f; - if ((f = get_last_md_by_name(c, name, &lmd)) < 0) + if ((f = get_last_md_by_nrecno(c, nrecno, &lmd)) < 0) return -1; if (!f) return 0; - if ((f = get_meta_by_name_md(c, name, &lmd, &meta)) < 0) + if ((f = get_meta_by_nrecno_md(c, nrecno, &lmd, &meta)) < 0) return -1; if (!f) { @@ -185,3 +187,147 @@ uint32_t get_version_timestamp(struct syrep_db_context *c, uint32_t v) { return timestamp->t; } +int get_name_by_nrecno(struct syrep_db_context *c, const struct syrep_nrecno *nrecno, struct syrep_name *name) { + DBT key, data; + int ret; + + assert(c && nrecno); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = (void*) &nrecno->recno; + key.size = sizeof(nrecno->recno); + + if ((ret = c->db_nrecno_name->get(c->db_nrecno_name, NULL, &key, &data, 0))) { + if (ret == DB_NOTFOUND) + return 0; + + c->db_nrecno_name->err(c->db_nrecno_name, ret, "nrecno_name::get"); + return -1; + } + + if (name) { + memset(name, 0, sizeof(struct syrep_name)); + strncpy(name->path, data.data, MIN(PATH_MAX, data.size)); + } + + return 1; +} + +static uint32_t csum_name(const struct syrep_name *name) { + uint32_t a; + + assert(name); + + a = adler32(0, NULL, 0); + a = adler32(a, name->path, strlen(name->path)); + + return a; +} + +int get_nrecno_by_name(struct syrep_db_context *c, const struct syrep_name *rname, struct syrep_nrecno *rnrecno, int create) { + struct syrep_nhash nhash; + DBT key, data; + DBC *cursor = NULL; + int r = -1, ret; + + assert(c && rname); + + if ((ret = c->db_nhash_nrecno->cursor(c->db_nhash_nrecno, NULL, &cursor, 0)) != 0) { + c->db_nhash_nrecno->err(c->db_nhash_nrecno, ret, "nhash_nrecno"); + goto finish; + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + nhash.hash = csum_name(rname); + key.data = &nhash; + key.size = sizeof(nhash); + + ret = cursor->c_get(cursor, &key, &data, DB_SET); + + for(;;) { + struct syrep_nrecno nrecno; + struct syrep_name name; + int f; + + if (ret != 0) { + if (ret == DB_NOTFOUND) { + + r = 0; + goto finish; + } + + c->db_nhash_nrecno->err(c->db_nhash_nrecno, ret, "nhash_nrecno::get"); + goto finish; + } + + memcpy(&nrecno, data.data, sizeof(nrecno)); + + if ((f = get_name_by_nrecno(c, &nrecno, &name)) < 0) + goto finish; + + if (f && !strcmp(name.path, rname->path)) { + if (rnrecno) + memcpy(rnrecno, &nrecno, sizeof(struct syrep_nrecno)); + + r = 1; + goto finish; + } + + ret = cursor->c_get(cursor, &key, &data, DB_NEXT); + } + +finish: + + if (cursor) + cursor->c_close(cursor); + + if (!r && create) + r = new_name(c, rname, rnrecno) < 0 ? -1 : 1; + + return r; +} + +int new_name(struct syrep_db_context *c, const struct syrep_name *name, struct syrep_nrecno *rnrecno) { + struct syrep_nhash nhash; + struct syrep_nrecno nrecno; + int ret; + DBT key, data; + assert(c && name); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + data.data = (void*) name->path; + data.size = strlen(name->path); + + if ((ret = c->db_nrecno_name->put(c->db_nrecno_name, NULL, &key, &data, DB_APPEND))) { + c->db_nrecno_name->err(c->db_nrecno_name, ret, "nrecno_name::put"); + return -1; + } + + nrecno.recno = *((db_recno_t*) data.data); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + nhash.hash = csum_name(name); + key.data = &nhash; + key.size = sizeof(nhash); + + data.data = &nrecno; + data.size = sizeof(nrecno); + + if ((ret = c->db_nhash_nrecno->put(c->db_nhash_nrecno, NULL, &key, &data, 0))) { + c->db_nhash_nrecno->err(c->db_nhash_nrecno, ret, "nhash_nrecno::put"); + return -1; + } + + if (rnrecno) + memcpy(rnrecno, &nrecno, sizeof(struct syrep_nrecno)); + + return 0; +} |