diff --git a/src/controller/myconf.c b/src/controller/myconf.c index cf8c6038..b6a18053 100644 --- a/src/controller/myconf.c +++ b/src/controller/myconf.c @@ -13,11 +13,11 @@ int add_config(void* c, char* name, char* value) { - cluster_t* cls = (cluster_t*)c; - xce_config_t var = { .name = name, .value = value }; - xce_config_t* cv = NULL; + cluster_t* cls = (cluster_t*)c; + xce_config_t cvar = { .name = name, .value = value }; + xce_config_t* cv = NULL; - cv = create_obj_by_typename(&(cls->objmgr), "xconfig", &var); + cv = create_obj_by_typename(&(cls->objmgr), "xconfig", &cvar); if (cv == NULL) { return -errno; } diff --git a/src/flake.lock b/src/flake.lock index b575d1af..48a2e0b8 100644 --- a/src/flake.lock +++ b/src/flake.lock @@ -117,11 +117,11 @@ "xbuild": "xbuild" }, "locked": { - "lastModified": 1771035982, - "narHash": "sha256-SC9T1ltnamOCJuWbWeFKjwAG+XauLr1VAoJvzevH2nw=", + "lastModified": 1771555882, + "narHash": "sha256-kNX3V49Gq1b+QUqh0/dgW74qeRg3nE7DC6sWaSCJKsQ=", "ref": "master", - "rev": "c1e40697060a4f689ff9ee70e830eb93a09fa145", - "revCount": 11, + "rev": "3da443cbadd0c15e4708f53d9f5abe2d3a40c2d2", + "revCount": 16, "type": "git", "url": "ssh://forgejo@gitea.shenrs.eu/rshen/librtti" }, diff --git a/src/include/zarray.h b/src/include/zarray.h index c47a6183..dce47558 100644 --- a/src/include/zarray.h +++ b/src/include/zarray.h @@ -3,6 +3,7 @@ #define _ZARRAY_H_ 1 #include +#include #include "mylock.h" #include "xlist.h" @@ -35,4 +36,8 @@ extern void* zarray_get(zarray_t*, int); extern void* zarray_find(zarray_t*, zarray_find_cond_fn_t, ...); extern void zarray_fini(zarray_t*); +typedef void (*xzarray_item_killer_t)(void *); + +extern typeinfo_t xzarray_type; + #endif diff --git a/src/lib/testsuite/test_zarray.c b/src/lib/testsuite/test_zarray.c index 294f4a11..947cc94e 100644 --- a/src/lib/testsuite/test_zarray.c +++ b/src/lib/testsuite/test_zarray.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -5,117 +7,152 @@ #include "zarray.h" -static void test_zarray_create(void) +static void test_zarray_create() { - zarray_t array; + var a = makeInstance(&xzarray_type, 4, NULL); - zarray_init(&array, 8, NULL); + TEST_ASSERT_TRUE(a != NULL); - TEST_ASSERT_EQUAL(0, array.count); - TEST_ASSERT_NULL(array.data); + destroy(a); } -static void test_zarray_store(void) +static void test_zarray_store() { - zarray_t array; - int idx; - char* s1 = "hello"; - char* s2 = NULL; + var a = makeInstance(&xzarray_type, 4, NULL); + int idx; + int rc; + char* p = NULL; - zarray_init(&array, 8, NULL); - idx = zarray_store(&array, (void*)s1); + TEST_ASSERT_TRUE(a != NULL); + + idx = vstore(a, (void*)"Hello"); TEST_ASSERT_TRUE(idx >= 0); - s2 = (char*)zarray_get(&array, idx); - TEST_ASSERT_NOT_NULL(s2); - TEST_ASSERT_EQUAL(0, strcmp(s1, s2)); - zarray_fini(&(array)); -} - -static void test_zarray_del(void) -{ - zarray_t array; - int idx; - char* s1 = "hello"; - - zarray_init(&array, 8, NULL); - idx = zarray_store(&array, (void*)s1); - TEST_ASSERT_TRUE(idx >= 0); - TEST_ASSERT_TRUE(array.count == 1); - zarray_del(&array, idx); - TEST_ASSERT_TRUE(zarray_get(&array, idx) == NULL); - TEST_ASSERT_TRUE(array.count == 0); - - zarray_fini(&array); -} - -static void test_zarray_put(void) -{ - zarray_t array; - int idx; - char* s1 = "hello"; - char* s2 = "test"; - - zarray_init(&array, 8, NULL); - idx = zarray_store(&array, (void*)s1); - TEST_ASSERT_TRUE(idx >= 0); - TEST_ASSERT_TRUE(array.count == 1); - TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL); - - TEST_ASSERT_TRUE(strcmp((char*)zarray_get(&array, idx), s1) == 0); - - zarray_put(&array, idx, (void*)s2); - TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL); - TEST_ASSERT_TRUE(strcmp((char*)zarray_get(&array, idx), s2) == 0); - - zarray_fini(&array); -} - -static void test_zarray_put_get_ex(void) -{ - zarray_t array; - int idxs[2] = { 1, 3 }; - char* s1 = "hello"; - char* s2 = "test"; - void* datas1[2] = { s1, s2 }; - void* datas2[2]; - int rc; - - zarray_init(&array, 8, NULL); - rc = zarray_put_ex(&array, 2, &idxs[0], &datas1[0]); + rc = vget(a, idx, (void**)&p); TEST_ASSERT_TRUE(rc >= 0); - rc = zarray_get_ex(&array, 2, &idxs[0], &datas2[0]); + TEST_ASSERT_TRUE(p != NULL); + + TEST_ASSERT_TRUE(strcmp(p, "Hello") == 0); + + destroy(a); +} + +static void test_zarray_put() +{ + var a = makeInstance(&xzarray_type, 4, NULL); + int rc, idx = 10; + char* p; + + TEST_ASSERT_TRUE(a != NULL); + + rc = vput(a, idx, (void*)"Hello,world"); TEST_ASSERT_TRUE(rc >= 0); - TEST_ASSERT_TRUE((datas1[0] == datas2[0]) && (datas1[1] == datas2[1])); - zarray_fini(&array); + rc = vget(a, idx, (void**)&p); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE(p != NULL); + + TEST_ASSERT_TRUE(strcmp(p, "Hello,world") == 0); + destroy(a); } -static int sum_(void* arg1, void* arg2) +static void test_zarray_put_get_vec() { - int* pv = (int*)arg1; - int x = (int)((long)arg2); + var a = makeInstance(&xzarray_type, 4, NULL); + int idxs[5] = { 1, 3, 5, 7, 9 }; + void* vals[5] = { (void*)(long)2, (void*)(long)4, (void*)(long)6, + (void*)(long)8, (void*)(long)10 }; + void* vals1[5]; + int i; + int rc; - (*pv) += x; - return 0; -} + TEST_ASSERT_TRUE(a != NULL); -static void test_zarray_iter(void) -{ - zarray_t array; - int i; - int val = 0; + rc = vput_vec(a, 5, &idxs[0], (void**)&vals[0]); + TEST_ASSERT_TRUE(rc >= 0); - zarray_init(&array, 10, NULL); - for (i = 0; i < 10; i++) { - zarray_store(&array, (void*)(long)i); + rc = vget_vec(a, 5, &idxs[0], &vals1[0]); + TEST_ASSERT_TRUE(rc >= 0); + + for (i = 0; i < 5; i++) { + TEST_ASSERT_TRUE(vals[i] == vals1[i]); } - zarray_iter(&array, (zarray_iter_fn_t)sum_, &val); + destroy(a); +} - TEST_ASSERT_TRUE(val == 45); +static void test_zarray_iter() +{ + var a = makeInstance(&xzarray_type, 4, NULL); + int idxs[5] = { 1, 3, 5, 7, 9 }; + int vals[5] = { 2, 4, 6, 8, 10 }; + int i; + iterator_t it; + int rc; - zarray_fini(&(array)); + TEST_ASSERT_TRUE(a != NULL); + + for (i = 0; i < 5; i++) { + rc = vput(a, idxs[i], (void*)(long)vals[i]); + TEST_ASSERT_TRUE(rc >= 0); + } + + rc = iter_make(&it, a); + TEST_ASSERT_TRUE(rc == RTTI_ITER_OK); + + i = 0; + while (1) { + void* data; + + rc = iter_next(&it, &data); + if (rc == RTTI_ITER_NO_DATA) { + break; + } + + TEST_ASSERT_TRUE((int)(long)data == vals[i]); + i++; + } + + TEST_ASSERT_TRUE(i == 5); + + iter_destroy(&it); + + destroy(a); +} + +static void my_killer(void* p) +{ + if (p == NULL) { + return; + } + + free(p); +} + +static void test_zarray_clear() +{ + var a = makeInstance(&xzarray_type, 4, my_killer); + char* s = strdup("Hello"); + char* d = NULL; + int idx = 31; + int rc; + + TEST_ASSERT_TRUE(a != NULL); + + rc = vput(a, idx, s); + TEST_ASSERT_TRUE(rc >= 0); + + rc = vget(a, idx, (void**)&d); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE(d == s); + + rc = vclear(a, idx); + TEST_ASSERT_TRUE(rc >= 0); + + rc = vget(a, idx, (void**)&d); + TEST_ASSERT_TRUE(rc == -ENOENT); + + destroy(a); /* no memory leak */ } void test_zarray(void) { @@ -123,8 +160,8 @@ void test_zarray(void) RUN_TEST(test_zarray_create); RUN_TEST(test_zarray_store); - RUN_TEST(test_zarray_del); + RUN_TEST(test_zarray_clear); RUN_TEST(test_zarray_put); + RUN_TEST(test_zarray_put_get_vec); RUN_TEST(test_zarray_iter); - RUN_TEST(test_zarray_put_get_ex); } diff --git a/src/lib/zarray.c b/src/lib/zarray.c index 0fcb47af..cb93bf2b 100644 --- a/src/lib/zarray.c +++ b/src/lib/zarray.c @@ -1,7 +1,10 @@ #include +#include #include #include +#include "bitset.h" +#include "mylock.h" #include "utils.h" #include "zarray.h" @@ -323,8 +326,7 @@ int zarray_get_ex(zarray_t* array, int count, int* idxs, void** data) if (idx >= array->caps) { data[i] = NULL; - } - else { + } else { data[i] = array->data[idx]; } } @@ -347,3 +349,323 @@ void* zarray_get(zarray_t* array, int idx) return datas[0]; } + +typedef struct { + mylock_t lock; +} xzarray_private_t; + +typedef struct { + unsigned int inuse : 1; + void* data; +} xzarray_item_t; + +typedef struct { + int count; + size_t caps; + size_t delta; + int pos; + xzarray_item_t* data; + destroy_fn_t killer; +} xzarray_t; + +static size_t xzarray_datasize(va_list ap) +{ + size_t sz = sizeof(xzarray_t); + + return sz; +} + +static int xzarray_init(meta_obj_t* obj, va_list ap) +{ + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + size_t delta = va_arg(ap, size_t); + destroy_fn_t killer = va_arg(ap, destroy_fn_t); + + if (delta < 1) { + return -EINVAL; + } + + a->count = 0; + a->caps = 0; + a->delta = delta; + a->data = NULL; + a->pos = 0; + a->killer = killer; + + mylock_init(&(priv->lock)); + + return 1; +} + +static void xzarray_destroy(meta_obj_t* obj) +{ + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + int i; + + for (i = 0; i < a->caps; i++) { + if (a->data[i].inuse) { + if (a->killer != NULL) { + a->killer(a->data[i].data); + } + } + } + + FREEUP(a->data); + + mylock_fini(&(priv->lock)); +} + +static int xzarray_ensure_items(xzarray_t* array, int mincap) +{ + int nc, i; + void* p; + + if (mincap < array->caps) { + return 1; + } + + nc = mincap; + if (nc < array->caps + array->delta) { + nc = array->caps + array->delta; + } + + p = (xzarray_item_t*)realloc(array->data, nc * sizeof(xzarray_item_t)); + if (p == NULL) { + return -ENOMEM; + } + + array->data = p; + for (i = array->caps; i < nc; i++) { + array->data[i].inuse = 0; + array->data[i].data = NULL; + } + + /* this will make we can get next free + * location quickly + */ + array->pos = array->caps; + array->caps = nc; + + return 1; +} + +static int xzarray_store(meta_obj_t* obj, void* data) +{ + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + int rc = 0; + + mylock_lock(&(priv->lock)); + rc = xzarray_ensure_items(a, a->count + 1); + if (rc >= 0) { + int idx, i; + + rc = -ENOMEM; + idx = a->pos; + + for (i = 0; i < a->caps; i++) { + if (a->data[idx].inuse == 0) { + a->data[idx].inuse = 1; + a->data[idx].data = data; + a->count++; + + rc = idx; + } + + idx++; + if (idx >= a->caps) { + idx = 0; + } + } + + if (rc >= 0) { + a->pos = (rc + 1) % a->caps; + } + } + mylock_unlock(&(priv->lock)); + return rc; +} + +static int xzarray_get_vec(meta_obj_t* obj, int count, int* idxs, void** data) +{ + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + int i; + int rc = 0; + + if ((count <= 0) || (idxs == NULL) || (data == NULL)) { + return -EINVAL; + } + + mylock_lock(&(priv->lock)); + for (i = 0; i < count; i++) { + int idx = idxs[i]; + + if ((idx >= a->caps) || (a->data[idx].inuse == 0)) { + rc = -ENOENT; + break; + } + } + + if (rc == 0) { + for (i = 0; i < count; i++) { + int idx = idxs[i]; + + data[i] = a->data[idx].data; + } + } + mylock_unlock(&(priv->lock)); + return rc; +} + +static int xzarray_get(meta_obj_t* obj, int idx, void** data) +{ + int idxs[] = { idx }; + + return xzarray_get_vec(obj, 1, (int*)&idxs[0], data); +} + +static int xzarray_put_vec(meta_obj_t* obj, int count, int* idxs, void** data) +{ + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + int i, rc, maxid; + + if ((count < 1) || (idxs == NULL) || (data == NULL)) { + return -EINVAL; + } + + mylock_lock(&(priv->lock)); + maxid = 0; + rc = 0; + + for (i = 0; i < count; i++) { + if (idxs[i] < 0) { + rc = -EINVAL; + break; + } + if (maxid < idxs[i]) { + maxid = idxs[i]; + } + } + + if (rc >= 0) { + rc = xzarray_ensure_items(a, maxid + 1); + } + + if (rc >= 0) { + for (i = 0; i < count; i++) { + int idx = idxs[i]; + + if (a->data[idx].inuse == 1) { + if (a->killer != NULL) { + a->killer(a->data[idx].data); + } + } + + a->data[idx].data = data[i]; + a->data[idx].inuse = 1; + } + } + + mylock_unlock(&(priv->lock)); + + return rc; +} + +static int xzarray_put(meta_obj_t* obj, int idx, void* data) +{ + int idxs[] = { idx }; + void* datas[] = { data }; + return xzarray_put_vec(obj, 1, &(idxs[0]), &(datas[0])); +} + +static int xzarray_clear(meta_obj_t* obj, int idx) +{ + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj); + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj); + int rc = -EINVAL; + + mylock_lock(&(priv->lock)); + if (idx < a->caps) { + rc = 0; + if (a->data[idx].inuse) { + if (a->killer != NULL) { + a->killer(a->data[idx].data); + } + } + + a->data[idx].inuse = 0; + a->data[idx].data = NULL; + a->pos = idx; /* we can find the available idx next time */ + } + mylock_unlock(&(priv->lock)); + + return rc; +} + +static int xzarray_make_iter(iterator_t* iter, va_list ap) +{ + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(iter->obj); + + mylock_lock(&(priv->lock)); + iter->data = (void*)(long)0; + + return RTTI_ITER_OK; +} + +static int xzarray_iter_next(iterator_t* iter, void** data) +{ + xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, iter->obj); + int i; + + for (i = (int)(long)iter->data; i < a->caps; i++) { + if (a->data[i].inuse) { + *data = a->data[i].data; + iter->data = (void*)(long)(i + 1); + + return RTTI_ITER_OK; + } + } + + return RTTI_ITER_NO_DATA; +} + +static int xzarray_iter_reset(iterator_t* iter) +{ + iter->data = (void*)(long)0; + + return RTTI_ITER_OK; +} + +static void xzarray_iter_destroy(iterator_t* iter) +{ + xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(iter->obj); + + mylock_unlock(&(priv->lock)); + + return; +} + +typeinfo_t xzarray_type = { + .name = "xzarray", + .privateSize = sizeof(xzarray_private_t), + .dataSize = (datasize_fn_t)xzarray_datasize, + .init = (obj_init_fn_t)xzarray_init, + .destroy = (obj_destroy_fn_t)xzarray_destroy, + .interfaces + = { .varray = &(intf_varray_t) { .vstore = (vstore_fn_t)xzarray_store, + .vget = (vget_fn_t)xzarray_get, + .vget_vec = (vget_vec_fn_t)xzarray_get_vec, + .vput = (vput_fn_t)xzarray_put, + .vput_vec = (vput_vec_fn_t)xzarray_put_vec, + .vclear = (vclear_fn_t)xzarray_clear }, + .iter + = &(intf_iterator_t) { .make = (iter_make_fn_t)xzarray_make_iter, + .next = (iter_next_fn_t)xzarray_iter_next, + .reset = (iter_reset_fn_t)xzarray_iter_reset, + .destroy + = (iter_destroy_fn_t)xzarray_iter_destroy } } +};