内存探测组件,预留热插拔。
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
|||||||
kvstore
|
kvstore
|
||||||
testcase
|
testcase
|
||||||
|
|
||||||
|
mem_leak
|
||||||
11
Makefile
11
Makefile
@@ -9,8 +9,8 @@ COMMON_SRCS = ./common/config.c ./diskuring/diskuring.c
|
|||||||
|
|
||||||
SRCS = $(NET_SRCS) $(KV_SRCS) $(MEM_SRCS) $(COMMON_SRCS)
|
SRCS = $(NET_SRCS) $(KV_SRCS) $(MEM_SRCS) $(COMMON_SRCS)
|
||||||
|
|
||||||
INC = -I./NtyCo/core/ -I/usr/include/libxml2
|
INC = -I./NtyCo/core/ -I/usr/include/libxml2 -I./
|
||||||
LIBDIRS = -L./NtyCo/ -L./memory/ -L./diskuring/
|
LIBDIRS = -L./NtyCo/
|
||||||
LIBS = -lntyco -lpthread -luring -ldl -lxml2 -ljemalloc
|
LIBS = -lntyco -lpthread -luring -ldl -lxml2 -ljemalloc
|
||||||
|
|
||||||
TARGET = kvstore
|
TARGET = kvstore
|
||||||
@@ -33,7 +33,7 @@ ECHO:
|
|||||||
@echo $(SUBDIR)
|
@echo $(SUBDIR)
|
||||||
|
|
||||||
$(TARGET): $(OBJS)
|
$(TARGET): $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBDIRS) $(LIBS)
|
$(CC) $(CFLAGS) -o $@ $^ $(LIBDIRS) $(LIBS)
|
||||||
|
|
||||||
$(TEST_REDIS): $(TEST_REDIS_SRCS)
|
$(TEST_REDIS): $(TEST_REDIS_SRCS)
|
||||||
$(CC) -g -o $@ $^ $(TEST_REDIS_LDFLAGS)
|
$(CC) -g -o $@ $^ $(TEST_REDIS_LDFLAGS)
|
||||||
@@ -41,7 +41,8 @@ $(TEST_REDIS): $(TEST_REDIS_SRCS)
|
|||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(INC) -c $^ -g -o $@
|
$(CC) $(CFLAGS) $(INC) -c $^ -g -o $@
|
||||||
|
|
||||||
clean:
|
clean: clmem
|
||||||
rm -rf $(OBJS) $(TARGET) $(TEST_REDIS)
|
rm -rf $(OBJS) $(TARGET) $(TEST_REDIS)
|
||||||
|
|
||||||
|
clmem:
|
||||||
|
rm -rf mem_leak/*
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ static void set_default_config(AppConfig *cfg)
|
|||||||
cfg->master_port = 8888;
|
cfg->master_port = 8888;
|
||||||
cfg->persistence = PERSIST_NONE;
|
cfg->persistence = PERSIST_NONE;
|
||||||
cfg->allocator = ALLOC_JEMALLOC;
|
cfg->allocator = ALLOC_JEMALLOC;
|
||||||
|
cfg->leak_mode = MEMLEAK_DETECT_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- 字符串转枚举 ---- */
|
/* ---- 字符串转枚举 ---- */
|
||||||
@@ -90,9 +91,18 @@ static void parse_allocator(const char *s, AllocatorType *out)
|
|||||||
if (!s || !out) return;
|
if (!s || !out) return;
|
||||||
if (!strcasecmp(s, "jemalloc")) *out = ALLOC_JEMALLOC;
|
if (!strcasecmp(s, "jemalloc")) *out = ALLOC_JEMALLOC;
|
||||||
else if (!strcasecmp(s, "malloc")) *out = ALLOC_MALLOC;
|
else if (!strcasecmp(s, "malloc")) *out = ALLOC_MALLOC;
|
||||||
|
else if (!strcasecmp(s, "mypool")) *out = ALLOC_MYPOOL;
|
||||||
else *out = ALLOC_OTHER;
|
else *out = ALLOC_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_leakage(const char *s, MemLeakDetectMode *out)
|
||||||
|
{
|
||||||
|
if (!s || !out) return;
|
||||||
|
if (!strcasecmp(s, "enable")) *out = MEMLEAK_DETECT_ON;
|
||||||
|
else if (!strcasecmp(s, "disable")) *out = MEMLEAK_DETECT_OFF;
|
||||||
|
else *out = MEMLEAK_DETECT_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
static int read_file_mmap(const char *filename, void **out_addr, size_t *out_len, int *out_fd) {
|
static int read_file_mmap(const char *filename, void **out_addr, size_t *out_len, int *out_fd) {
|
||||||
if (!filename || !out_addr || !out_len || !out_fd) return -1;
|
if (!filename || !out_addr || !out_len || !out_fd) return -1;
|
||||||
|
|
||||||
@@ -174,11 +184,21 @@ const char *allocator_to_string(AllocatorType a)
|
|||||||
switch (a) {
|
switch (a) {
|
||||||
case ALLOC_JEMALLOC: return "jemalloc";
|
case ALLOC_JEMALLOC: return "jemalloc";
|
||||||
case ALLOC_MALLOC: return "malloc";
|
case ALLOC_MALLOC: return "malloc";
|
||||||
|
case ALLOC_MYPOOL: return "mypool";
|
||||||
case ALLOC_OTHER: return "other";
|
case ALLOC_OTHER: return "other";
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *leakage_to_string(MemLeakDetectMode a)
|
||||||
|
{
|
||||||
|
switch (a) {
|
||||||
|
case MEMLEAK_DETECT_ON: return "enable";
|
||||||
|
case MEMLEAK_DETECT_OFF: return "disable";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- 主函数:从 XML 加载配置 ---- */
|
/* ---- 主函数:从 XML 加载配置 ---- */
|
||||||
|
|
||||||
/* server 部分 */
|
/* server 部分 */
|
||||||
@@ -333,6 +353,15 @@ void memory_load(xmlNodePtr *root, AppConfig *out_cfg){
|
|||||||
xmlFree(txt);
|
xmlFree(txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlNodePtr leakage_node = find_child(mem, "leakage");
|
||||||
|
if (leakage_node) {
|
||||||
|
xmlChar *txt = xmlNodeGetContent(leakage_node);
|
||||||
|
if (txt) {
|
||||||
|
parse_leakage((char *)txt, &out_cfg->leak_mode);
|
||||||
|
xmlFree(txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define __CONFIG_H__
|
#define __CONFIG_H__
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <memory/alloc_dispatch.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LOG_LEVEL_DEBUG,
|
LOG_LEVEL_DEBUG,
|
||||||
@@ -19,11 +20,17 @@ typedef enum {
|
|||||||
PERSIST_NONE
|
PERSIST_NONE
|
||||||
} PersistenceType;
|
} PersistenceType;
|
||||||
|
|
||||||
typedef enum {
|
// typedef enum {
|
||||||
ALLOC_JEMALLOC,
|
// ALLOC_JEMALLOC,
|
||||||
ALLOC_MALLOC,
|
// ALLOC_MALLOC,
|
||||||
ALLOC_OTHER
|
// ALLOC_MYPOOL,
|
||||||
} AllocatorType;
|
// ALLOC_OTHER
|
||||||
|
// } AllocatorType;
|
||||||
|
|
||||||
|
// typedef enum {
|
||||||
|
// MEMLEAK_DETECT_OFF = 0, // 关闭检测
|
||||||
|
// MEMLEAK_DETECT_ON = 1 // 开启检测
|
||||||
|
// } MemLeakDetectMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char ip[64];
|
char ip[64];
|
||||||
@@ -43,6 +50,7 @@ typedef struct {
|
|||||||
char hash_file[256];
|
char hash_file[256];
|
||||||
|
|
||||||
AllocatorType allocator;
|
AllocatorType allocator;
|
||||||
|
MemLeakDetectMode leak_mode;
|
||||||
} AppConfig;
|
} AppConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,5 +63,6 @@ const char *log_level_to_string(LogLevel lvl);
|
|||||||
const char *server_mode_to_string(ServerMode mode);
|
const char *server_mode_to_string(ServerMode mode);
|
||||||
const char *persistence_to_string(PersistenceType p);
|
const char *persistence_to_string(PersistenceType p);
|
||||||
const char *allocator_to_string(AllocatorType a);
|
const char *allocator_to_string(AllocatorType a);
|
||||||
|
const char *leakage_to_string(MemLeakDetectMode a);
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
#endif /* CONFIG_H */
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
</persistence>
|
</persistence>
|
||||||
|
|
||||||
<memory>
|
<memory>
|
||||||
<allocator>jemalloc</allocator> <!-- jemalloc / malloc / other -->
|
<allocator>mypool</allocator> <!-- jemalloc / malloc / mypool -->
|
||||||
|
<leakage>enable</leakage> <!-- enable/disable-->
|
||||||
</memory>
|
</memory>
|
||||||
</config>
|
</config>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "diskuring.h"
|
#include "diskuring.h"
|
||||||
#include "../memory/alloc_dispatch.h"
|
#include "memory/alloc_dispatch.h"
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
|
|||||||
14
kvstore.c
14
kvstore.c
@@ -353,6 +353,7 @@ int init_kvengine(void) {
|
|||||||
kvs_replay_log(global_cmd_log_fd);
|
kvs_replay_log(global_cmd_log_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("kvengine init complete\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,10 +371,14 @@ void dest_kvengine(void) {
|
|||||||
destroy_cmd_log(global_cmd_log_fd);
|
destroy_cmd_log(global_cmd_log_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_memory_pool(void){
|
void init_memory_pool(AppConfig *cfg){
|
||||||
#if MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
|
#if MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
|
||||||
mp_create(&global_mempool);
|
mp_create(&global_mempool);
|
||||||
#endif
|
#endif
|
||||||
|
kvs_set_memleak_detect(cfg->leak_mode);
|
||||||
|
kvs_set_alloc_type(cfg->allocator);
|
||||||
|
|
||||||
|
printf("mempool init complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dest_memory_pool(void){
|
void dest_memory_pool(void){
|
||||||
@@ -440,7 +445,9 @@ int init_config(AppConfig *cfg){
|
|||||||
printf("|—— Persist-hash : %s\n", cfg->hash_file);
|
printf("|—— Persist-hash : %s\n", cfg->hash_file);
|
||||||
|
|
||||||
printf("Log level : %s\n", log_level_to_string(cfg->log_level));
|
printf("Log level : %s\n", log_level_to_string(cfg->log_level));
|
||||||
printf("Allocator : %s\n", allocator_to_string(cfg->allocator));
|
printf("Memory : \n");
|
||||||
|
printf("|——Allocator : %s\n", allocator_to_string(cfg->allocator));
|
||||||
|
printf("|——MemLeakDetectMode : %s\n", leakage_to_string(cfg->leak_mode));
|
||||||
printf("=============== Config ===============\n");
|
printf("=============== Config ===============\n");
|
||||||
|
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
@@ -476,9 +483,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
init_memory_pool();
|
init_memory_pool(&global_cfg);
|
||||||
init_kvengine();
|
init_kvengine();
|
||||||
|
|
||||||
|
|
||||||
#if (NETWORK_SELECT == NETWORK_REACTOR)
|
#if (NETWORK_SELECT == NETWORK_REACTOR)
|
||||||
reactor_start(port, kvs_protocol, master_ip, master_port); //
|
reactor_start(port, kvs_protocol, master_ip, master_port); //
|
||||||
|
|||||||
@@ -1,30 +1,111 @@
|
|||||||
|
#include "alloc_dispatch.h"
|
||||||
#include "mempool.h"
|
#include "mempool.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <jemalloc/jemalloc.h>
|
#include <jemalloc/jemalloc.h>
|
||||||
|
|
||||||
mp_pool_t global_mempool;
|
mp_pool_t global_mempool;
|
||||||
|
|
||||||
void *kvs_malloc(size_t size) {
|
static atomic_int g_memory_mode = ATOMIC_VAR_INIT(MEMLEAK_DETECT_OFF);
|
||||||
#if MEMORY_SELECT_MALLOC == MEMORY_USE_DEFAULT
|
static atomic_int g_memleak_detect_mode = ATOMIC_VAR_INIT(MEMLEAK_DETECT_OFF);
|
||||||
return malloc(size);
|
|
||||||
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
|
// 设置内存池类型
|
||||||
return mp_alloc(size);
|
void kvs_set_alloc_type(AllocatorType mode) {
|
||||||
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_JEMALLOC
|
atomic_store(&g_memory_mode, mode);
|
||||||
return je_malloc(size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvs_free(void *ptr) {
|
// 获取当前内存池类型
|
||||||
#if MEMORY_SELECT_MALLOC == MEMORY_USE_DEFAULT
|
AllocatorType kvs_get_alloc_type(void) {
|
||||||
free(ptr);
|
return atomic_load(&g_memory_mode);
|
||||||
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
|
}
|
||||||
int ret = mp_free(ptr);
|
|
||||||
if(ret == MEMPOOL_DOUBLE_FREE){
|
// 设置内存泄漏检测模式
|
||||||
printf("double free %p\n", ptr);
|
void kvs_set_memleak_detect(MemLeakDetectMode mode) {
|
||||||
|
atomic_store(&g_memleak_detect_mode, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前内存泄漏检测模式
|
||||||
|
MemLeakDetectMode kvs_get_memleak_detect(void) {
|
||||||
|
return atomic_load(&g_memleak_detect_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *kvs_malloc_impl(size_t size){
|
||||||
|
|
||||||
|
switch (atomic_load(&g_memleak_detect_mode)){
|
||||||
|
case ALLOC_MALLOC:
|
||||||
|
return malloc(size);
|
||||||
|
case ALLOC_MYPOOL:
|
||||||
|
return mp_alloc(&global_mempool, size);
|
||||||
|
case ALLOC_JEMALLOC:
|
||||||
|
return je_malloc(size);
|
||||||
|
case ALLOC_OTHER:
|
||||||
|
default:
|
||||||
|
return malloc(size);
|
||||||
}
|
}
|
||||||
#elif MEMORY_SELECT_MALLOC == MEMORY_USE_JEMALLOC
|
return NULL;
|
||||||
je_free(ptr);
|
}
|
||||||
#endif
|
|
||||||
|
void kvs_free_impl(void *ptr) {
|
||||||
|
switch (atomic_load(&g_memleak_detect_mode)){
|
||||||
|
case ALLOC_MALLOC:
|
||||||
|
free(ptr);
|
||||||
|
break;
|
||||||
|
case ALLOC_MYPOOL:{
|
||||||
|
int ret = mp_free(&global_mempool, ptr);
|
||||||
|
if(ret == MEMPOOL_DOUBLE_FREE){
|
||||||
|
printf("double free %p\n", ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ALLOC_JEMALLOC:
|
||||||
|
je_free(ptr);
|
||||||
|
break;
|
||||||
|
case ALLOC_OTHER:
|
||||||
|
default:
|
||||||
|
free(ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *nMalloc(size_t size, const char * filename, const char *func, int line){
|
||||||
|
void *ptr = kvs_malloc_impl(size);
|
||||||
|
|
||||||
|
if(atomic_load(&g_memleak_detect_mode) == MEMLEAK_DETECT_ON) {
|
||||||
|
char buff[128];
|
||||||
|
snprintf(buff, 128, "./mem_leak/%p.mem", ptr);
|
||||||
|
FILE* fp = fopen(buff, "w");
|
||||||
|
if(!fp){
|
||||||
|
kvs_free(ptr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "[+] [%s : %s : %d] %p: %ld malloc\n", filename, func, line, ptr, size);
|
||||||
|
fflush(fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nFree(void *ptr, const char * filename, const char *func, int line){
|
||||||
|
if(!ptr) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(atomic_load(&g_memleak_detect_mode) == MEMLEAK_DETECT_ON) {
|
||||||
|
char buff[128];
|
||||||
|
snprintf(buff, 128, "./mem_leak/%p.mem", ptr);
|
||||||
|
|
||||||
|
if(unlink(buff) < 0) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
kvs_free_impl(ptr);
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,36 @@
|
|||||||
#define MEMORY_USE_MYMALLOC 1
|
#define MEMORY_USE_MYMALLOC 1
|
||||||
#define MEMORY_USE_JEMALLOC 2
|
#define MEMORY_USE_JEMALLOC 2
|
||||||
|
|
||||||
#define MEMORY_SELECT_MALLOC MEMORY_USE_MYMALLOC
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include "mempool.h"
|
#include "mempool.h"
|
||||||
|
|
||||||
void *kvs_malloc(size_t size);
|
typedef enum {
|
||||||
void kvs_free(void *ptr);
|
ALLOC_JEMALLOC,
|
||||||
|
ALLOC_MALLOC,
|
||||||
|
ALLOC_MYPOOL,
|
||||||
|
ALLOC_OTHER
|
||||||
|
} AllocatorType;
|
||||||
|
|
||||||
|
void kvs_set_alloc_type(AllocatorType mode);
|
||||||
|
AllocatorType kvs_get_alloc_type(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MEMLEAK_DETECT_OFF = 0, // 关闭检测
|
||||||
|
MEMLEAK_DETECT_ON = 1 // 开启检测
|
||||||
|
} MemLeakDetectMode;
|
||||||
|
|
||||||
|
void kvs_set_memleak_detect(MemLeakDetectMode mode);
|
||||||
|
MemLeakDetectMode kvs_get_memleak_detect(void);
|
||||||
|
|
||||||
|
void *kvs_malloc_impl(size_t size);
|
||||||
|
void kvs_free_impl(void *ptr);
|
||||||
|
|
||||||
|
void *nMalloc(size_t size, const char * filename, const char *func, int line);
|
||||||
|
void nFree(void *ptr, const char * filename, const char *func, int line);
|
||||||
|
|
||||||
|
#define kvs_malloc(size) nMalloc (size , __FILE__, __func__, __LINE__)
|
||||||
|
#define kvs_free(ptr) nFree (ptr , __FILE__, __func__, __LINE__)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user