resp协议定义, xml定义配置文件

This commit is contained in:
1iaan
2026-01-19 10:37:32 +00:00
parent e404554363
commit bb2c4275cb
46 changed files with 9998 additions and 473 deletions

237
common/config.c Normal file
View File

@@ -0,0 +1,237 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h> // strcasecmp
#include <libxml/parser.h>
#include <libxml/tree.h>
static xmlNodePtr find_child(xmlNodePtr parent, const char *name)
{
if (!parent || !name) return NULL;
for (xmlNodePtr n = parent->children; n; n = n->next)
{
if (n->type == XML_ELEMENT_NODE &&
xmlStrcmp(n->name, BAD_CAST name) == 0)
{
return n;
}
}
return NULL;
}
static void set_default_config(AppConfig *cfg)
{
memset(cfg, 0, sizeof(*cfg));
strncpy(cfg->ip, "127.0.0.1", sizeof(cfg->ip) - 1);
cfg->ip[sizeof(cfg->ip) - 1] = '\0';
strncpy(cfg->master_ip, "127.0.0.1", sizeof(cfg->master_ip) - 1);
cfg->master_ip[sizeof(cfg->master_ip) - 1] = '\0';
cfg->port = 8888;
cfg->log_level = LOG_LEVEL_INFO;
cfg->mode = MODE_MASTER;
cfg->master_port = 8888;
cfg->persistence = PERSIST_NONE;
cfg->allocator = ALLOC_JEMALLOC;
}
/* ---- 字符串转枚举 ---- */
static void parse_log_level(const char *s, LogLevel *out)
{
if (!s || !out) return;
if (!strcasecmp(s, "DEBUG")) *out = LOG_LEVEL_DEBUG;
else if (!strcasecmp(s, "INFO")) *out = LOG_LEVEL_INFO;
else if (!strcasecmp(s, "ERROR")) *out = LOG_LEVEL_ERROR;
/* 不认识就保持默认 */
}
static void parse_server_mode(const char *s, ServerMode *out)
{
if (!s || !out) return;
if (!strcasecmp(s, "master")) *out = MODE_MASTER;
else if (!strcasecmp(s, "slave")) *out = MODE_SLAVE;
}
static void parse_persistence(const char *s, PersistenceType *out)
{
if (!s || !out) return;
if (!strcasecmp(s, "incremental")) *out = PERSIST_INCREMENTAL;
else if (!strcasecmp(s, "none")) *out = PERSIST_NONE;
}
static void parse_allocator(const char *s, AllocatorType *out)
{
if (!s || !out) return;
if (!strcasecmp(s, "jemalloc")) *out = ALLOC_JEMALLOC;
else if (!strcasecmp(s, "malloc")) *out = ALLOC_MALLOC;
else *out = ALLOC_OTHER;
}
/* ---- 对外的枚举转字符串工具 ---- */
const char *log_level_to_string(LogLevel lvl)
{
switch (lvl) {
case LOG_LEVEL_DEBUG: return "DEBUG";
case LOG_LEVEL_INFO: return "INFO";
case LOG_LEVEL_ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
const char *server_mode_to_string(ServerMode mode)
{
switch (mode) {
case MODE_MASTER: return "master";
case MODE_SLAVE: return "slave";
default: return "unknown";
}
}
const char *persistence_to_string(PersistenceType p)
{
switch (p) {
case PERSIST_INCREMENTAL: return "incremental";
case PERSIST_NONE: return "none";
default: return "unknown";
}
}
const char *allocator_to_string(AllocatorType a)
{
switch (a) {
case ALLOC_JEMALLOC: return "jemalloc";
case ALLOC_MALLOC: return "malloc";
case ALLOC_OTHER: return "other";
default: return "unknown";
}
}
/* ---- 主函数:从 XML 加载配置 ---- */
int config_load(const char *filename, AppConfig *out_cfg)
{
if (!filename || !out_cfg) return -1;
set_default_config(out_cfg);
xmlDocPtr doc = xmlReadFile(filename, "UTF-8", XML_PARSE_NOBLANKS);
if (!doc) {
fprintf(stderr, "config_load: failed to read file %s\n", filename);
return -1;
}
xmlNodePtr root = xmlDocGetRootElement(doc);
if (!root || xmlStrcmp(root->name, BAD_CAST "config") != 0) {
fprintf(stderr, "config_load: root element is not <config>\n");
xmlFreeDoc(doc);
return -1;
}
/* server 部分 */
xmlNodePtr server = find_child(root, "server");
if (server) {
/* ip */
xmlNodePtr ip_node = find_child(server, "ip");
if (ip_node) {
xmlChar *txt = xmlNodeGetContent(ip_node);
if (txt) {
strncpy(out_cfg->ip, (char *)txt, sizeof(out_cfg->ip) - 1);
out_cfg->ip[sizeof(out_cfg->ip) - 1] = '\0';
xmlFree(txt);
}
}
/* port */
xmlNodePtr port_node = find_child(server, "port");
if (port_node) {
xmlChar *txt = xmlNodeGetContent(port_node);
if (txt) {
out_cfg->port = atoi((char *)txt);
xmlFree(txt);
}
}
/* mode: master / slave */
xmlNodePtr mode_node = find_child(server, "mode");
if (mode_node) {
xmlChar *txt = xmlNodeGetContent(mode_node);
if (txt) {
parse_server_mode((char *)txt, &out_cfg->mode);
xmlFree(txt);
}
}
/* master (always read if present) */
xmlNodePtr master = find_child(server, "master");
if (master) {
xmlNodePtr mip_node = find_child(master, "ip");
if (mip_node) {
xmlChar *txt = xmlNodeGetContent(mip_node);
if (txt) {
strncpy(out_cfg->master_ip, (char *)txt, sizeof(out_cfg->master_ip) - 1);
out_cfg->master_ip[sizeof(out_cfg->master_ip) - 1] = '\0';
xmlFree(txt);
}
}
xmlNodePtr mport_node = find_child(master, "port");
if (mport_node) {
xmlChar *txt = xmlNodeGetContent(port_node);
if (txt) {
out_cfg->master_port = atoi((char *)txt);
xmlFree(txt);
}
}
}
}
/* log 部分 */
xmlNodePtr log = find_child(root, "log");
if (log) {
xmlNodePtr lvl_node = find_child(log, "level");
if (lvl_node) {
xmlChar *txt = xmlNodeGetContent(lvl_node);
if (txt) {
parse_log_level((char *)txt, &out_cfg->log_level);
xmlFree(txt);
}
}
}
/* persistence 部分 */
xmlNodePtr pers = find_child(root, "persistence");
if (pers) {
xmlNodePtr type_node = find_child(pers, "type");
if (type_node) {
xmlChar *txt = xmlNodeGetContent(type_node);
if (txt) {
parse_persistence((char *)txt, &out_cfg->persistence);
xmlFree(txt);
}
}
}
/* memory 部分 */
xmlNodePtr mem = find_child(root, "memory");
if (mem) {
xmlNodePtr alloc_node = find_child(mem, "allocator");
if (alloc_node) {
xmlChar *txt = xmlNodeGetContent(alloc_node);
if (txt) {
parse_allocator((char *)txt, &out_cfg->allocator);
xmlFree(txt);
}
}
}
xmlFreeDoc(doc);
/* xmlCleanupParser() 建议在程序退出时 main 里统一调用 */
return 0;
}

52
common/config.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include <stddef.h>
typedef enum {
LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_ERROR
} LogLevel;
typedef enum {
MODE_MASTER,
MODE_SLAVE
} ServerMode;
typedef enum {
PERSIST_INCREMENTAL,
PERSIST_NONE
} PersistenceType;
typedef enum {
ALLOC_JEMALLOC,
ALLOC_MALLOC,
ALLOC_OTHER
} AllocatorType;
typedef struct {
char ip[64];
int port;
ServerMode mode;
char master_ip[64]; // slave 才需要
int master_port; // slave 才需要
LogLevel log_level;
PersistenceType persistence;
AllocatorType allocator;
} AppConfig;
/**
* 从 XML 文件加载配置
* 返回 0 表示成功;非 0 表示失败
*/
int config_load(const char *filename, AppConfig *out_cfg);
const char *log_level_to_string(LogLevel lvl);
const char *server_mode_to_string(ServerMode mode);
const char *persistence_to_string(PersistenceType p);
const char *allocator_to_string(AllocatorType a);
#endif /* CONFIG_H */