Chinaunix首页 | 论坛 | 博客
  • 博客访问: 331109
  • 博文数量: 100
  • 博客积分: 2620
  • 博客等级: 少校
  • 技术积分: 920
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-16 02:50
文章分类

全部博文(100)

文章存档

2011年(5)

2010年(12)

2009年(83)

分类:

2009-12-18 22:30:48

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) |
0

上一篇:mangosd 之 Log

下一篇:mangosd 之 CliRunnable

给主人留下些什么吧!~~