int coat_free(coat_t *t, int id) { assert(t); if (cpool_check(&t->pool, id)) { // Free but should have been allocated. return -EBADF; } if (t->oat_delete) { cvector_item_t obj = coat_get(t, id); if (!obj) { // No such object. return -EBADF; } t->oat_delete(t, obj); } cvector_set(&t->table, id, (cvector_item_t) NULL); cpool_free(&t->pool, id); return 0; }
int coat_alloc(coat_t *t, uint32_t arg[COAT_ARGS], cvector_item_t *out_obj) { assert(t); // Allocate new ID. int id = cpool_alloc(&t->pool); if (!id || id == COAT_INVALID_ID) { goto error; } // Potentially expand ID table vector. while (cvector_count(&t->table) <= id) { if (t->oat_expand) { t->oat_expand(&t->table); continue; } // Defaults to adding NULL pointers to fill ID table. cvector_add(&t->table, (cvector_item_t) NULL); } cvector_item_t obj = cvector_get(&t->table, id); if (!obj && t->oat_create) { // Create object structure and store it. obj = t->oat_create(t, id, arg); if (!obj) { goto error; } cvector_set(&t->table, id, obj); } if (out_obj) { (*out_obj) = obj; } return id; error: if (id) cpool_free(&t->pool, id); return COAT_INVALID_ID; }
static int test_cvector(void) { test_start("cvector"); // Src: https://gist.github.com/EmilHernvall/953968 cvector_t v; cvector_init(&v); cvector_add(&v, (cvector_item_t)1); cvector_add(&v, (cvector_item_t)2); cvector_add(&v, (cvector_item_t)3); cvector_add(&v, (cvector_item_t)4); cvector_add(&v, (cvector_item_t)5); test_assert(cvector_count(&v) == (int)5); test_assert(cvector_get(&v, 0) == (cvector_item_t)1); test_assert(cvector_get(&v, 1) == (cvector_item_t)2); test_assert(cvector_get(&v, 2) == (cvector_item_t)3); test_assert(cvector_get(&v, 3) == (cvector_item_t)4); test_assert(cvector_get(&v, 4) == (cvector_item_t)5); cvector_delete(&v, 1); cvector_delete(&v, 3); test_assert(cvector_count(&v) == (int)3); test_assert(cvector_get(&v, 0) == (cvector_item_t)1); test_assert(cvector_get(&v, 1) == (cvector_item_t)3); test_assert(cvector_get(&v, 2) == (cvector_item_t)4); cvector_free(&v); int vcStress = 10000; for (int i = 0; i < vcStress; i++) { int data = ((i << 2) * 0xcafebabe) ^ 0xdeadbeef; cvector_add(&v, (cvector_item_t)data); test_assert(cvector_count(&v) == (int)(i + 1)); test_assert(cvector_get(&v, i) == (cvector_item_t)data); data = (data << 7) ^ 0xbaabaabb; cvector_set(&v, i, (cvector_item_t)data); test_assert(cvector_count(&v) == (int)(i + 1)); test_assert(cvector_get(&v, i) == (cvector_item_t)data); } cvector_free(&v); return test_success(); }
/*bind home_dir and name node, i.e., one name node owns unique home dir*/ EC_BOOL chfsnp_mgr_bind(CHFSNP_MGR *chfsnp_mgr, const CSTRING *path, const UINT32 chfsnp_id) { CSTRING *home_dir; CSTRING *home_dir_old; uint32_t home_dir_pos; ASSERT(cvector_size(CHFSNP_MGR_NP_HOME_DIR_VEC(chfsnp_mgr)) == CHFSNP_MGR_NP_MAX_NUM(chfsnp_mgr)); if(CHFSNP_MGR_NP_MAX_NUM(chfsnp_mgr) <= chfsnp_id) { sys_log(LOGSTDOUT, "error:chfsnp_mgr_bind: max np num %u but chfsnp id %u overflow\n", CHFSNP_MGR_NP_MAX_NUM(chfsnp_mgr), chfsnp_id); return (EC_FALSE); } home_dir_pos = __chfsnp_mgr_get_np_id_of_path(chfsnp_mgr, (uint32_t)cstring_get_len(path), cstring_get_str(path)); if(CHFSNP_ERR_ID != home_dir_pos) { home_dir = cvector_get_no_lock(CHFSNP_MGR_NP_HOME_DIR_VEC(chfsnp_mgr), home_dir_pos); sys_log(LOGSTDOUT, "error:chfsnp_mgr_bind: some dir %s already bound to np %u, thus cannot accept binding %s\n", (char *)cstring_get_str(home_dir), home_dir_pos, (char *)cstring_get_str(path)); return (EC_FALSE); } home_dir = cstring_dup(path); if(NULL_PTR == home_dir) { sys_log(LOGSTDOUT, "error:chfsnp_mgr_bind: dup %s failed\n", (char *)cstring_get_str(path)); return (EC_FALSE); } home_dir_old = (CSTRING *)cvector_set(CHFSNP_MGR_NP_HOME_DIR_VEC(chfsnp_mgr), chfsnp_id, (void *)home_dir); if(NULL_PTR != home_dir_old) { cstring_free(home_dir_old); } return (EC_TRUE); }