diff --git a/include/logging.h b/include/logging.h index 174b4e8..af9fa6b 100644 --- a/include/logging.h +++ b/include/logging.h @@ -66,7 +66,7 @@ Logger *newLogger(const char *name); */ Logger *getDefaultLogger(void); -Logger *getLogger(const char *name, log_level level); +Logger *getLogger(const char *name); /** * @brief 销毁日志对象,该方法会销毁默认日志对象 diff --git a/src/logging.c b/src/logging.c index 1929b23..310ef49 100644 --- a/src/logging.c +++ b/src/logging.c @@ -21,6 +21,8 @@ static Logger *ROOT_LOGGER = NULL; // 根日志对象,唯一实例 +static Map *LOGGER_MAP = NULL; // 日志对象映射表 + /** * @brief 为日志添加一个handler * @param handler 处理器对象 @@ -201,11 +203,17 @@ Logger *newLogger(const char *name) { return NULL; } + if (LOGGER_MAP == NULL) { + LOGGER_MAP = map_create(sizeof(Logger **)); + } + logger->level = LOG_INFO; logger->handler = loggingHandlerConsole(); logger->name = name; logger->filter = NULL; + map_put(LOGGER_MAP, name, &logger); + return logger; } @@ -224,18 +232,28 @@ Logger *getDefaultLogger(void) { * @param level 日志等级 * @return 日志器对象 */ -Logger *getLogger(const char *name, log_level level) { +Logger *getLogger(const char *name) { if (name == NULL) { return NULL; } + if (LOGGER_MAP == NULL) { + LOGGER_MAP = map_create(sizeof(Logger **)); + } + + Logger **cache_logger_ptr = (Logger **)map_get(LOGGER_MAP, name); + if (cache_logger_ptr != NULL) { + return *cache_logger_ptr; + } Logger *logger = (Logger *)malloc(sizeof(Logger)); - logger->level = level; + logger->level = LOG_INFO; logger->handler = loggingHandlerConsole(); logger->name = name; logger->filter = NULL; + map_put(LOGGER_MAP, name, &logger); + return logger; } @@ -258,7 +276,17 @@ void destroyLogger(Logger *logger) { } } +static void +__destroyLoggerForeach(const char *key, void *value, void *user_data) { + (void)user_data; + (void)key; + destroyLogger(*(Logger **)value); +} + /** * @brief 销毁日志对象 */ -void destroyDefaultLogger(void) { destroyLogger(ROOT_LOGGER); } \ No newline at end of file +void destroyDefaultLogger(void) { + map_foreach(LOGGER_MAP, __destroyLoggerForeach, NULL); + map_destroy(LOGGER_MAP); +} \ No newline at end of file diff --git a/src/utils/logging-map.c b/src/utils/logging-map.c index 8aa5bba..91776f4 100644 --- a/src/utils/logging-map.c +++ b/src/utils/logging-map.c @@ -15,9 +15,8 @@ static uint32_t hash_bytes(const void *data, size_t len) { } /* 创建空 map */ -Map *map_create(size_t key_len, size_t value_len) { +Map *map_create(size_t value_len) { Map *m = calloc(1, sizeof(*m)); - m->key_len = key_len; m->value_len = value_len; m->bucket_cap = 8; /* 初始桶数 */ m->bucket = calloc(m->bucket_cap, sizeof(Node *)); @@ -25,15 +24,16 @@ Map *map_create(size_t key_len, size_t value_len) { } /* 根据 key 找到桶下标 */ -static size_t bucket_index(Map *m, const void *key) { - uint32_t h = hash_bytes(key, m->key_len); +static size_t bucket_index(Map *m, const char *key) { + size_t len = strlen(key); + uint32_t h = hash_bytes(key, len); return h & (m->bucket_cap - 1); /* 要求 bucket_cap 是 2 的幂 */ } /* 在桶链中线性查找 */ -static Node *find_in_chain(Node *head, const void *key, size_t key_len) { +static Node *find_in_chain(Node *head, const char *key) { for (; head; head = head->next) { - if (memcmp(head->kv, key, key_len) == 0) { + if (strcmp(head->key, key) == 0) { return head; } } @@ -48,8 +48,9 @@ static void map_resize(Map *m) { for (size_t i = 0; i < m->bucket_cap; ++i) { Node *node = m->bucket[i]; while (node) { - Node *next = node->next; - size_t idx = hash_bytes(node->kv, m->key_len) & (new_cap - 1); + Node *next = node->next; + size_t idx = + hash_bytes(node->key, strlen(node->key)) & (new_cap - 1); node->next = new_bucket[idx]; new_bucket[idx] = node; node = next; @@ -61,45 +62,47 @@ static void map_resize(Map *m) { } /* 插入或覆盖 */ -void map_put(Map *m, const void *key, const void *value) { +void map_put(Map *m, const char *key, const void *value) { if (m->size * 4 >= m->bucket_cap * 3) { /* 装载因子 0.75 */ map_resize(m); } size_t idx = bucket_index(m, key); - Node *node = find_in_chain(m->bucket[idx], key, m->key_len); + Node *node = find_in_chain(m->bucket[idx], key); if (node) { /* 覆盖旧值 */ - memcpy(node->kv + m->key_len, value, m->value_len); + memcpy(node->value, value, m->value_len); return; } /* 新建节点 */ - node = malloc(sizeof(*node)); - node->kv = malloc(m->key_len + m->value_len); - node->next = m->bucket[idx]; - memcpy(node->kv, key, m->key_len); - memcpy(node->kv + m->key_len, value, m->value_len); + node = malloc(sizeof(*node)); + node->value = malloc(m->value_len); + node->next = m->bucket[idx]; + node->key = malloc(strlen(key) + 1); + memcpy(node->key, key, strlen(key) + 1); + memcpy(node->value, value, m->value_len); m->bucket[idx] = node; ++m->size; } /* 查找 */ -void *map_get(Map *m, const void *key) { +void *map_get(Map *m, const char *key) { size_t idx = bucket_index(m, key); - Node *node = find_in_chain(m->bucket[idx], key, m->key_len); - return node ? (node->kv + m->key_len) : NULL; + Node *node = find_in_chain(m->bucket[idx], key); + return node ? node->value : NULL; } /* 删除 */ -bool map_erase(Map *m, const void *key) { +bool map_erase(Map *m, const char *key) { size_t idx = bucket_index(m, key); Node **link = &m->bucket[idx]; for (; *link; link = &(*link)->next) { - if (memcmp((*link)->kv, key, m->key_len) == 0) { + if (strcmp((*link)->key, key) == 0) { Node *to_del = *link; *link = to_del->next; - free(to_del->kv); + free(to_del->key); + free(to_del->value); free(to_del); --m->size; return true; @@ -114,11 +117,27 @@ void map_destroy(Map *m) { Node *node = m->bucket[i]; while (node) { Node *next = node->next; - free(node->kv); + free(node->key); + free(node->value); free(node); node = next; } } free(m->bucket); free(m); +} + +/* 遍历 */ +void map_foreach(Map *m, + void (*callback)(const char *key, + void *value, + void *user_data), + void *user_data) { + for (size_t i = 0; i < m->bucket_cap; ++i) { + Node *node = m->bucket[i]; + while (node) { + callback(node->key, node->value, user_data); + node = node->next; + } + } } \ No newline at end of file diff --git a/src/utils/logging-map.h b/src/utils/logging-map.h index 14a1e92..cae31d7 100644 --- a/src/utils/logging-map.h +++ b/src/utils/logging-map.h @@ -7,11 +7,12 @@ typedef struct Node { struct Node *next; - uint8_t *kv; /* key 在前 value 在后 */ + char *key; + void *value; } Node; struct Map { - size_t key_len, value_len; + size_t value_len; size_t bucket_cap; size_t size; /* 当前元素个数 */ Node **bucket; /* 指针数组 */ @@ -20,16 +21,23 @@ struct Map { typedef struct Map Map; /* 创建空 map:key_len/value_len 以字节为单位 */ -Map *map_create(size_t key_len, size_t value_len); +Map *map_create(size_t value_len); /* 插入或覆盖: 必须指向 key_len 字节;同理 value */ -void map_put(Map *m, const void *key, const void *value); +void map_put(Map *m, const char *key, const void *value); /* 查找:找到返回 value 指针;未找到返回 NULL */ -void *map_get(Map *m, const void *key); +void *map_get(Map *m, const char *key); /* 删除:返回 true 表示确实删掉了 */ -bool map_erase(Map *m, const void *key); +bool map_erase(Map *m, const char *key); + +/* 遍历: 遍历所有元素*/ +void map_foreach(Map *m, + void (*callback)(const char *key, + void *value, + void *user_data), + void *user_data); /* 销毁并释放所有内存 */ void map_destroy(Map *m); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f2f9869..010d63b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,6 +20,10 @@ add_executable(${PROJECT_NAME}filter test-filter.c) target_link_libraries(${PROJECT_NAME}filter logging) add_test(test_filter ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}filter${CMAKE_EXECUTEABLE_SUFFIX}) +#测试多log多次获取 +add_executable(${PROJECT_NAME}logs test-logs.c) +target_link_libraries(${PROJECT_NAME}logs logging) +add_test(test_logs ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}logs${CMAKE_EXECUTEABLE_SUFFIX}) #测试工具map add_executable(${PROJECT_NAME}map test-map.c) diff --git a/tests/test-logs.c b/tests/test-logs.c new file mode 100644 index 0000000..bf17fcd --- /dev/null +++ b/tests/test-logs.c @@ -0,0 +1,24 @@ +#include "logging.h" +#include "logging/logging-core.h" +#include + +int main() { + Logger *t1 = getLogger("Test1"); + t1->level = LOG_ERROR; + + Logger *t2 = getLogger("Test2"); + t2->level = LOG_DEBUG; + + Logger *t11 = getLogger("Test1"); + + if (t1 == t11) { + printf("t1 and t11 are the same\n"); + printf("t1 log level: %s", LOG_LEVEL_STR[t11->level]); + } else { + printf("t1 and t11 are different\n"); + return 1; + } + + destroyDefaultLogger(); + return 0; +} \ No newline at end of file diff --git a/tests/test-map.c b/tests/test-map.c index 2253ce0..a04ddc2 100644 --- a/tests/test-map.c +++ b/tests/test-map.c @@ -1,17 +1,37 @@ #include "utils/logging-map.h" +#include +#include +#include + +void foreach_callback(const char *key, void *value, void *user_data) { + (void)user_data; + printf("foreach key: %s, value: %d\n", key, *(int *)value); +} int main(int argc, char *argv[]) { (void)argc; (void)argv; - Map *map = map_create(0, sizeof(int)); + Map *map = map_create(sizeof(int)); - const char *keys[] = {"key1", "key2", "key3", "key4", "key5"}; + const char *keys[] = {"key1", "key22", "key33", "key44", "key55"}; for (int i = 0; i < 5; i++) { + printf("put key %s,value %d\n", keys[i], i); map_put(map, keys[i], &i); } + for (int i = 0; i < 5; i++) { + int *value = map_get(map, keys[i]); + printf("get value: %d\n", *value); + if (*value != i) { + return 1; + } + } + + map_foreach(map, foreach_callback, NULL); + map_destroy(map); + return 0; -} \ No newline at end of file +}