/* Key size */
#define KEY_SIZE (sizeof(uint8_t) + KNOT_DNAME_MAXLEN + sizeof(uint16_t))
-#define db_api(cache) (cache->api)
int kr_cache_open(struct kr_cache *cache, const namedb_api_t *api, void *opts, mm_ctx_t *mm)
{
if (!cache) {
return kr_error(EINVAL);
}
- db_api(cache) = (api == NULL) ? namedb_lmdb_api() : api;
- int ret = db_api(cache)->init(&cache->db, mm, opts);
+ cache->api = (api == NULL) ? namedb_lmdb_api() : api;
+ int ret = cache->api->init(&cache->db, mm, opts);
if (ret != 0) {
return ret;
}
void kr_cache_close(struct kr_cache *cache)
{
if (cache && cache->db) {
- if (db_api(cache)) {
- db_api(cache)->deinit(cache->db);
+ if (cache->api) {
+ cache->api->deinit(cache->db);
}
cache->db = NULL;
}
int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigned flags)
{
- if (!cache || !cache->db || !db_api(cache) || !txn ) {
+ if (!cache || !cache->db || !cache->api || !txn ) {
return kr_error(EINVAL);
}
cache->stats.txn_write += 1;
}
txn->owner = cache;
- return db_api(cache)->txn_begin(cache->db, (namedb_txn_t *)txn, flags);
+ return cache->api->txn_begin(cache->db, (namedb_txn_t *)txn, flags);
}
int kr_cache_txn_commit(struct kr_cache_txn *txn)
{
- if (!txn || !txn->owner) {
+ if (!txn || !txn->owner || !txn->owner->api) {
return kr_error(EINVAL);
}
- int ret = db_api(txn->owner)->txn_commit((namedb_txn_t *)txn);
+ int ret = txn->owner->api->txn_commit((namedb_txn_t *)txn);
if (ret != 0) {
kr_cache_txn_abort(txn);
}
void kr_cache_txn_abort(struct kr_cache_txn *txn)
{
- if (txn && txn->owner) {
- db_api(txn->owner)->txn_abort((namedb_txn_t *)txn);
+ if (txn && txn->owner && txn->owner->api) {
+ txn->owner->api->txn_abort((namedb_txn_t *)txn);
}
}
{
uint8_t keybuf[KEY_SIZE];
size_t key_len = cache_key(keybuf, tag, name, type);
- if (!txn || !txn->owner) {
+ if (!txn || !txn->owner || !txn->owner->api) {
return NULL;
}
/* Look up and return value */
namedb_val_t key = { keybuf, key_len };
namedb_val_t val = { NULL, 0 };
- int ret = db_api(txn->owner)->find((namedb_txn_t *)txn, &key, &val, 0);
+ int ret = txn->owner->api->find((namedb_txn_t *)txn, &key, &val, 0);
if (ret != KNOT_EOK) {
return NULL;
}
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 || !txn->owner || !name || !tag || !header) {
+ if (!txn || !txn->owner || !txn->owner->api || !name || !tag || !header) {
return kr_error(EINVAL);
}
size_t key_len = cache_key(keybuf, tag, name, type);
namedb_val_t key = { keybuf, key_len };
namedb_val_t entry = { NULL, sizeof(*header) + data.len };
+ const namedb_api_t *db_api = txn->owner->api;
/* LMDB can do late write and avoid copy */
txn->owner->stats.insert += 1;
- if (db_api(txn->owner) == namedb_lmdb_api()) {
- int ret = db_api(txn->owner)->insert((namedb_txn_t *)txn, &key, &entry, 0);
+ if (db_api == namedb_lmdb_api()) {
+ int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
if (ret != 0) {
return ret;
}
return kr_error(ENOMEM);
}
entry_write(entry.data, header, data);
- int ret = db_api(txn->owner)->insert((namedb_txn_t *)txn, &key, &entry, 0);
+ int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
free(entry.data);
if (ret != 0) {
return ret;
int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
{
- if (!txn || !txn->owner || !tag || !name ) {
+ if (!txn || !txn->owner || !txn->owner->api || !tag || !name ) {
return kr_error(EINVAL);
}
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(txn->owner)->del((namedb_txn_t *)txn, &key);
+ return txn->owner->api->del((namedb_txn_t *)txn, &key);
}
int kr_cache_clear(struct kr_cache_txn *txn)
{
- if (!txn || !txn->owner ) {
+ if (!txn || !txn->owner || !txn->owner->api) {
return kr_error(EINVAL);
}
- return db_api(txn->owner)->clear((namedb_txn_t *)txn);
+ return txn->owner->api->clear((namedb_txn_t *)txn);
}
int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint32_t *timestamp)
struct kr_cache *owner; /**< Transaction owner */
};
-/** Used storage backend for cache (default LMDB) */
-//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;
-//}
-
/**
* Open/create cache with provided storage options.
* @param cache cache structure to be initialized
static inline void *mm_test_malloc(void *ctx, size_t n)
{ return test_malloc(n); }
static inline void mm_test_free(void *p)
-{ return test_free(p); }
+{ if (p) test_free(p); }
/** Memory context using CMocka allocator. */
static inline void test_mm_ctx_init(mm_ctx_t *mm)
#include <stdlib.h>
#include <time.h>
+#include <dlfcn.h>
mm_ctx_t global_mm;
struct kr_cache_txn global_txn;
#define CACHE_TTL 10
#define CACHE_TIME 0
+int (*original_knot_rdataset_add)(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm) = NULL;
+
+int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm)
+{
+ int err, err_mock;
+ err_mock = (int)mock();
+ if (original_knot_rdataset_add == NULL)
+ {
+ original_knot_rdataset_add = dlsym(RTLD_NEXT,"knot_rdataset_add");
+ assert_non_null (original_knot_rdataset_add);
+ }
+ err = original_knot_rdataset_add(rrs, rr, mm);
+ if (err_mock != KNOT_EOK)
+ err = err_mock;
+ return err;
+}
+
+
/* Simulate init failure */
static int fake_test_init(namedb_t **db_ptr, mm_ctx_t *mm, void *arg)
{
/* test invalid parameters and some api failures */
static void test_fake_invalid (void **state)
{
-// 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);
+ knot_dname_t dname[] = "";
+ 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);
}
{
knot_dname_t dname[] = "";
uint32_t timestamp = CACHE_TIME;
+ struct namedb_lmdb_opts opts;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.path = global_env;
+ opts.mapsize = CACHE_SIZE;
+ assert_int_equal(kr_cache_open(NULL, NULL, &opts, &global_mm),KNOT_EINVAL);
assert_int_not_equal(kr_cache_txn_begin(NULL, &global_txn, 0), 0);
assert_int_not_equal(kr_cache_txn_begin(*state, NULL, 0), 0);
assert_int_not_equal(kr_cache_txn_commit(NULL), 0);
assert_int_equal(ret, KNOT_EOK);
}
+static void test_materialize(void **state)
+{
+ knot_rrset_t output_rr;
+ knot_dname_t * owner_saved = global_rr.owner;
+ bool res_cmp_ok_empty, res_cmp_fail_empty;
+ bool res_cmp_ok, res_cmp_fail;
+
+ global_rr.owner = NULL;
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ output_rr = kr_cache_materialize(&global_rr, 0, &global_mm);
+ res_cmp_ok_empty = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_HEADER);
+ res_cmp_fail_empty = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr,&global_mm);
+ global_rr.owner = owner_saved;
+ assert_true(res_cmp_ok_empty);
+ assert_false(res_cmp_fail_empty);
+
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ will_return (knot_rdataset_add,KNOT_EOK);
+ output_rr = kr_cache_materialize(&global_rr, 0, &global_mm);
+ res_cmp_ok = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr,&global_mm);
+ assert_true(res_cmp_ok);
+
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ will_return (knot_rdataset_add,KNOT_EINVAL);
+ output_rr = kr_cache_materialize(&global_rr, 0, &global_mm);
+ res_cmp_fail = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr,&global_mm);
+ assert_false(res_cmp_fail);
+}
+
/* Test cache read */
static void test_query(void **state)
{
};
const UnitTest tests[] = {
+ /* Invalid input */
+ unit_test(test_invalid),
/* Cache persistence */
group_test_setup(test_open_conventional_api),
unit_test(test_insert_rr),
+ unit_test(test_materialize),
unit_test(test_query),
/* Cache aging */
unit_test(test_query_aged),