Commit e6e3434e authored by Grigorii Demidov's avatar Grigorii Demidov

lib\cache: removing of global instance of cache storage api

parent 3fc7e424
......@@ -299,7 +299,7 @@ static int cache_backends(lua_State *L)
lua_newtable(L);
for (unsigned i = 0; i < registry->len; ++i) {
struct storage_api *storage = &registry->at[i];
lua_pushboolean(L, storage->api() == kr_cache_storage());
lua_pushboolean(L, storage->api() == engine->resolver.cache.api); /* kr_cache_storage()); */
lua_setfield(L, -2, storage->prefix);
}
return 1;
......@@ -309,7 +309,7 @@ static int cache_backends(lua_State *L)
static int cache_count(lua_State *L)
{
struct engine *engine = engine_luaget(L);
const namedb_api_t *storage = kr_cache_storage();
const namedb_api_t *storage = engine->resolver.cache.api; /* kr_cache_storage(); */
/* Fetch item count */
struct kr_cache_txn txn;
......@@ -390,9 +390,9 @@ static int cache_open(lua_State *L)
kr_cache_close(&engine->resolver.cache);
/* Reopen cache */
kr_cache_storage_set(storage->api);
/* kr_cache_storage_set(storage->api); */
Please register or sign in to reply
void *storage_opts = storage->opts_create(conf, cache_size);
int ret = kr_cache_open(&engine->resolver.cache, storage_opts, engine->pool);
int ret = kr_cache_open(&engine->resolver.cache, storage->api(), storage_opts, engine->pool);
free(storage_opts);
if (ret != 0) {
format_error(L, "can't open cache");
......
......@@ -30,22 +30,15 @@
/* Key size */
#define KEY_SIZE (sizeof(uint8_t) + KNOT_DNAME_MAXLEN + sizeof(uint16_t))
#define db_api(cache) (cache->api)
Please register or sign in to reply
/**
* Used cache storage engine (default LMDB)
* @todo namedb_t should change so it always contains a pointer
* to its API, so it can be carried around instead of keeping it in a
* global variable.
*/
const namedb_api_t *(*kr_cache_storage)(void) = namedb_lmdb_api;
#define db_api kr_cache_storage()
int kr_cache_open(struct kr_cache *cache, void *opts, mm_ctx_t *mm)
int kr_cache_open(struct kr_cache *cache, const namedb_api_t *api, void *opts, mm_ctx_t *mm)
Please register or sign in to reply
{
if (!cache) {
return kr_error(EINVAL);
}
int ret = db_api->init(&cache->db, mm, opts);
db_api(cache) = (api == NULL) ? namedb_lmdb_api() : api;
int ret = db_api(cache)->init(&cache->db, mm, opts);
if (ret != 0) {
return ret;
}
......@@ -56,8 +49,8 @@ int kr_cache_open(struct kr_cache *cache, void *opts, mm_ctx_t *mm)
void kr_cache_close(struct kr_cache *cache)
{
if (cache && cache->db) {
if (db_api) {
db_api->deinit(cache->db);
if (db_api(cache)) {
db_api(cache)->deinit(cache->db);
}
cache->db = NULL;
}
......@@ -65,7 +58,7 @@ void kr_cache_close(struct kr_cache *cache)
int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigned flags)
{
if (!cache || !cache->db || !txn) {
if (!cache || !cache->db || !db_api(cache) || !txn ) {
return kr_error(EINVAL);
}
......@@ -75,16 +68,16 @@ int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigne
cache->stats.txn_write += 1;
}
txn->owner = cache;
return db_api->txn_begin(cache->db, (namedb_txn_t *)txn, flags);
return db_api(cache)->txn_begin(cache->db, (namedb_txn_t *)txn, flags);
}
int kr_cache_txn_commit(struct kr_cache_txn *txn)
{
if (!txn) {
if (!txn || !txn->owner) {
return kr_error(EINVAL);
}
int ret = db_api->txn_commit((namedb_txn_t *)txn);
int ret = db_api(txn->owner)->txn_commit((namedb_txn_t *)txn);
if (ret != 0) {
kr_cache_txn_abort(txn);
}
......@@ -93,8 +86,8 @@ int kr_cache_txn_commit(struct kr_cache_txn *txn)
void kr_cache_txn_abort(struct kr_cache_txn *txn)
{
if (txn) {
db_api->txn_abort((namedb_txn_t *)txn);
if (txn && txn->owner) {
db_api(txn->owner)->txn_abort((namedb_txn_t *)txn);
}
}
......@@ -108,15 +101,18 @@ static size_t cache_key(uint8_t *buf, uint8_t tag, const knot_dname_t *name, uin
return len + sizeof(type);
}
static struct kr_cache_entry *cache_entry(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
static struct kr_cache_entry *cache_entry(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
{
uint8_t keybuf[KEY_SIZE];
size_t key_len = cache_key(keybuf, tag, name, type);
if (!txn || !txn->owner) {
return NULL;
}
/* Look up and return value */
namedb_val_t key = { keybuf, key_len };
namedb_val_t val = { NULL, 0 };
int ret = db_api->find(txn, &key, &val, 0);
int ret = db_api(txn->owner)->find((namedb_txn_t *)txn, &key, &val, 0);
if (ret != KNOT_EOK) {
return NULL;
}
......@@ -131,7 +127,7 @@ struct kr_cache_entry *kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, cons
return NULL;
}
struct kr_cache_entry *entry = cache_entry((namedb_txn_t *)txn, tag, name, type);
struct kr_cache_entry *entry = cache_entry(txn, tag, name, type);
if (!entry) {
txn->owner->stats.miss += 1;
return NULL;
......@@ -170,7 +166,7 @@ static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *heade
int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
struct kr_cache_entry *header, namedb_val_t data)
{
if (!txn || !name || !tag || !header) {
if (!txn || !txn->owner || !name || !tag || !header) {
return kr_error(EINVAL);
}
......@@ -182,8 +178,8 @@ int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n
/* LMDB can do late write and avoid copy */
txn->owner->stats.insert += 1;
if (db_api == namedb_lmdb_api()) {
int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
if (db_api(txn->owner) == namedb_lmdb_api()) {
int ret = db_api(txn->owner)->insert((namedb_txn_t *)txn, &key, &entry, 0);
if (ret != 0) {
return ret;
}
......@@ -195,7 +191,7 @@ int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n
return kr_error(ENOMEM);
}
entry_write(entry.data, header, data);
int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
int ret = db_api(txn->owner)->insert((namedb_txn_t *)txn, &key, &entry, 0);
free(entry.data);
if (ret != 0) {
return ret;
......@@ -207,7 +203,7 @@ int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n
int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
{
if (!txn || !tag || !name ) {
if (!txn || !txn->owner || !tag || !name ) {
return kr_error(EINVAL);
}
......@@ -215,16 +211,16 @@ int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n
size_t key_len = cache_key(keybuf, tag, name, type);
namedb_val_t key = { keybuf, key_len };
txn->owner->stats.delete += 1;
return db_api->del((namedb_txn_t *)txn, &key);
return db_api(txn->owner)->del((namedb_txn_t *)txn, &key);
}
int kr_cache_clear(struct kr_cache_txn *txn)
{
if (!txn) {
if (!txn || !txn->owner ) {
return kr_error(EINVAL);
}
return db_api->clear((namedb_txn_t *)txn);
return db_api(txn->owner)->clear((namedb_txn_t *)txn);
}
int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint32_t *timestamp)
......
......@@ -43,15 +43,16 @@ struct kr_cache_entry
*/
struct kr_cache
{
namedb_t *db; /**< Storage instance */
struct {
uint32_t hit; /**< Number of cache hits */
uint32_t miss; /**< Number of cache misses */
uint32_t insert; /**< Number of insertions */
uint32_t delete; /**< Number of deletions */
uint32_t txn_read; /**< Number of read transactions */
uint32_t txn_write; /**< Number of write transactions */
} stats;
namedb_t *db; /**< Storage instance */
const namedb_api_t *api; /**< Storage engine */
struct {
uint32_t hit; /**< Number of cache hits */
uint32_t miss; /**< Number of cache misses */
uint32_t insert; /**< Number of insertions */
uint32_t delete; /**< Number of deletions */
uint32_t txn_read; /**< Number of read transactions */
uint32_t txn_write; /**< Number of write transactions */
} stats;
};
/** Cache transaction */
......@@ -61,22 +62,23 @@ struct kr_cache_txn {
};
/** Used storage backend for cache (default LMDB) */
extern const namedb_api_t *(*kr_cache_storage)(void);
//extern const namedb_api_t *(*kr_cache_storage)(void);
/** Replace used cache storage backend. */
static inline void kr_cache_storage_set(const namedb_api_t *(*api)(void))
{
kr_cache_storage = api;
}
//static inline void kr_cache_storage_set(const namedb_api_t *(*api)(void))
//{
// kr_cache_storage = api;
//}
Please register or sign in to reply
/**
* Open/create cache with provided storage options.
* @param cache cache structure to be initialized
* @param api Storage engine
* @param storage_opts Storage-specific options (may be NULL for default)
* @param mm Memory context.
* @return 0 or an error code
*/
int kr_cache_open(struct kr_cache *cache, void *opts, mm_ctx_t *mm);
int kr_cache_open(struct kr_cache *cache, const namedb_api_t *api, void *opts, mm_ctx_t *mm);
/**
* Close persistent cache.
......
......@@ -51,7 +51,7 @@ static bool is_expired(struct kr_cache_entry *entry, uint32_t drift)
static char* prune(void *env, struct kr_module *module, const char *args)
{
struct engine *engine = env;
const namedb_api_t *storage = kr_cache_storage();
const namedb_api_t *storage = engine->resolver.cache.api; /* kr_cache_storage(); */
struct kr_cache_txn txn;
int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, 0);
......
......@@ -39,32 +39,32 @@ namedb_val_t global_namedb_data = {namedb_data, NAMEDB_DATA_SIZE};
#define CACHE_TIME 0
/* Simulate init failure */
static int test_init_failure(namedb_t **db_ptr, mm_ctx_t *mm, void *arg)
static int fake_test_init(namedb_t **db_ptr, mm_ctx_t *mm, void *arg)
{
return KNOT_EINVAL;
return mock();
Please register or sign in to reply
}
/* Simulate commit failure */
static int test_commit_failure(namedb_txn_t *txn)
static int fake_test_commit(namedb_txn_t *txn)
{
return KNOT_ESPACE;
}
/* Dummy abort */
static void test_abort(namedb_txn_t *txn)
static void fake_test_abort(namedb_txn_t *txn)
{
return;
}
/* Stub for find */
static int test_find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags)
static int fake_test_find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags)
{
val->data = &global_fake_ce;
return KNOT_EOK;
}
/* Stub for insert */
static int test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags)
static int fake_test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags)
{
int err = KNOT_EINVAL, res_cmp;
struct kr_cache_entry *header = val->data;
......@@ -81,19 +81,51 @@ static int test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, uns
return err;
}
/* Fake api */
static namedb_api_t *fake_namedb_lmdb_api(void)
{
static namedb_api_t fake_api = {
"lmdb_fake_api",
fake_test_init, NULL,
NULL, fake_test_commit, fake_test_abort,
NULL, NULL, fake_test_find, fake_test_ins, NULL,
NULL, NULL, NULL, NULL, NULL, NULL
};
return &fake_api;
}
/* Test cache open */
static void test_open(void **state)
static int test_open(void **state, namedb_api_t *api)
{
static struct kr_cache cache;
struct namedb_lmdb_opts opts;
memset(&opts, 0, sizeof(opts));
opts.path = global_env;
opts.mapsize = CACHE_SIZE;
int ret = kr_cache_open(&cache, &opts, &global_mm);
assert_int_equal(ret, 0);
*state = &cache;
return kr_cache_open(&cache, api, &opts, &global_mm);
}
/* fake api test open */
static void test_open_fake_api(void **state)
{
bool res;
will_return(fake_test_init,KNOT_EOK);
assert_int_equal(test_open(state, fake_namedb_lmdb_api()),KNOT_EOK);
res = (((struct kr_cache *)(*state))->api == fake_namedb_lmdb_api());
assert_true(res);
}
static void test_open_conventional_api(void **state)
{
bool res;
assert_int_equal(test_open(state, NULL),KNOT_EOK);
res = (((struct kr_cache *)(*state))->api == namedb_lmdb_api());
assert_true(res);
}
/* Test cache teardown. */
static void test_close(void **state)
{
......@@ -101,7 +133,6 @@ static void test_close(void **state)
*state = NULL;
}
/* Open transaction */
static struct kr_cache_txn *test_txn_write(void **state)
{
......@@ -118,46 +149,18 @@ static struct kr_cache_txn *test_txn_rdonly(void **state)
return &global_txn;
}
/* Fake api */
static const namedb_api_t *namedb_lmdb_api_fake(void)
/* test invalid parameters and some api failures */
static void test_fake_invalid (void **state)
{
static const namedb_api_t api_fake = {
"lmdb_api_fake",
test_init_failure, NULL,
NULL, test_commit_failure, test_abort,
NULL, NULL, test_find, test_ins, NULL,
NULL, NULL, NULL, NULL, NULL, NULL
};
return &api_fake;
// knot_dname_t dname[] = "";
// assert_null(kr_cache_open(NULL, NULL, NULL));
// assert_int_equal(kr_cache_peek(&global_txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, 0),
// &global_fake_ce);
// assert_int_not_equal(kr_cache_txn_commit(&global_txn), KNOT_EOK);
will_return(fake_test_init,KNOT_EINVAL);
assert_int_equal(test_open(state, fake_namedb_lmdb_api()),KNOT_EINVAL);
}
static void test_failures(void **state)
{
const namedb_api_t *(*kr_cache_storage_saved)(void);
void *ret_cache_peek;
int ret_commit;
int ret_open;
knot_dname_t dname[] = "";
/* Get read transaction */
struct kr_cache_txn *txn = test_txn_rdonly(state);
/* save original api */
kr_cache_storage_saved = kr_cache_storage;
/* fake to simulate failures or constant success */
kr_cache_storage_set(namedb_lmdb_api_fake);
/* call kr_cache_peek() with no time constraint */
ret_cache_peek = kr_cache_peek(txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, 0);
ret_open = kr_cache_open(NULL, NULL, NULL);
ret_commit = kr_cache_txn_commit(txn);
/* restore */
kr_cache_storage_set(kr_cache_storage_saved);
assert_int_equal(ret_cache_peek, &global_fake_ce);
assert_int_not_equal(ret_open, KNOT_EOK);
assert_int_not_equal(ret_commit, KNOT_EOK);
}
/* Test invalid parameters and some api failures. */
static void test_invalid(void **state)
......@@ -175,6 +178,7 @@ static void test_invalid(void **state)
assert_int_not_equal(kr_cache_peek_rr(&global_txn, NULL, NULL), 0);
assert_int_not_equal(kr_cache_insert_rr(&global_txn, NULL, 0), 0);
assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0), 0);
assert_int_equal(kr_cache_insert_rr(&global_txn, &global_rr, 0), 0);
assert_int_not_equal(kr_cache_insert(NULL, KR_CACHE_USER, dname,
KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data), 0);
assert_int_not_equal(kr_cache_insert(&global_txn, 0, dname,
......@@ -190,13 +194,9 @@ static void test_invalid(void **state)
}
/* Test cache write */
static void test_insert(void **state)
static void test_insert_rr(void **state)
{
const namedb_api_t *(*kr_cache_storage_saved)(void);
int i, ret_cache_insert;
knot_dname_t dname[] = "";
test_random_rr(&global_rr, CACHE_TTL);
struct kr_cache_txn *txn = test_txn_write(state);
int ret = kr_cache_insert_rr(txn, &global_rr, CACHE_TIME);
if (ret == KNOT_EOK) {
......@@ -204,26 +204,7 @@ static void test_insert(void **state)
} else {
kr_cache_txn_abort(txn);
}
assert_int_equal(ret, KNOT_EOK);
memset(&global_fake_ce,0xAA,sizeof(global_fake_ce));
srand(time(NULL));
for (i = 0; i < NAMEDB_DATA_SIZE; i += 4)
{
int r = rand();
namedb_data[i] = r;
namedb_data[i + 1] = r >> 8;
namedb_data[i + 2] = r >> 16;
namedb_data[i + 3] = r >> 24;
}
kr_cache_storage_saved = kr_cache_storage;
kr_cache_storage_set(namedb_lmdb_api_fake);
ret_cache_insert = kr_cache_insert(&global_txn, KR_CACHE_USER, dname,
KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data);
kr_cache_storage_set(kr_cache_storage_saved);
assert_int_equal(ret_cache_insert, KNOT_EOK);
}
/* Test cache read */
......@@ -324,16 +305,15 @@ int main(void)
/* Invalid input */
const UnitTest tests_bad[] = {
group_test_setup(test_open),
unit_test(test_invalid),
unit_test(test_failures),
group_test_setup(test_open_fake_api),
unit_test(test_fake_invalid),
group_test_teardown(test_close)
};
const UnitTest tests[] = {
/* Cache persistence */
group_test_setup(test_open),
unit_test(test_insert),
group_test_setup(test_open_conventional_api),
unit_test(test_insert_rr),
unit_test(test_query),
/* Cache aging */
unit_test(test_query_aged),
......
......@@ -71,8 +71,7 @@ static PyObject* init(PyObject* self, PyObject* args)
memset(&opts, 0, sizeof(opts));
opts.path = global_tmpdir;
opts.mapsize = 100 * 4096;
kr_cache_storage_set(namedb_lmdb_api);
int ret = kr_cache_open(&global_context.cache, &opts, &global_mm);
int ret = kr_cache_open(&global_context.cache, NULL, &opts, &global_mm);
assert(ret == 0);
/* No configuration parsing support yet. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment