summaryrefslogtreecommitdiffstats
path: root/src/dbutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbutil.c')
-rw-r--r--src/dbutil.c167
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;
+}
+