mangosd 之 DB Access
mangosd的数据库访问按照是否需要返回值分为三种情况;(1)对于需要返回值的sql命令,采用Query()函数直接在主线程访问数据库;(2)不需要返回值的sql命令则通过Execute函数,将sql命令封装在SqlOperation中,并通过一个互斥队列将SqlOperation的指针传到SqlDelayThread中执行(Delay的Sql,很形象);(3)也有需要返回值的,但同时也需要在DelayThread中执行的异步Query;在SqlDelayThread中,SqlOperation调用Execute函数(接口),传入Database指针,这样可以通过传入不同的Database子类指针就可以动态插拔使用的数据库。这也是面向接口编程的一种实践吧。依赖的都是基类的接口,对于扩展和变化可以很好的兼容。看看代码:
class SqlOperation
{
public:
virtual void OnRemove() { delete this; }
virtual void Execute(Database *db) = 0;
virtual ~SqlOperation() {}
};
class SqlStatement : public SqlOperation
{
private:
const char *m_sql;
public:
SqlStatement(const char *sql) : m_sql(strdup(sql)){}
~SqlStatement() { free((void*)const_cast(m_sql)); }
void Execute(Database *db);
};
void SqlDelayThread::run()
{
SqlOperation* s;
mysql_thread_init();
while (m_running)
{
// if the running state gets turned off while sleeping
// empty the queue before exiting
ZThread::Thread::sleep(10);
while (!m_sqlQueue.empty())
{
s = m_sqlQueue.next();
s->Execute(m_dbEngine);
delete s;
}
}
}
void SqlStatement::Execute(Database *db)
{
/// just do it
db->DirectExecute(m_sql);
}
需要注意的几点:
1. 数据库操作类型是独立的。传入到m_sqlQueue( ZThread::LockedQueue
ZThread::FastMutex>)队列的是SqlOperation指针,可以通过传入不同的SqlOperation子类指针来达到扩展的目的;比如mangos也实现了:
class SqlTransaction : public SqlOperation
{
private:
std::queue m_queue;
public:
SqlTransaction() {}
void DelayExecute(const char *sql) { m_queue.push(strdup(sql)); }
void Execute(Database *db);
};
这样只需要SqlTransaction 在自己的Execute实现事物相关的数据库操作过程就可以实现功能了。
2.使用的数据库也是独立的。只需要向SqlOperation的Execute传入不同的的Database子类(DatabaseMysql,DatabaseSqlite等)就可以使用不同的数据库了,很是方便;这也体现了依赖倒置原则的威力。
3.mangos没有实现自己的内存管理,都是直接new,m_sqlQueue中存放的就是SqlOperation指针,在MysqlDelayThread中操作完毕后需要删除。即主线程中new,MysqlDelayThread中 delete。这样直接的new,用起来是方便,拿来就用,但是作为服务器程序,运行久了就会开始累积内存碎片,可能会导致运行越来越慢。现在很多游戏运营商都会有周期性例行维护,估计和内存碎片也是有一定关系的。
4.对m_sqlQueue队列进行互斥保护的是ZThread::FastMutex,但是怎么也没有看出“Fast”体现在拿来,acquire,release,tryacquire都是很普通的调用系统提供的api,希望高人来指点一二。
5.对于在DelayThread中执行的有返回值的sql命令,返回结果通过一个vector回到WorldRunnable,Update的时候得到处理。
typedef std::pair SqlResultPair;
std::vector m_queries;
阅读(1016) | 评论(0) | 转发(0) |