diff --git a/redismodule.h b/redismodule.h index 186e284..2f2e3c9 100644 --- a/redismodule.h +++ b/redismodule.h @@ -91,7 +91,7 @@ typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value); -typedef size_t (*RedisModuleTypeMemUsageFunc)(void *value); +typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value); typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); typedef void (*RedisModuleTypeFreeFunc)(void *value); @@ -214,6 +214,10 @@ int REDISMODULE_API_FUNC(RedisModule_IsBlockedTimeoutRequest)(RedisModuleCtx *ct void *REDISMODULE_API_FUNC(RedisModule_GetBlockedClientPrivateData)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_AbortBlock)(RedisModuleBlockedClient *bc); long long REDISMODULE_API_FUNC(RedisModule_Milliseconds)(void); +RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetThreadSafeContext)(RedisModuleBlockedClient *bc); +void REDISMODULE_API_FUNC(RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx); +void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextLock)(RedisModuleCtx *ctx); +void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextUnlock)(RedisModuleCtx *ctx); /* This is included inline inside each Redis module. */ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) __attribute__((unused)); @@ -322,6 +326,10 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(GetBlockedClientPrivateData); REDISMODULE_GET_API(AbortBlock); REDISMODULE_GET_API(Milliseconds); + REDISMODULE_GET_API(GetThreadSafeContext); + REDISMODULE_GET_API(FreeThreadSafeContext); + REDISMODULE_GET_API(ThreadSafeContextLock); + REDISMODULE_GET_API(ThreadSafeContextUnlock); RedisModule_SetModuleAttribs(ctx,name,ver,apiver); return REDISMODULE_OK; diff --git a/rmutil/Makefile b/rmutil/Makefile index 32a5dac..09e023b 100644 --- a/rmutil/Makefile +++ b/rmutil/Makefile @@ -3,10 +3,11 @@ ifndef RM_INCLUDE_DIR RM_INCLUDE_DIR=../ endif -CFLAGS = -g -fPIC -lc -lm -O3 -std=gnu99 -I$(RM_INCLUDE_DIR) -Wall -Wno-unused-function +CFLAGS ?= -g -fPIC -O3 -std=gnu99 -Wall -Wno-unused-function +CFLAGS += -I$(RM_INCLUDE_DIR) CC=gcc -OBJS=util.o strings.o sds.o vector.o heap.o priority_queue.o +OBJS=util.o strings.o sds.o vector.o alloc.o periodic.o all: librmutil.a @@ -17,13 +18,14 @@ librmutil.a: $(OBJS) ar rcs $@ $^ test_vector: test_vector.o vector.o - $(CC) -Wall -o test_vector vector.o test_vector.o -lc -O0 - @(sh -c ./test_vector) - -test_heap: test_heap.o heap.o vector.o - $(CC) -Wall -o test_heap heap.o vector.o test_heap.o -lc -O0 - @(sh -c ./test_heap) - -test_priority_queue: test_priority_queue.o priority_queue.o heap.o vector.o - $(CC) -Wall -o test_priority_queue priority_queue.o heap.o vector.o test_priority_queue.o -lc -O0 - @(sh -c ./test_priority_queue) + $(CC) -Wall -o $@ $^ -lc -lpthread -O0 + @(sh -c ./$@) +.PHONY: test_vector + +test_periodic: test_periodic.o periodic.o + $(CC) -Wall -o $@ $^ -lc -lpthread -O0 + @(sh -c ./$@) +.PHONY: test_periodic + +test: test_periodic test_vector +.PHONY: test diff --git a/rmutil/test.h b/rmutil/test.h new file mode 100644 index 0000000..a15864a --- /dev/null +++ b/rmutil/test.h @@ -0,0 +1,69 @@ +#ifndef __TESTUTIL_H__ +#define __TESTUTIL_H__ + +#include +#include +#include + +static int numTests = 0; +static int numAsserts = 0; + +#define TESTFUNC(f) \ + printf(" Testing %s\t\t", __STRING(f)); \ + numTests++; \ + fflush(stdout); \ + if (f()) { \ + printf(" %s FAILED!\n", __STRING(f)); \ + exit(1); \ + } else \ + printf("[PASS]\n"); + +#define ASSERTM(expr, ...) \ + if (!(expr)) { \ + fprintf(stderr, "%s:%d: Assertion '%s' Failed: " __VA_ARGS__ "\n", __FILE__, __LINE__, \ + __STRING(expr)); \ + return -1; \ + } \ + numAsserts++; + +#define ASSERT(expr) \ + if (!(expr)) { \ + fprintf(stderr, "%s:%d Assertion '%s' Failed\n", __FILE__, __LINE__, __STRING(expr)); \ + return -1; \ + } \ + numAsserts++; + +#define ASSERT_STRING_EQ(s1, s2) ASSERT(!strcmp(s1, s2)); + +#define ASSERT_EQUAL(x, y, ...) \ + if (x != y) { \ + fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ + fprintf(stderr, "%g != %g: " __VA_ARGS__ "\n", (double)x, (double)y); \ + return -1; \ + } \ + numAsserts++; + +#define FAIL(fmt, ...) \ + { \ + fprintf(stderr, "%s:%d: FAIL: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + return -1; \ + } + +#define RETURN_TEST_SUCCESS return 0; +#define TEST_CASE(x, block) \ + int x { \ + block; \ + return 0 \ + } + +#define PRINT_TEST_SUMMARY printf("\nTotal: %d tests and %d assertions OK\n", numTests, numAsserts); + +#define TEST_MAIN(body) \ + int main(int argc, char **argv) { \ + printf("Starting Test '%s'...\n", argv[0]); \ + body; \ + PRINT_TEST_SUMMARY; \ + printf("\n--------------------\n\n"); \ + return 0; \ + } +#endif \ No newline at end of file diff --git a/rmutil/test_vector.c b/rmutil/test_vector.c index 8a6d849..c5737b2 100644 --- a/rmutil/test_vector.c +++ b/rmutil/test_vector.c @@ -1,65 +1,58 @@ #include "vector.h" #include -#include "assert.h" +#include "test.h" -int main(int argc, char **argv) { - - - Vector *v = NewVector(int, 1); - int N = 10; +int testVector() { - for (int i = 0; i < N/2; i++) { - Vector_Put(v, i, i); - } + Vector *v = NewVector(int, 1); + ASSERT(v != NULL); + // Vector_Put(v, 0, 1); + // Vector_Put(v, 1, 3); + for (int i = 0; i < 10; i++) { + Vector_Push(v, i); + } + ASSERT_EQUAL(10, Vector_Size(v)); + ASSERT_EQUAL(16, Vector_Cap(v)); - for (int i = N/2; i < N; i++) { - Vector_Push(v, i); - } - assert(Vector_Size(v) == N); - assert(Vector_Cap(v) >= N); - - for (int i = 0; i < Vector_Size(v); i++) { - int n; - int rc = Vector_Get(v, i, &n); - printf("%d %d\n", rc, n); - assert ( 1== rc ); - assert (n == i); - } - - Vector_Free(v); - - v = NewVector(char *, 0); - N = 4; - char *strings[4] = {"hello", "world", "foo", "bar"}; + for (int i = 0; i < Vector_Size(v); i++) { + int n; + int rc = Vector_Get(v, i, &n); + ASSERT_EQUAL(1, rc); + // printf("%d %d\n", rc, n); - for (int i = 0; i < N/2; i++) { - Vector_Put(v, i, strings[i]); - } - - for (int i = N/2; i < N; i++) { - Vector_Push(v, strings[i]); - } - assert(Vector_Size(v) == N); - assert(Vector_Cap(v) >= N); - - for (size_t i = 0; i < Vector_Size(v); i++) { - char *x; - int rc = Vector_Get(v, i, &x); - assert (rc == 1); - assert (!strcmp(x, strings[i])); - } - - int rc = Vector_Get(v, 100, NULL); - assert (rc == 0); - - Vector_Free(v); - printf("PASS!\n"); - - return 0; - //Vector_Push(v, "hello"); - //Vector_Push(v, "world"); - // char *x = NULL; - // int rc = Vector_Getx(v, 0, &x); - // printf("rc: %d got %s\n", rc, x); - + ASSERT_EQUAL(n, i); + } + + Vector_Free(v); + + v = NewVector(char *, 0); + int N = 4; + char *strings[4] = {"hello", "world", "foo", "bar"}; + + for (int i = 0; i < N; i++) { + Vector_Push(v, strings[i]); + } + ASSERT_EQUAL(N, Vector_Size(v)); + ASSERT(Vector_Cap(v) >= N); + + for (int i = 0; i < Vector_Size(v); i++) { + char *x; + int rc = Vector_Get(v, i, &x); + ASSERT_EQUAL(1, rc); + ASSERT_STRING_EQ(x, strings[i]); + } + + int rc = Vector_Get(v, 100, NULL); + ASSERT_EQUAL(0, rc); + + Vector_Free(v); + + return 0; + // Vector_Push(v, "hello"); + // Vector_Push(v, "world"); + // char *x = NULL; + // int rc = Vector_Getx(v, 0, &x); + // printf("rc: %d got %s\n", rc, x); } + +TEST_MAIN({ TESTFUNC(testVector); });