diff --git a/src/include/idgen.h b/src/include/idgen.h new file mode 100644 index 00000000..d03874f1 --- /dev/null +++ b/src/include/idgen.h @@ -0,0 +1,23 @@ +#if !defined(_IDGEN_H_) + +#define _IDGEN_H_ 1 + +#include "config.h" + +#include +#include +#include + +#include "mylock.h" + +typedef struct { + mylock_t lock; + time_t timestamp; + uint32_t sequence; +} idgen_ctx_t; + +extern int idgen_ctx_init(idgen_ctx_t*); +extern int idgen(idgen_ctx_t*, size_t, size_t, size_t, uint64_t*); +extern void idgen_ctx_fini(idgen_ctx_t*); + +#endif diff --git a/src/include/utils.h b/src/include/utils.h index 0483c785..973324a5 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -20,6 +20,8 @@ | (((uint64_t)timestamp) << TIMESTAMP_SHIFT) \ | (((uint64_t)tag) << TAG_SHIFT) | sequence) +#define ROUNDUP(v, bits) (((v) + UMAX_BITS(bits)) & ~UMAX_BITS(bits)) + #define xce_use(x) (void)(x) #define float_near_zero (0.000001) diff --git a/src/lib/idgen.c b/src/lib/idgen.c new file mode 100644 index 00000000..306d0ab5 --- /dev/null +++ b/src/lib/idgen.c @@ -0,0 +1,70 @@ +#include +#include + +#include "idgen.h" +#include "mylock.h" +#include "utils.h" +#include "xce/errnox.h" + +int idgen_ctx_init(idgen_ctx_t* ctx) +{ + if (ctx == NULL) { + return -EINVAL; + } + + mylock_init(&(ctx->lock)); + ctx->timestamp = time(NULL); + ctx->sequence = 0; + + return 0; +} + +int idgen(idgen_ctx_t* ctx, size_t clusterId, size_t apiserverId, + size_t arraySize, uint64_t* pidx) +{ + time_t now; + uint64_t idx; + uint64_t ts, tag, seq; + + if ((ctx == NULL) || (clusterId > MAX_CLUSTER_ID) + || (apiserverId > MAX_APISERVER_ID) || (arraySize < 1) + || (arraySize > MAX_ARRAY_IDX + 1) || (pidx == NULL)) { + return -EINVAL; + } + + mylock_lock(&(ctx->lock)); + now = time(NULL); + + if (now != ctx->timestamp) { + ctx->timestamp = now; + ctx->sequence = 0; + } + + ts = ctx->timestamp; + + if (arraySize == 1) { + /* non array job */ + tag = 0x0; + seq = ctx->sequence; + ctx->sequence++; + } else { + tag = TAG_JOB_ARRAY; + seq = ROUNDUP(ctx->sequence, N_ARRAY_IDX_BITS); + ctx->sequence = ROUNDUP(seq + 1, N_ARRAY_IDX_BITS); + } + mylock_unlock(&(ctx->lock)); + + idx = MAKE_JOBID(clusterId, apiserverId, ts, tag, seq); + + *pidx = idx; + return arraySize; +} + +void idgen_ctx_fini(idgen_ctx_t* ctx) +{ + if (ctx == NULL) { + return; + } + + mylock_fini(&(ctx->lock)); +} diff --git a/src/lib/meson.build b/src/lib/meson.build index 42000ad3..846f7832 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -26,7 +26,8 @@ libxce_src = [ gen_srcs[0], 'xlist.c', 'xstring.c', 'zarray.c', - 'wrap.c' + 'wrap.c', + 'idgen.c' ] incdir = include_directories('../include') @@ -58,7 +59,8 @@ libxce_test_src = ['testsuite/test.c', 'testsuite/test_utils.c', 'testsuite/test_xstring.c', 'testsuite/test_zarray.c', - 'testsuite/test_config.c' + 'testsuite/test_config.c', + 'testsuite/test_idgen.c' ] libxce_test_deps = [libxce_deps, unity_dep, libxce_dep] diff --git a/src/lib/testsuite/test.c b/src/lib/testsuite/test.c index 3c737961..30258417 100644 --- a/src/lib/testsuite/test.c +++ b/src/lib/testsuite/test.c @@ -11,6 +11,7 @@ extern void test_ht_int(void); extern void test_error(void); extern void test_utils(void); extern void test_config(void); +extern void test_idgen(void); void setUp(void) { return; } @@ -20,6 +21,7 @@ int main(int argc, char* argv[]) { UNITY_BEGIN(); test_config(); + test_idgen(); test_ht_string(); test_ht_int(); test_zarray(); diff --git a/src/lib/testsuite/test_idgen.c b/src/lib/testsuite/test_idgen.c new file mode 100644 index 00000000..2c7ab03a --- /dev/null +++ b/src/lib/testsuite/test_idgen.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "idgen.h" +#include + +static void test_idgen_invalid(void) +{ + idgen_ctx_t ctx; + uint64_t idx; + + // TEST_ASSERT_TRUE(0 == 1); + TEST_ASSERT_TRUE(idgen_ctx_init(NULL) == -EINVAL); + + idgen_ctx_init(&ctx); + + TEST_ASSERT_TRUE(idgen(&ctx, 128, 3, 1, &idx) == -EINVAL); + TEST_ASSERT_TRUE(idgen(&ctx, 32, 128, 1, &idx) == -EINVAL); + TEST_ASSERT_TRUE(idgen(&ctx, 32, 3, 0, &idx) == -EINVAL); + TEST_ASSERT_TRUE(idgen(&ctx, 32, 3, 65536, &idx) == -EINVAL); + TEST_ASSERT_TRUE(idgen(&ctx, 32, 3, 128, NULL) == -EINVAL); + + idgen_ctx_fini(&ctx); +} + +static void test_idgen1(void) +{ + idgen_ctx_t ctx; + uint64_t idx; + int rc, i; + + rc = idgen_ctx_init(&ctx); + TEST_ASSERT_TRUE(rc >= 0); + + for (i = 0; i < 20; i++) { + rc = idgen(&ctx, 0x0, 0x0, 1, &idx); + TEST_ASSERT_TRUE(rc >= 0); + printf("\tidx = %lx\n", idx); + } + + idgen_ctx_fini(&ctx); +} + +static void test_idgen_array(void) +{ + idgen_ctx_t ctx; + uint64_t idx; + int rc, i; + + rc = idgen_ctx_init(&ctx); + TEST_ASSERT_TRUE(rc >= 0); + + for (i = 0; i < 5; i++) { + int k; + + for (k = 0; k < 5; k++) { + rc = idgen(&ctx, 0x0, 0x0, i + 1, &idx); + TEST_ASSERT_TRUE(rc >= 0); + if ( i >= 1) { + TEST_ASSERT_TRUE((idx & MAX_ARRAY_IDX) == 0); + } + printf("\tidx = %lx\n", idx); + } + } + + idgen_ctx_fini(&ctx); +} + +void test_idgen(void) +{ + printf("\n>> idgen test\n\n"); + + RUN_TEST(test_idgen_invalid); + RUN_TEST(test_idgen1); + RUN_TEST(test_idgen_array); +} diff --git a/src/lib/testsuite/test_utils.c b/src/lib/testsuite/test_utils.c index 2dde2f77..0df83a33 100644 --- a/src/lib/testsuite/test_utils.c +++ b/src/lib/testsuite/test_utils.c @@ -92,10 +92,18 @@ void test_dup_threshold() return; } +void test_roundup(void) +{ + TEST_ASSERT_TRUE(ROUNDUP(1, 3) == 8); + TEST_ASSERT_TRUE(ROUNDUP(9, 4) == 16); + TEST_ASSERT_TRUE(ROUNDUP(31, 5) == 32); +} + void test_utils(void) { printf("\n>> utils test\n\n"); RUN_TEST(test_timewindow_config_dup); RUN_TEST(test_dup_threshold); + RUN_TEST(test_roundup); }