<p><strong><span style="font-family:Microsoft YaHei;">客户端接口部分,这个编译成库文件</span></strong></p>
// tlog_interface.h
namespace tlog
{
class tlog_category_interface;
class tlog_ctx_interface;
};
typedef tlog::tlog_ctx_interface* LPTLOGCTX;
typedef tlog::tlog_category_interface* LPLOGCATEGORYINST;
LPTLOGCTX tlog_init_from_file(const char*);
LPLOGCATEGORYINST tlog_get_category(LPTLOGCTX, const char*);
void tlog_info(LPLOGCATEGORYINST, size_t, size_t, const char*);
int tlog_fini_ctx(LPTLOGCTX*);
// tlog_base.h
namespace tlog{
class tlog_category_interface
{
public:
~tlog_category_interface(){}
virtual void exec(const char*) = 0;
virtual int release() = 0;
};
class tlog_ctx_interface
{
public:
~tlog_ctx_interface(){}
virtual tlog_category_interface* get_category(const char*) = 0;
virtual int release();
};
enum EN_DRVICE_TYPE
{
en_device_file,
en_device_net,
};
struct stDevice
{
EN_DRVICE_TYPE _enType;
stDevice(EN_DRVICE_TYPE enType)
:_enType(enType)
{}
virtual EN_DRVICE_TYPE get_type() { return _enType; }
virtual bool init(pugi::xml_node node) = 0;
virtual int release() = 0;
virtual void exec(const char* pszData) = 0;
};
struct stDeviceFile : public stDevice
{
std::string _pattern; // 路径
uint32_t _bufferSize; // 大小
std::string _data; // 内容
std::ofstream _out; // 句柄
stDeviceFile()
: stDevice(en_device_file)
{}
virtual bool init(pugi::xml_node node)
{
// 初始化数据成员
// 打开要写的文件
}
virtual int release()
{
// 如果 _data 里面还有内容,写入到文件
// 关闭文件
}
virtual void exec(const char* pStr)
{
_data.append(pStr);
_data.append("\n");
if (_data.size() >= _bufferSize)
{
_out << _data;
_data.clear();
}
}
};
struct stDeviceNet : public stDevice
{
char _protocol[32];
char _ip[64];
char _port[8];
int _sock_c;
stDeviceNet()
: stDevice(en_device_net)
{}
virtual bool init(pugi::xml_node node)
{
// 初始化数据成员
// 链接到UDPServer
}
virtual int release()
{
}
virtual void exec(const char* pStr)
{
sockaddr_in ser;
bzero(&ser, sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(atoi(_port));
ser.sin_addr.s_addr = inet_addr(_ip);
int nlen = sizeof(ser);
sendto(_sock_c, pStr, strlen(pStr) + 1, 0, (sockaddr*)&ser, nlen);
}
};
class tlog_category : public tlog_category_interface
{
private:
std::string _name;
std::vector<stDevice*> _vecDevice;
public:
bool init(pugi::xml_node node)
{
// 解析配置,初始化数据成员
}
virtual int release()
{
// vec data release;
// destroy vec;
}
virtual void exec(const char* pstr)
{
// for (auto& itr : _vec)
// if (itr) itr->exec(pstr);
}
};
class tlog_ctx : public tlog_ctx_interface
{
private:
std::unordered_map<std::string, tlog_category*> _mapCate;
public:
bool init(const char* pszPath)
{
// 初始化 _mapCate
}
virtual int release()
{
// _mapCate data release
// destroy _mapCate
}
virtual tlog_category_interface* get_category(const char* name)
{
return _mapCate[name];
}
};
};
// tlog_base.cpp
LPTLOGCTX tlog_init_from_file(const char* pszPath)
{
tlog_ctx* pCtx = new tlog_ctx;
pCtx->init(pszPath);
return pCtx;
}
LPLOGCATEGORYINST tlog_get_category(LPTLOGCTX pstCtx, const char* pszName)
{
if (pstCtx)
{
return pstCtx->get_category(pszName);
}
return NULL;
}
void tlog_info(LPLOGCATEGORYINST pCat, size_t id, size_t, cls, const char* pszFmt, ...)
{
if (!pCat) return;
va_list vArg;
va_start(vArg, pszFmt);
char buffer[MAX_SIZE] = {0};
// char* pbuffer = buffer;
// int len = _vsnprintf(pszFmt, vArg);
// if (len < 0)
// {
// va_end(vArg);
// return;
// }
// if (len >= MAX_SIZE)
// pbuffer = (char*)malloc(len + 1);
vsnprintf(buffer, MAX_SIZE, pszFmt, vArg);
pCat->exec(buffer);
va_end(vArg);
}
int tlog_fini_ctx(LPTLOGCTX* ppstCtx)
{
if (ppstCtx && *ppstCtx)
{
(*ppstCtx)->release();
*ppstCtx = NULL;
return 0;
}
return -1;
}
解析xml工具代码:
// tlog_sql.h
struct stEntry
{
std::string _name;
std::string _oldname;
std::string _type;
uint32_t _size;
std::string _desc;
bool _index;
};
struct stStruct
{
std::string _name;
std::string _oldname;
std::string _desc;
std::unordered_map<std::string, stEntry> _mapEntry;
};
/*
解析xml到三个文件:.sql .h .cpp
.sql
procedure
-- alter table name
IF EXIST (select * from information_schema.TABLES) WHERE table_name='...') THEN ALTER TABLE ... RENAME TO ... END IF;
-- new table
IF NOT EXIST (select * from information_schema.TABLES) WHERE table_name='...') THEN CREATE TABLE .... END IF;
-- alter column name
IF EXIST (select * from information_schema.COLUMNS) WHERE table_name='...' and column_name='...') THEN ALTER TABLE ... END IF;
-- add column
IF NOT EXIST (select * from information_schema.COLUMNS) WHERE table_name='...' and column_name='...') THEN ALTER TABLE ... END IF;
所有字段都这么组织一下sql语句,没有oldname的话就没有相关sql语句
.h interface
class data_basic
{
public:
virtual bool ss_split(const char* str) = 0;
virtual const char* get_sql() = 0;
};
template<class data_basic>
data_basic* getTlogData()
{
static data_base Inst;
return &Inst;
}
每一个struct都继承data_basic, name作为类名,entry内容作为数据成员
ss_split: 解析传入的 name|...|...|... 格式字符串到数据成员,组织DB INSERT语句
get_sql: 返回DB INSERT语句
.cpp
data_base* getTLogData(const char* name)
{
if (strcmp(name, "...") == 0)
return getTLogData<...>();
// .... else if () ....
return NULL;
}
... 是struct的名字,
*/
服务端代码没有给出,大概就是收到udp消息,用xml解析工具生成的 .h .cpp函数,插入到数据库