552 lines
12 KiB
C
552 lines
12 KiB
C
#include <errno.h>
|
|
#include <rtti.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "htab.h"
|
|
#include "kv.h"
|
|
#include "kvmgr.h"
|
|
#include "mylock.h"
|
|
#include "objmgr.h"
|
|
#include "utils.h"
|
|
#include "xce/types.h"
|
|
#include "zarray.h"
|
|
|
|
#include "controller.capnp.h"
|
|
|
|
int kvmgr_init(kvmgr_t* mgr, hash_key_fn_t keyfn, int nslots, int delta,
|
|
zarray_item_killer_t killer)
|
|
{
|
|
ht_init(&(mgr->htab), nslots, keyfn);
|
|
zarray_init(&(mgr->data), delta, killer);
|
|
mylock_init(&(mgr->lock));
|
|
return 0;
|
|
}
|
|
|
|
void kvmgr_fini(kvmgr_t* mgr)
|
|
{
|
|
ht_fini(&(mgr->htab));
|
|
zarray_fini(&(mgr->data));
|
|
mylock_fini(&(mgr->lock));
|
|
}
|
|
|
|
static void* kvmgr_lock_(kvmgr_t* mgr, void* key, int op)
|
|
{
|
|
hent_t* e = NULL;
|
|
int32_t idx;
|
|
void* ptr;
|
|
|
|
e = ht_get(&(mgr->htab), key);
|
|
if (e == NULL) {
|
|
SET_ERROR(ENOENT);
|
|
return NULL;
|
|
}
|
|
|
|
idx = e->data;
|
|
if (idx < 0) {
|
|
SET_ERROR(ENOENT);
|
|
return NULL;
|
|
}
|
|
|
|
ptr = (void*)zarray_get(&(mgr->data), idx);
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (op == OBJREF_NOP) {
|
|
return ptr;
|
|
}
|
|
|
|
return obj_ref(ptr, op);
|
|
}
|
|
|
|
void* kvmgr_lock(kvmgr_t* mgr, void* key, int op)
|
|
{
|
|
void* ptr = NULL;
|
|
|
|
if (mgr == NULL) {
|
|
SET_ERROR(EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((op != OBJREF_NOP) && (op != OBJREF_READ) && (op != OBJREF_UPDATE)) {
|
|
SET_ERROR(EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
mylock_lock(&(mgr->lock));
|
|
ptr = kvmgr_lock_(mgr, key, op);
|
|
mylock_unlock(&(mgr->lock));
|
|
|
|
return ptr;
|
|
}
|
|
|
|
void* kvmgr_lock_byid(kvmgr_t* mgr, int idx, int op)
|
|
{
|
|
void* ptr = NULL;
|
|
|
|
if (mgr == NULL) {
|
|
SET_ERROR(-EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((idx < 0) || (idx >= mgr->data.caps)) {
|
|
SET_ERROR(-EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((op != OBJREF_NOP) && (op != OBJREF_READ) && (op != OBJREF_UPDATE)) {
|
|
SET_ERROR(-EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
mylock_lock(&(mgr->lock));
|
|
ptr = (void*)zarray_get(&(mgr->data), idx);
|
|
mylock_unlock(&(mgr->lock));
|
|
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (op == OBJREF_NOP) {
|
|
return ptr;
|
|
}
|
|
|
|
return obj_ref(ptr, op);
|
|
}
|
|
|
|
static int32_t kvmgr_add_(kvmgr_t* mgr, void* key, void* p)
|
|
{
|
|
hent_t* e = NULL;
|
|
int idx;
|
|
|
|
e = ht_get(&(mgr->htab), key);
|
|
if (e != NULL) {
|
|
return -EEXIST;
|
|
}
|
|
|
|
idx = zarray_store(&(mgr->data), p);
|
|
if (idx < 0) {
|
|
return idx;
|
|
}
|
|
|
|
e = ht_add(&(mgr->htab), (void*)key);
|
|
if (e == NULL) {
|
|
zarray_del(&(mgr->data), idx);
|
|
return -errno;
|
|
}
|
|
|
|
e->data = idx;
|
|
return idx;
|
|
}
|
|
|
|
int32_t kvmgr_add(kvmgr_t* mgr, void* key, void* p)
|
|
{
|
|
int32_t idx;
|
|
|
|
if ((mgr == NULL) || (p == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
mylock_lock(&(mgr->lock));
|
|
idx = kvmgr_add_(mgr, key, p);
|
|
mylock_unlock(&(mgr->lock));
|
|
|
|
return idx;
|
|
}
|
|
|
|
static int32_t kvmgr_put_(kvmgr_t* mgr, void* key, int idx, void* p)
|
|
{
|
|
hent_t* e = NULL;
|
|
int idx1 = -1;
|
|
|
|
e = ht_get(&(mgr->htab), key);
|
|
if (e != NULL) {
|
|
idx1 = e->data;
|
|
if (idx1 >= 0) {
|
|
zarray_del(&(mgr->data), idx1);
|
|
}
|
|
} else {
|
|
e = ht_add(&(mgr->htab), (void*)key);
|
|
if (e == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
if (idx1 != idx) {
|
|
zarray_del(&(mgr->data), idx);
|
|
}
|
|
|
|
e->data = idx;
|
|
return zarray_put(&(mgr->data), idx, p);
|
|
}
|
|
|
|
int32_t kvmgr_put(kvmgr_t* mgr, void* key, int idx, void* p)
|
|
{
|
|
int rc;
|
|
|
|
if ((mgr == NULL) || (key == NULL) || (p == NULL) || (idx < 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
mylock_lock(&(mgr->lock));
|
|
rc = kvmgr_put_(mgr, key, idx, p);
|
|
mylock_unlock(&(mgr->lock));
|
|
|
|
return rc;
|
|
}
|
|
|
|
static void kvmgr_del_(kvmgr_t* mgr, void* key)
|
|
{
|
|
hent_t* e = NULL;
|
|
int idx;
|
|
|
|
e = ht_get(&(mgr->htab), key);
|
|
if (e == NULL) {
|
|
return;
|
|
}
|
|
|
|
idx = e->data;
|
|
if (idx < 0) {
|
|
return;
|
|
}
|
|
|
|
zarray_del(&(mgr->data), idx);
|
|
|
|
return;
|
|
}
|
|
|
|
void kvmgr_del(kvmgr_t* mgr, void* key)
|
|
{
|
|
if (mgr == NULL) {
|
|
return;
|
|
}
|
|
mylock_lock(&(mgr->lock));
|
|
kvmgr_del_(mgr, key);
|
|
mylock_unlock(&(mgr->lock));
|
|
}
|
|
|
|
int kvmgr_iter(kvmgr_t* mgr, zarray_iter_skip_fn_t skipfn, xlist_t* l,
|
|
void* arg)
|
|
{
|
|
int rc = 0;
|
|
|
|
mylock_lock(&(mgr->lock));
|
|
rc = zarray_iter_ex(&(mgr->data), skipfn, l, arg);
|
|
mylock_unlock(&(mgr->lock));
|
|
|
|
return rc;
|
|
}
|
|
|
|
typedef struct {
|
|
my_rwlock_t lock;
|
|
} xkvmgr_private_t;
|
|
|
|
typedef struct {
|
|
kvmgr_key_type_t key_type;
|
|
unsigned int dynamic : 1;
|
|
uint32_t nslots;
|
|
var kvtab;
|
|
var data;
|
|
} xkvmgr_t;
|
|
|
|
static size_t xkvmgr_datasize(va_list ap)
|
|
{
|
|
size_t sz = sizeof(xkvmgr_t);
|
|
|
|
return sz;
|
|
}
|
|
|
|
static int xkvmgr_init(meta_obj_t* obj, va_list ap)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
kvmgr_params_t* params = va_arg(ap, kvmgr_params_t*);
|
|
kv_params_t kv_params;
|
|
xzarray_params_t data_params;
|
|
|
|
if ((params == NULL)
|
|
|| ((params->key_type != KVMGR_KEY_INT)
|
|
&& (params->key_type != KVMGR_KEY_STRING))
|
|
|| (params->nslots <= 1) || (params->delta < 1)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
kv_params.nslots = params->nslots;
|
|
kv_params.datakiller = NULL;
|
|
|
|
switch (params->key_type) {
|
|
case KVMGR_KEY_INT:
|
|
kv_params.keyops = &int_key_ops;
|
|
break;
|
|
case KVMGR_KEY_STRING:
|
|
kv_params.keyops = &string_key_ops;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
kvm->kvtab = makeInstance(&kvtab_type, &kv_params);
|
|
if (kvm->kvtab == NULL) {
|
|
return -errno;
|
|
}
|
|
|
|
data_params.delta = params->delta;
|
|
data_params.datakiller = params->datakiller;
|
|
kvm->data = makeInstance(&xzarray_type, &data_params);
|
|
if (kvm->data == NULL) {
|
|
destroy(kvm->kvtab);
|
|
|
|
return -errno;
|
|
}
|
|
|
|
kvm->nslots = params->nslots;
|
|
kvm->key_type = params->key_type;
|
|
kvm->dynamic = params->dynamic;
|
|
|
|
if (params->dynamic) {
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
my_rwlock_init(&(priv->lock));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void xkvmgr_destroy(meta_obj_t* obj)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
|
|
if (kvm->data != NULL) {
|
|
destroy(kvm->data);
|
|
}
|
|
|
|
if (kvm->kvtab != NULL) {
|
|
destroy(kvm->kvtab);
|
|
}
|
|
|
|
if (kvm->dynamic) {
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
my_rwlock_fini(&(priv->lock));
|
|
}
|
|
memset(kvm, 0x0, sizeof(*kvm));
|
|
|
|
return;
|
|
}
|
|
|
|
static int xkvmgr_add(meta_obj_t* obj, void* key, void* value)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
int rc;
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
int idx;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_wlock(&(priv->lock));
|
|
}
|
|
|
|
rc = vstore(kvm->data, value);
|
|
|
|
if (rc >= 0) {
|
|
idx = rc;
|
|
|
|
rc = key_add(kvm->kvtab, key, (void*)(long)idx);
|
|
|
|
if (rc >= 0) {
|
|
rc = idx;
|
|
} else {
|
|
vclear(kvm->data, idx);
|
|
}
|
|
}
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xkvmgr_find(meta_obj_t* obj, void* key, void** value)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
int rc;
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
void* data;
|
|
|
|
*value = NULL;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_rlock(&(priv->lock));
|
|
}
|
|
|
|
rc = key_find(kvm->kvtab, key, &data);
|
|
if (rc >= 0) {
|
|
int idx = (int)(long)data;
|
|
|
|
rc = vget(kvm->data, idx, &data);
|
|
if (rc >= 0) {
|
|
*value = data;
|
|
rc = 1;
|
|
}
|
|
}
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xkvmgr_make_iter(iterator_t* iter, va_list ap)
|
|
{
|
|
meta_obj_t* obj = iter->obj;
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
iterator_t* it = calloc(1, sizeof(*it));
|
|
int rc = 0;
|
|
|
|
if (it == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_rlock(&(priv->lock));
|
|
}
|
|
rc = iter_make(it, kvm->data);
|
|
if (rc < 0) {
|
|
FREEUP(it);
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
iter->data = it;
|
|
|
|
return RTTI_ITER_OK;
|
|
}
|
|
|
|
static int xkvmgr_iter_next(iterator_t* iter, void** data)
|
|
{
|
|
iterator_t* it = (iterator_t*)iter->data;
|
|
|
|
return iter_next(it, data);
|
|
}
|
|
|
|
static void xkvmgr_iter_destroy(iterator_t* iter)
|
|
{
|
|
iterator_t* it = iter->data;
|
|
meta_obj_t* obj = iter->obj;
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
|
|
if (it != NULL) {
|
|
iter_destroy(it);
|
|
|
|
FREEUP(it);
|
|
}
|
|
|
|
iter->data = NULL;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int xkvmgr_get_vec(meta_obj_t* obj, int count, int* idxs, void** data)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
int rc = 0;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_rlock(&(priv->lock));
|
|
}
|
|
rc = vget_vec(kvm->data, count, idxs, data);
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xkvmgr_get(meta_obj_t* obj, int idx, void** data)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
int rc = 0;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_rlock(&(priv->lock));
|
|
}
|
|
rc = vget(kvm->data, idx, data);
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xkvmgr_put_vec(meta_obj_t* obj, int count, int* idxs, void** data)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
int rc = 0;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_wlock(&(priv->lock));
|
|
}
|
|
rc = vput_vec(kvm->data, count, idxs, data);
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xkvmgr_put(meta_obj_t* obj, int idx, void* data)
|
|
{
|
|
xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj);
|
|
xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj);
|
|
int rc = 0;
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_wlock(&(priv->lock));
|
|
}
|
|
rc = vput(kvm->data, idx, data);
|
|
|
|
if (kvm->dynamic) {
|
|
my_rwlock_unlock(&(priv->lock));
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
typeinfo_t xkvmgr_type = {
|
|
.name = "xkvmgr",
|
|
.privateSize = sizeof(xkvmgr_private_t),
|
|
.dataSize = (datasize_fn_t)xkvmgr_datasize,
|
|
.init = (obj_init_fn_t)xkvmgr_init,
|
|
.destroy = (obj_destroy_fn_t)xkvmgr_destroy,
|
|
.interfaces
|
|
= { .kv = &(intf_kv_t) { .add_key = (key_add_fn_t)xkvmgr_add,
|
|
.del_key = (key_del_fn_t)NULL,
|
|
.find_key = (key_find_fn_t)xkvmgr_find },
|
|
.varray = &(intf_varray_t) { .vstore = (vstore_fn_t)NULL,
|
|
.vget = (vget_fn_t)xkvmgr_get,
|
|
.vget_vec = (vget_vec_fn_t)xkvmgr_get_vec,
|
|
.vput = (vput_fn_t)xkvmgr_put,
|
|
.vput_vec = (vput_vec_fn_t)xkvmgr_put_vec,
|
|
.vclear = (vclear_fn_t)NULL },
|
|
.iter
|
|
= &(intf_iterator_t) { .make = (iter_make_fn_t)xkvmgr_make_iter,
|
|
.next = (iter_next_fn_t)xkvmgr_iter_next,
|
|
.reset = (iter_reset_fn_t)NULL,
|
|
.destroy
|
|
= (iter_destroy_fn_t)xkvmgr_iter_destroy } }
|
|
};
|