#include #include #include #include #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 } } };