resp协议定义, xml定义配置文件
This commit is contained in:
237
common/config.c
Normal file
237
common/config.c
Normal 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
52
common/config.h
Normal 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 */
|
||||
Reference in New Issue
Block a user