diff options
Diffstat (limited to 'src/dbutil.c')
-rw-r--r-- | src/dbutil.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/dbutil.c b/src/dbutil.c new file mode 100644 index 0000000..b7b44b9 --- /dev/null +++ b/src/dbutil.c @@ -0,0 +1,167 @@ +#include <string.h> +#include <assert.h> +#include <time.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 ret; + struct syrep_id id; + DBT key, data; + + assert(c && c->db_id_meta && name); + + memset(&id, 0, sizeof(id)); + memcpy(&id.name, name, sizeof(struct syrep_name)); + memcpy(&id.md, md, sizeof(struct syrep_md)); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = &id; + key.size = sizeof(struct syrep_id); + + if ((ret = c->db_id_meta->get(c->db_id_meta, NULL, &key, &data, 0))) { + if (ret == DB_NOTFOUND) + return 0; + + c->db_id_meta->err(c->db_id_meta, ret, "id_meta::get"); + return -1; + } + + assert(data.data); + + if (meta) + memcpy(meta, data.data, sizeof(struct syrep_meta)); + + return 1; +} + + +int get_current_name_by_md(struct syrep_db_context *c, const struct syrep_md *md, struct syrep_name *name) { + int ret, f; + struct syrep_meta meta; + DBT key, data; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + 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 == DB_NOTFOUND) + return 0; + + c->db_md_lastname->err(c->db_md_lastname, ret, "md_lastname::get()"); + return -1; + } + + assert(data.data); + + if ((f = get_meta_by_name_md(c, (struct syrep_name*) data.data, md, &meta)) < 0) + return -1; + + if (!f) { + fprintf(stderr, "Database inconsistency\n"); + return -1; + } + + if (meta.last_seen != c->version) + return 0; + + if (name) + memcpy(name, data.data, sizeof(struct syrep_name)); + + return 1; +} + +int get_last_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, 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); + + if ((ret = c->db_name_lastmd->get(c->db_name_lastmd, NULL, &key, &data, 0))) { + if (ret == DB_NOTFOUND) { + return 0; + } + + c->db_name_lastmd->err(c->db_name_lastmd, ret, "name_lastmd::get()"); + return -1; + } + + + assert(data.data); + if (md) + memcpy(md, data.data, sizeof(struct syrep_md)); + + return 1; +} + + +int get_current_md_by_name(struct syrep_db_context *c, const struct syrep_name *name, 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) + return -1; + + if (!f) + return 0; + + if ((f = get_meta_by_name_md(c, name, &lmd, &meta)) < 0) + return -1; + + if (!f) { + fprintf(stderr, "Database inconsistency\n"); + return -1; + } + + if (meta.last_seen != c->version) + return 0; + + memcpy(md, &lmd, sizeof(struct syrep_md)); + return 1; +} + + +uint32_t get_version_timestamp(struct syrep_db_context *c, uint32_t v) { + DBT key, data; + struct syrep_version version; + struct syrep_timestamp *timestamp; + int ret; + + assert(c && c->db_version_timestamp); + + if (v > c->version) + return time(NULL); + + if (v <= 0) + v = 1; + + memset(&version, 0, sizeof(version)); + version.v = v; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = &version; + key.size = sizeof(version); + + if ((ret = c->db_version_timestamp->get(c->db_version_timestamp, NULL, &key, &data, 0))) { + c->db_version_timestamp->err(c->db_version_timestamp, ret, "version_timestamp::get"); + return (uint32_t) -1; + } + + timestamp = (struct syrep_timestamp*) data.data; + assert(timestamp); + + return timestamp->t; +} + |