Skip to content
Snippets Groups Projects
Commit 69d5531e authored by Marek Vavruša's avatar Marek Vavruša
Browse files

namedb: interactive iterator (lmdb) + updated tests

Not supported in trie because of the API incompatibility.
parent 63515387
No related branches found
No related tags found
No related merge requests found
......@@ -66,11 +66,12 @@ struct namedb_api {
int (*count)(knot_txn_t *txn);
int (*find)(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags);
int (*insert)(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags);
int (*del)(knot_txn_t *txn,knot_val_t *key);
int (*del)(knot_txn_t *txn, knot_val_t *key);
/* Iteration */
knot_iter_t *(*iter_begin)(knot_txn_t *txn, unsigned flags);
knot_iter_t *(*iter_seek)(knot_iter_t *iter, knot_val_t *key, unsigned flags);
knot_iter_t *(*iter_next)(knot_iter_t *iter);
int (*iter_key)(knot_iter_t *iter, knot_val_t *key);
int (*iter_val)(knot_iter_t *iter, knot_val_t *val);
......
......@@ -16,9 +16,10 @@
#ifdef HAVE_LMDB
#include <lmdb.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#include <lmdb.h>
#include "common/namedb/namedb_lmdb.h"
#include "libknot/errcode.h"
......@@ -201,76 +202,35 @@ static int count(knot_txn_t *txn)
return stat.ms_entries;
}
static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
static knot_iter_t *iter_set(knot_iter_t *iter, knot_val_t *key, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { 0, NULL };
int ret = mdb_get(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
if (ret == MDB_NOTFOUND) {
return KNOT_ENOENT;
} else {
return lmdb_error_to_knot(ret);
}
MDB_cursor *cursor = iter;
MDB_cursor_op op = MDB_SET;
switch(flags) {
case KNOT_NAMEDB_NOOP: return cursor;
case KNOT_NAMEDB_FIRST: op = MDB_FIRST; break;
case KNOT_NAMEDB_LAST: op = MDB_LAST; break;
case KNOT_NAMEDB_NEXT: op = MDB_NEXT; break;
case KNOT_NAMEDB_PREV: op = MDB_PREV; break;
case KNOT_NAMEDB_LEQ: assert(0); /* ENOTSUP */ break;
case KNOT_NAMEDB_GEQ: op = MDB_SET_RANGE; break;
default: break;
}
val->data = data.mv_data;
val->len = data.mv_size;
return KNOT_EOK;
}
static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_cursor *cursor = NULL;
int ret = mdb_cursor_open(txn->txn, env->dbi, &cursor);
if (ret != 0) {
return lmdb_error_to_knot(ret);
MDB_val db_key = { 0, NULL };
if (key) {
db_key.mv_data = key->data;
db_key.mv_size = key->len;
}
MDB_val db_key = { key->len, key->data };
MDB_val data = { val->len, val->data };
ret = mdb_cursor_get(cursor, &db_key, NULL, MDB_SET);
int ret = mdb_cursor_get(cursor, key ? &db_key : NULL, NULL, op);
if (ret != 0) {
mdb_cursor_close(cursor);
if (ret == MDB_NOTFOUND) {
// Insert new item
ret = mdb_put(txn->txn, env->dbi, &db_key, &data, 0);
if (ret != 0) {
return lmdb_error_to_knot(ret);
}
return KNOT_EOK;
} else {
return ret;
}
}
ret = mdb_cursor_put(cursor, &db_key, &data, MDB_CURRENT);
mdb_cursor_close(cursor);
if (ret != 0) {
return lmdb_error_to_knot(ret);
}
return KNOT_EOK;
}
static int del(knot_txn_t *txn, knot_val_t *key)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { 0, NULL };
int ret = mdb_del(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
return lmdb_error_to_knot(ret);
return NULL;
}
return KNOT_EOK;
return cursor;
}
static knot_iter_t *iter_begin(knot_txn_t *txn, unsigned flags)
......@@ -291,15 +251,7 @@ static knot_iter_t *iter_begin(knot_txn_t *txn, unsigned flags)
static knot_iter_t *iter_next(knot_iter_t *iter)
{
MDB_cursor *cursor = iter;
int ret = mdb_cursor_get(cursor, NULL, NULL, MDB_NEXT);
if (ret != 0) {
mdb_cursor_close(cursor);
return NULL;
}
return cursor;
return iter_set(iter, NULL, KNOT_NAMEDB_NEXT);
}
static int iter_key(knot_iter_t *iter, knot_val_t *key)
......@@ -342,6 +294,54 @@ static void iter_finish(knot_iter_t *iter)
mdb_cursor_close(cursor);
}
static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
knot_iter_t *iter = iter_begin(txn, KNOT_NAMEDB_NOOP);
if (iter == NULL) {
return KNOT_ERROR;
}
int ret = KNOT_EOK;
if (iter_set(iter, key, flags) == NULL) {
return KNOT_ENOENT;
} else {
ret = iter_val(iter, val);
}
iter_finish(iter);
return ret;
}
static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { val->len, val->data };
int ret = mdb_put(txn->txn, env->dbi, &db_key, &data, 0);
if (ret != 0) {
return lmdb_error_to_knot(ret);
}
return KNOT_EOK;
}
static int del(knot_txn_t *txn, knot_val_t *key)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { 0, NULL };
int ret = mdb_del(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
return lmdb_error_to_knot(ret);
}
return KNOT_EOK;
}
const struct namedb_api *namedb_lmdb_api(void)
{
static const struct namedb_api api = {
......@@ -349,7 +349,7 @@ const struct namedb_api *namedb_lmdb_api(void)
init, deinit,
txn_begin, txn_commit, txn_abort,
count, find, insert, del,
iter_begin, iter_next, iter_key, iter_val, iter_finish
iter_begin, iter_set, iter_next, iter_key, iter_val, iter_finish
};
return &api;
......
......@@ -14,6 +14,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "libknot/errcode.h"
#include "common/namedb/namedb_trie.h"
......@@ -108,6 +110,11 @@ static knot_iter_t *iter_begin(knot_txn_t *txn, unsigned flags)
return hattrie_iter_begin((hattrie_t *)txn->db, is_sorted);
}
static knot_iter_t *iter_seek(knot_iter_t *iter, knot_val_t *key, unsigned flags)
{
assert(0);
return NULL; /* ENOTSUP */
}
static knot_iter_t *iter_next(knot_iter_t *iter)
......@@ -155,7 +162,7 @@ const struct namedb_api *namedb_trie_api(void)
init, deinit,
txn_begin, txn_commit, txn_abort,
count, find, insert, del,
iter_begin, iter_next, iter_key, iter_val, iter_finish
iter_begin, iter_seek, iter_next, iter_key, iter_val, iter_finish
};
return &api;
......
......@@ -124,6 +124,9 @@ static void namedb_test_set(unsigned nkeys, char **keys, char *dbid,
is_int(db_size, iterated, "%s: unsorted iteration", api->name);
/* Sorted iteration. */
char first_key[KEY_MAXLEN] = { '\0' };
char second_key[KEY_MAXLEN] = { '\0' };
char last_key[KEY_MAXLEN] = { '\0' };
char key_buf[KEY_MAXLEN] = {'\0'};
iterated = 0;
it = api->iter_begin(&txn, KNOT_NAMEDB_SORTED);
......@@ -135,12 +138,38 @@ static void namedb_test_set(unsigned nkeys, char **keys, char *dbid,
api->name, key_buf, (const char *)key.data);
break;
}
if (iterated == 1) {
memcpy(second_key, key.data, key.len);
}
} else {
memcpy(first_key, key.data, key.len);
}
++iterated;
memcpy(key_buf, key.data, key.len);
it = api->iter_next(it);
}
is_int(db_size, iterated, "hattrie: sorted iteration");
strcpy(last_key, key_buf);
is_int(db_size, iterated, "%s: sorted iteration", api->name);
api->iter_finish(it);
/* Interactive iteration. */
it = api->iter_begin(&txn, KNOT_NAMEDB_NOOP);
if (it != NULL) { /* If supported. */
/* Get first key. */
it = api->iter_seek(it, NULL, KNOT_NAMEDB_FIRST);
ret = api->iter_key(it, &key);
ok(strcmp(key.data, first_key) == 0, "%s: iter_set(FIRST)", api->name);
it = api->iter_seek(it, &key, KNOT_NAMEDB_NEXT);
ret = api->iter_key(it, &key);
ok(strcmp(key.data, second_key) == 0, "%s: iter_set(NEXT)", api->name);
it = api->iter_seek(it, &key, KNOT_NAMEDB_PREV);
ret = api->iter_key(it, &key);
ok(strcmp(key.data, first_key) == 0, "%s: iter_set(PREV)", api->name);
it = api->iter_seek(it, &key, KNOT_NAMEDB_LAST);
ret = api->iter_key(it, &key);
ok(strcmp(key.data, last_key) == 0, "%s: iter_set(LAST)", api->name);
}
api->iter_finish(it);
api->txn_abort(&txn);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment