From b6c6f1ae082a41a438eb10c9cdfd13b30b41ad93 Mon Sep 17 00:00:00 2001 From: ornse01 Date: Mon, 30 Jan 2012 15:21:51 +0000 Subject: [PATCH] implement abstruct id and control block manager. git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@369 20a0b8eb-f62a-4a12-8fe1-b598822500fb --- src/coll/idtocb.c | 149 +++++++++++++++++ src/coll/idtocb.h | 71 ++++++++ src/coll/test_coll.h | 35 ++++ src/coll/test_idtocb.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 691 insertions(+) create mode 100644 src/coll/idtocb.c create mode 100644 src/coll/idtocb.h create mode 100644 src/coll/test_coll.h create mode 100644 src/coll/test_idtocb.c diff --git a/src/coll/idtocb.c b/src/coll/idtocb.c new file mode 100644 index 0000000..3a541b7 --- /dev/null +++ b/src/coll/idtocb.c @@ -0,0 +1,149 @@ +/* + * idtocb.c + * + * Copyright (c) 2012 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include "idtocb.h" + +#include +#include +#include +#include + +#ifdef BCHAN_CONFIG_DEBUG +# define DP(arg) printf arg +# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err) +#else +# define DP(arg) /**/ +# define DP_ER(msg, err) /**/ +#endif + +struct idtocb_t_ { + W entry_size; + W max_entries; + W max_allocated_id; + UB p[1]; +}; + +EXPORT ID idtocb_allocate(idtocb_t *manager) +{ + W i, n; + idtocb_entry_t *entry; + + for (i = 0; i < manager->max_entries; i++) { + n = (manager->max_allocated_id + 1 + i) % manager->max_entries; + entry = (idtocb_entry_t*)(manager->p + n * manager->entry_size); + if (entry->id < 0) { + entry->id = manager->max_allocated_id + 1 + i; + if (entry->id < 0) { /* for overflow */ + entry->id = n; + } + manager->max_allocated_id = entry->id; + return entry->id; + } + } + + return ER_NOMEM; /* TODO: sub error code */ +} + +EXPORT VOID idtocb_free(idtocb_t *manager, ID id) +{ + W err; + idtocb_entry_t *entry; + + err = idtocb_getcontrolblock(manager, id, &entry); + if (err < 0) { + return; + } + entry->id = -1; +} + +EXPORT W idtocb_getcontrolblock(idtocb_t *manager, ID id, idtocb_entry_t **ptr) +{ + W n; + idtocb_entry_t *entry; + + n = id % manager->max_entries; + entry = (idtocb_entry_t*)(manager->p + n * manager->entry_size); + if (entry->id != id) { + return ER_NOEXS; /* TODO: sub error code */ + } + *ptr = entry; + + return ER_OK; +} + +EXPORT idtocb_t* idtocb_new(W entry_size, W max_entries) +{ + idtocb_t *ret; + W i; + idtocb_entry_t *entry; + + ret = malloc(sizeof(idtocb_t) - sizeof(UB) + sizeof(UB)*entry_size*max_entries); + if (ret == NULL) { + return NULL; + } + ret->entry_size = entry_size; + ret->max_entries = max_entries; + ret->max_allocated_id = 0; + for (i = 0; i < max_entries; i++) { + entry = (idtocb_entry_t*)(ret->p + i * entry_size); + entry->id = -1; + } + + return ret; +} + +EXPORT VOID idtocb_delete(idtocb_t *manager) +{ + free(manager); +} + +/* iterator */ + +EXPORT Bool idtocb_iterator_next(idtocb_iterator_t *iter, idtocb_entry_t **entry) +{ + idtocb_entry_t *e0; + + for (; iter->i < iter->manager->max_entries;) { + e0 = (idtocb_entry_t*)(iter->manager->p + iter->i * iter->manager->entry_size); + iter->i++; + if (e0->id > 0) { + *entry = e0; + return True; + } + } + + return False; +} + +EXPORT VOID idtocb_iterator_initialize(idtocb_iterator_t *iter, idtocb_t *manager) +{ + iter->manager = manager; + iter->i = 0; +} + +EXPORT VOID idtocb_iterator_finalize(idtocb_iterator_t *iter) +{ +} diff --git a/src/coll/idtocb.h b/src/coll/idtocb.h new file mode 100644 index 0000000..0735f5a --- /dev/null +++ b/src/coll/idtocb.h @@ -0,0 +1,71 @@ +/* + * idtocb.h + * + * Copyright (c) 2012 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +/* Vendor name: */ +/* Functionality name: idtocb */ +/* Detail name: */ + +#include + +/* controll block manager */ +/* relation id and block */ + +#ifndef __IDTOCB_H__ +#define __IDTOCB_H__ + +/* Vendor name: */ +/* Functionality name: idtocb */ +/* Detail name: entry */ +struct idtocb_entry_t_ { + ID id; +}; +typedef struct idtocb_entry_t_ idtocb_entry_t; + +/* Vendor name: */ +/* Functionality name: idtocb */ +/* Detail name: */ +typedef struct idtocb_t_ idtocb_t; + +IMPORT idtocb_t* idtocb_new(W entry_size, W max_entries); +IMPORT VOID idtocb_delete(idtocb_t *manager); +IMPORT ID idtocb_allocate(idtocb_t *manager); +IMPORT VOID idtocb_free(idtocb_t *manager, ID id); +IMPORT W idtocb_getcontrolblock(idtocb_t *manager, ID id, idtocb_entry_t **ptr); + +/* Vendor name: */ +/* Functionality name: idtocb */ +/* Detail name: iterator */ +struct idtocb_iterator_t_ { + idtocb_t *manager; + W i; +}; +typedef struct idtocb_iterator_t_ idtocb_iterator_t; + +IMPORT VOID idtocb_iterator_initialize(idtocb_iterator_t *iter, idtocb_t *manager); +IMPORT VOID idtocb_iterator_finalize(idtocb_iterator_t *iter); +IMPORT Bool idtocb_iterator_next(idtocb_iterator_t *iter, idtocb_entry_t **entry); + +#endif diff --git a/src/coll/test_coll.h b/src/coll/test_coll.h new file mode 100644 index 0000000..bf838ec --- /dev/null +++ b/src/coll/test_coll.h @@ -0,0 +1,35 @@ +/* + * test_coll.h + * + * Copyright (c) 2012 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include +#include + +#ifndef __TEST_COLL_H__ +#define __TEST_COLL_H__ + +IMPORT VOID test_idtocb_main(unittest_driver_t *driver); + +#endif diff --git a/src/coll/test_idtocb.c b/src/coll/test_idtocb.c new file mode 100644 index 0000000..4473383 --- /dev/null +++ b/src/coll/test_idtocb.c @@ -0,0 +1,436 @@ +/* + * test_idtocb.c + * + * Copyright (c) 2012 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include "test_coll.h" + +#include "idtocb.h" + +#include +#include +#include +#include +#include + +#include + +typedef struct { + idtocb_entry_t base; + W i; +} test_idtocb_1_t; + +LOCAL UNITTEST_RESULT test_idtocb_1() +{ +#define TEST_IDTOCB_1_TESTSIZE 10 + idtocb_t *cb; + ID ids[TEST_IDTOCB_1_TESTSIZE]; + test_idtocb_1_t *p; + idtocb_iterator_t iter; + W i, j, err; + Bool cont; + UNITTEST_RESULT ret = UNITTEST_RESULT_PASS; + + cb = idtocb_new(sizeof(test_idtocb_1_t), TEST_IDTOCB_1_TESTSIZE); + if (cb == NULL) { + return UNITTEST_RESULT_FAIL; + } + + for (i = 0; i < TEST_IDTOCB_1_TESTSIZE; i++) { + ids[i] = idtocb_allocate(cb); + if (ids[i] < 0) { + printf("idtocb_allocate %d error\n", i); + ret = UNITTEST_RESULT_FAIL; + break; + } + } + + for (i = 0; i < TEST_IDTOCB_1_TESTSIZE; i++) { + err = idtocb_getcontrolblock(cb, ids[i], (idtocb_entry_t**)&p); + if (err < 0) { + printf("idtocb_getcontrolblock error: %08x\n", err); + ret = UNITTEST_RESULT_FAIL; + break; + } + p->i = i; + } + + for (i = 0; i < TEST_IDTOCB_1_TESTSIZE; i++) { + err = idtocb_getcontrolblock(cb, ids[i], (idtocb_entry_t**)&p); + if (err < 0) { + printf("idtocb_getcontrolblock error: %08x\n", err); + ret = UNITTEST_RESULT_FAIL; + break; + } + if (p->i != i) { + printf("idtocb_getcontrolblock result is not expected\n"); + ret = UNITTEST_RESULT_FAIL; + break; + } + } + + i = 0; + idtocb_iterator_initialize(&iter, cb); + for (;;) { + cont = idtocb_iterator_next(&iter, (idtocb_entry_t**)&p); + if (cont == False) { + break; + } + i++; + for (j = 0; j < TEST_IDTOCB_1_TESTSIZE; j++) { + if (p->base.id == ids[j]) { + if (p->i != j) { + printf("idtocb_iterator return value irregal\n"); + ret = UNITTEST_RESULT_FAIL; + break; + } + } + } + } + idtocb_iterator_finalize(&iter); + if (i != TEST_IDTOCB_1_TESTSIZE) { + printf("idtocb_iterator iteration number is not expected:1\n"); + ret = UNITTEST_RESULT_FAIL; + } + + for (i = 0; i < TEST_IDTOCB_1_TESTSIZE; i++) { + idtocb_free(cb, ids[i]); + } + + i = 0; + idtocb_iterator_initialize(&iter, cb); + for (;;) { + cont = idtocb_iterator_next(&iter, (idtocb_entry_t**)&p); + if (cont == False) { + break; + } + i++; + } + idtocb_iterator_finalize(&iter); + if (i != 0) { + printf("idtocb_iterator iteration number is not expected:2\n"); + ret = UNITTEST_RESULT_FAIL; + } + + idtocb_delete(cb); + + return ret; +} + +typedef struct { + idtocb_entry_t base; + W i; + ID id; +} test_idtocb_2_t; + +LOCAL Bool test_idtocb_2_setvalue(idtocb_t *cb, ID *ids, W len) +{ + test_idtocb_2_t *p; + W i, err; + + for (i = 0; i < len; i++) { + if (ids[i] < 0) { + continue; + } + + err = idtocb_getcontrolblock(cb, ids[i], (idtocb_entry_t**)&p); + if (err < 0) { + printf("idtocb_getcontrolblock error: %08x\n", err); + return False; + } + p->i = i; + p->id = p->base.id; + } + + return True; +} + +LOCAL Bool test_idtocb_2_checkvalue(idtocb_t *cb, ID *ids, W len) +{ + test_idtocb_2_t *p; + W i, j, err; + idtocb_iterator_t iter; + Bool cont; + + for (i = 0; i < len; i++) { + if (ids[i] < 0) { + continue; + } + + err = idtocb_getcontrolblock(cb, ids[i], (idtocb_entry_t**)&p); + if (err < 0) { + printf("idtocb_getcontrolblock error: %08x\n", err); + return False; + } + if (p->i != i) { + return False; + } + if (p->id != p->base.id) { + return False; + } + } + + idtocb_iterator_initialize(&iter, cb); + for (;;) { + cont = idtocb_iterator_next(&iter, (idtocb_entry_t**)&p); + if (cont == False) { + break; + } + for (j = 0; j < len; j++) { + if (p->base.id == ids[j]) { + if (p->i != j) { + printf("idtocb_iterator return value irregal: i\n"); + idtocb_iterator_finalize(&iter); + return False; + } + if (p->id != ids[j]) { + printf("idtocb_iterator return value irregal: id\n"); + idtocb_iterator_finalize(&iter); + return False; + } + } + } + } + idtocb_iterator_finalize(&iter); + + return True; +} + +LOCAL Bool test_idtocb_2_checklength(idtocb_t *cb, W expected_len) +{ + test_idtocb_2_t *p; + W i; + idtocb_iterator_t iter; + Bool cont; + + i = 0; + idtocb_iterator_initialize(&iter, cb); + for (;;) { + cont = idtocb_iterator_next(&iter, (idtocb_entry_t**)&p); + if (cont == False) { + break; + } + i++; + } + idtocb_iterator_finalize(&iter); + + if (i != expected_len) { + printf("iteration number is not expected\n"); + return False; + } + return True; +} + +LOCAL UNITTEST_RESULT test_idtocb_2() +{ +#define TEST_IDTOCB_2_TESTSIZE 15 + idtocb_t *cb; + ID ids[TEST_IDTOCB_2_TESTSIZE]; + W i; + Bool is_pass; + UNITTEST_RESULT ret = UNITTEST_RESULT_PASS; + + cb = idtocb_new(sizeof(test_idtocb_2_t), TEST_IDTOCB_2_TESTSIZE); + if (cb == NULL) { + return UNITTEST_RESULT_FAIL; + } + + is_pass = test_idtocb_2_checklength(cb, 0); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + for (i = 0; i < TEST_IDTOCB_2_TESTSIZE; i++) { + ids[i] = idtocb_allocate(cb); + if (ids[i] < 0) { + printf("idtocb_allocate %d error\n", i); + ret = UNITTEST_RESULT_FAIL; + break; + } + } + + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_setvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checkvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + idtocb_free(cb, ids[3]); + ids[3] = -1; + idtocb_free(cb, ids[5]); + ids[5] = -1; + idtocb_free(cb, ids[7]); + ids[7] = -1; + idtocb_free(cb, ids[8]); + ids[8] = -1; + + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_2_TESTSIZE - 4); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checkvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + ids[3] = idtocb_allocate(cb); + if (ids[3] < 0) { + printf("idtocb_allocate %d error\n", 3); + ret = UNITTEST_RESULT_FAIL; + } + ids[7] = idtocb_allocate(cb); + if (ids[7] < 0) { + printf("idtocb_allocate %d error\n", 7); + ret = UNITTEST_RESULT_FAIL; + } + ids[8] = idtocb_allocate(cb); + if (ids[8] < 0) { + printf("idtocb_allocate %d error\n", 8); + ret = UNITTEST_RESULT_FAIL; + } + ids[5] = idtocb_allocate(cb); + if (ids[5] < 0) { + printf("idtocb_allocate %d error\n", 5); + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_setvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checkvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + idtocb_free(cb, ids[1]); + ids[1] = -1; + idtocb_free(cb, ids[2]); + ids[2] = -1; + idtocb_free(cb, ids[9]); + ids[9] = -1; + idtocb_free(cb, ids[6]); + ids[6] = -1; + is_pass = test_idtocb_2_checkvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_2_TESTSIZE - 4); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + ids[2] = idtocb_allocate(cb); + if (ids[2] < 0) { + printf("idtocb_allocate %d error\n", 2); + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_setvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checkvalue(cb, ids, TEST_IDTOCB_2_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_2_TESTSIZE - 3); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + } + + for (i = 0; i < TEST_IDTOCB_2_TESTSIZE; i++) { + idtocb_free(cb, ids[i]); + } + + idtocb_delete(cb); + + return ret; +} + +LOCAL UNITTEST_RESULT test_idtocb_3() +{ +#define TEST_IDTOCB_3_TESTSIZE 15 + idtocb_t *cb; + ID id0, ids[TEST_IDTOCB_3_TESTSIZE]; + W i; + UNITTEST_RESULT ret = UNITTEST_RESULT_PASS; + Bool is_pass; + + cb = idtocb_new(sizeof(test_idtocb_2_t), TEST_IDTOCB_3_TESTSIZE); + if (cb == NULL) { + return UNITTEST_RESULT_FAIL; + } + + for (i = 0; i < TEST_IDTOCB_3_TESTSIZE * 2; i++) { + id0 = idtocb_allocate(cb); + if (i < TEST_IDTOCB_3_TESTSIZE) { + if (id0 < 0) { + printf("idtocb_allocate %d error\n", i); + ret = UNITTEST_RESULT_FAIL; + break; + } + is_pass = test_idtocb_2_checklength(cb, i+1); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + break; + } + } else { + if ((id0 & 0xFFFF0000) != ER_NOMEM) { + printf("idtocb_allocate %d is not error\n", i); + ret = UNITTEST_RESULT_FAIL; + break; + } + is_pass = test_idtocb_2_checklength(cb, TEST_IDTOCB_3_TESTSIZE); + if (is_pass == False) { + ret = UNITTEST_RESULT_FAIL; + break; + } + } + } + + for (i = 0; i < TEST_IDTOCB_3_TESTSIZE; i++) { + idtocb_free(cb, ids[i]); + } + + idtocb_delete(cb); + + return ret; +} + +EXPORT VOID test_idtocb_main(unittest_driver_t *driver) +{ + UNITTEST_DRIVER_REGIST(driver, test_idtocb_1); + UNITTEST_DRIVER_REGIST(driver, test_idtocb_2); + UNITTEST_DRIVER_REGIST(driver, test_idtocb_3); +} -- 2.11.0