+static int xdb_open(const char *path)
+{
+ int ret;
+
+ ret = db_create(&database, NULL, 0);
+ if (ret != 0)
+ {
+ AFB_ERROR("Failed to create database: %s.", db_strerror(ret));
+ return -1;
+ }
+
+ ret = database->open(database, NULL, path, NULL, DB_BTREE, DB_CREATE, 0600);
+ if (ret != 0)
+ {
+ AFB_ERROR("Failed to open the '%s' database: %s.", path, db_strerror(ret));
+ database->close(database, 0);
+ return -1;
+ }
+ return 0;
+}
+
+static void xdb_put(struct afb_req req, DBT *key, DBT *data, int replace)
+{
+ int ret;
+
+ ret = database->put(database, NULL, key, data, replace ? 0 : DB_NOOVERWRITE);
+ if (ret == 0)
+ afb_req_success(req, NULL, NULL);
+ else
+ {
+ AFB_ERROR("can't %s key %s with %s", replace ? "replace" : "insert", DATA_STR(*key), DATA_STR(*data));
+ afb_req_fail_f(req, "failed", "%s", db_strerror(ret));
+ }
+}
+
+static void xdb_delete(struct afb_req req, DBT *key)
+{
+ int ret;
+
+ ret = database->del(database, NULL, key, 0);
+ if (ret == 0)
+ afb_req_success_f(req, NULL, NULL);
+ else
+ {
+ AFB_ERROR("can't delete key %s", DATA_STR(*key));
+ afb_req_fail_f(req, "failed", "%s", db_strerror(ret));
+ }
+
+ free(DATA_PTR(key));
+}
+
+static void verb_read(struct afb_req req)
+{
+ DATA key;
+ DATA data;
+ int ret;
+
+ char value[4096];
+
+ struct json_object* result;
+ struct json_object* val;
+
+
+ if (get_key(req, &key))
+ return;
+
+ AFB_INFO("read: key=%s", DATA_STR(key));
+
+ memset(&data, 0, sizeof data);
+ data.data = value;
+ data.ulen = 4096;
+ data.flags = DB_DBT_USERMEM;
+
+ ret = database->get(database, NULL, &key, &data, 0);
+ if (ret == 0)
+ {
+ result = json_object_new_object();
+ val = json_tokener_parse(DATA_STR(data));
+ json_object_object_add(result, "value", val ? val : json_object_new_string(DATA_STR(data)));
+
+ afb_req_success_f(req, result, "db success: read %s=%s.", DATA_STR(key), DATA_STR(data));
+ }
+ else
+ afb_req_fail_f(req, "Failed to read datas.", "db fail: read %s - %s", DATA_STR(key), db_strerror(ret));
+
+ free(DATA_PTR(key));
+}
+
+#endif
+
+// ----- gdbm database -----
+#if USE_GDBM
+
+#include <errno.h>
+#include <gdbm.h>
+
+#define DBFILE "ll-database-binding.dbm"
+#define DATA datum
+#define DATA_SET(k,d,s) do{(k)->dptr=(char*)d;(k)->dsize=(int)s;}while(0)
+#define DATA_PTR(k) ((void*)((k).dptr))
+#define DATA_STR(k) ((char*)((k).dptr))
+#define DATA_SZ(k) ((size_t)((k).dsize))
+
+static GDBM_FILE database;
+
+static void onfatal(const char *text)
+{
+ AFB_ERROR("fatal gdbm message: %s", text);
+}
+
+static int xdb_open(const char *path)
+{
+ database = gdbm_open(path, 512, GDBM_WRCREAT|GDBM_SYNC, 0600, onfatal);
+ if (!database)
+ {
+ AFB_ERROR("Fail to open/create database: %s%s%s", gdbm_errlist[gdbm_errno],
+ gdbm_syserr[gdbm_errno] ? ", " : "",
+ gdbm_syserr[gdbm_errno] ? strerror(errno) : "");
+ return -1;
+
+ }
+ return 0;
+}
+
+static void xdb_put(struct afb_req req, datum *key, datum *data, int replace)
+{
+ int ret;
+
+ ret = gdbm_store(database, *key, *data, replace ? GDBM_REPLACE : GDBM_INSERT);
+ if (ret == 0)
+ afb_req_success(req, NULL, NULL);
+ else
+ {
+ AFB_ERROR("can't %s key %s with %s: %s%s%s",
+ replace ? "replace" : "insert",
+ DATA_STR(*key),
+ DATA_STR(*data),
+ gdbm_errlist[gdbm_errno],
+ gdbm_syserr[gdbm_errno] ? ", " : "",
+ gdbm_syserr[gdbm_errno] ? strerror(errno) : "");
+ afb_req_fail_f(req, "failed", "%s", ret > 0 ? "key already exists" : gdbm_errlist[gdbm_errno]);
+ }
+}
+
+static void xdb_delete(struct afb_req req, datum *key)
+{
+ int ret;
+
+ ret = gdbm_delete(database, *key);
+ if (ret == 0)
+ afb_req_success_f(req, NULL, NULL);
+ else
+ {
+ AFB_ERROR("can't delete key %s: %s%s%s",
+ DATA_STR(*key),
+ gdbm_errlist[gdbm_errno],
+ gdbm_syserr[gdbm_errno] ? ", " : "",
+ gdbm_syserr[gdbm_errno] ? strerror(errno) : "");
+ afb_req_fail_f(req, "failed", "%s", gdbm_errlist[gdbm_errno]);
+ }
+}
+
+static void xdb_get(struct afb_req req, datum *key)
+{
+ struct json_object* obj;
+ datum result;
+
+ result = gdbm_fetch(database, *key);
+ if (result.dptr)
+ {
+ obj = json_object_new_object();
+ json_object_object_add(obj, "value", json_tokener_parse(result.dptr));
+ afb_req_success(req, obj, NULL);
+ free(result.dptr);
+ }
+ else
+ {
+ AFB_ERROR("can't get key %s: %s%s%s",
+ DATA_STR(*key),
+ gdbm_errlist[gdbm_errno],
+ gdbm_syserr[gdbm_errno] ? ", " : "",
+ gdbm_syserr[gdbm_errno] ? strerror(errno) : "");
+ afb_req_fail_f(req, "failed", "%s", gdbm_errlist[gdbm_errno]);
+ }
+}
+#endif