diy数据库(十一)--diydb的运行时模块

来源:互联网 发布:三峡大学网络教育 编辑:程序博客网 时间:2024/06/16 12:33

一、运行时模块(RNT)

        运行时模块是真正的业务处理模块,用于处理解析完成后的请求。它主要依赖索引模块(IXM)和数据管理模块(DMS)来处理请求。上层模块不能绕过RNT来调用IXM和DMS中的功能。《diy数据库(一)--概况》中对模块间的关系有比较清楚的说明。


二、RNT的实现

好吧,diydb的RNT实现非常简单,代码是最好的解释

Rtn.hpp

#ifndef RTN_HPP__#define RTN_HPP__#include "bson.h"#include "dms.hpp"#include "ixmBucket.hpp"class rtn{private :   dmsFile           *_dmsFile ;//数据管理模块(注意:不仅仅是数据文件)   ixmBucketManager  *_ixmBucketMgr ;//索引public :   rtn () ;   ~rtn() ;   int rtnInitialize () ;//实际上就是初始化数据管理模块和索引   int rtnInsert ( bson::BSONObj &record ) ;//将record对应的记录插入数据库   int rtnFind ( bson::BSONObj &inRecord, bson::BSONObj &outRecord ) ;//根据inRecord中的_id查找数据   int rtnRemove ( bson::BSONObj &record ) ;//将record对应的记录从数据库删除} ;#endif


Rtn.cpp

#include "core.hpp"#include "rtn.hpp"#include "pd.hpp"#include "pmd.hpp"using namespace bson ;rtn::rtn() :_dmsFile(NULL),_ixmBucketMgr(NULL){}rtn::~rtn(){   if ( _ixmBucketMgr )   {      delete _ixmBucketMgr ;   }   if ( _dmsFile )   {      delete _dmsFile ;   }}int rtn::rtnInitialize (){   int rc = DIY_OK ;      _ixmBucketMgr = new ( std::nothrow ) ixmBucketManager () ;   if ( !_ixmBucketMgr )   {      rc = DIY_OOM ;      PD_LOG ( PDERROR, "Failed to new bucket manager" ) ;      goto error ;   }      _dmsFile = new(std::nothrow) dmsFile ( _ixmBucketMgr ) ;   //_dmsFile = new(std::nothrow) dmsFile () ;   if ( !_dmsFile )   {      rc = DIY_OOM ;      PD_LOG ( PDERROR, "Failed to new dms file" ) ;      goto error ;   }      rc = _ixmBucketMgr->initialize () ;   if ( rc )   {      PD_LOG ( PDERROR, "Failed to call bucketMgr initialize, rc = %d", rc ) ;      goto error ;   }      // init dms//dms的初始化   rc = _dmsFile->initialize ( pmdGetKRCB()->getDataFilePath () ) ;   if ( rc )   {      PD_LOG ( PDERROR, "Failed to call dms initialize, rc = %d", rc ) ;      goto error ;   }done :   return rc ;error :   goto done ;}int rtn::rtnInsert ( BSONObj &record ){   int rc = DIY_OK ;//本身对rtn的insert,find和remove要加读写锁   dmsRecordID recordID ;   BSONObj outRecord ;   // check if _id exists      rc = _ixmBucketMgr->isIDExist ( record ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call isIDExist, rc = %d", rc ) ;      // write data into file   rc = _dmsFile->insert ( record, outRecord, recordID ) ;   if ( rc )   {      PD_LOG ( PDERROR, "Failed to call dms insert, rc = %d", rc ) ;      goto error ;   }      rc = _ixmBucketMgr->createIndex ( outRecord, recordID ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call ixmCreateIndex, rc = %d", rc ) ;   done :   return rc ;error :   goto done ;}int rtn::rtnFind ( BSONObj &inRecord, BSONObj &outRecord ){   int rc = DIY_OK ;   dmsRecordID recordID ;   rc = _ixmBucketMgr->findIndex ( inRecord, recordID ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call ixm findIndex, rc = %d", rc ) ;   rc = _dmsFile->find ( recordID, outRecord ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call dms find, rc = %d", rc ) ;done :   return rc ;error :   goto done ;}int rtn::rtnRemove ( BSONObj &record ){   int rc = DIY_OK ;   dmsRecordID recordID ;   rc = _ixmBucketMgr->removeIndex ( record, recordID ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call ixm removeIndex, rc = %d", rc ) ;   rc = _dmsFile->remove ( recordID ) ;   PD_RC_CHECK ( rc, PDERROR, "Failed to call dms remove, rc = %d", rc ) ;done :   return rc ;error :   goto done ;}
注意:看到这里,细心的朋友也许会发现diydb的RNT中有个bug,diydb的索引中,每个桶有个读写锁,而且数据管理模块在往数据文件中增删查数据时会加个全局的读写锁,你以为这样就够了吗?举个例子,假如一个工作线程A在执行rtnFind函数,这个时候他已经在索引中找到了要查的数据在数据文件中的记录id(即数据在数据文件中的页号和槽号),这个时候,他会按照这个记录id去读数据文件中的数据,但是这个时候如果另一个线程B在A读数据之前删除了数据库文件中的那条数据,那么,线程A就出错了。所以,简单粗暴的办法就是在RNT的操作中加读写锁,好吧,这个锁的粒度真是太大了。


三、总结

1、到这里diydb的单机部分总算是看完了,我get到的代码也只有单机部分,后续会将所有单机部分的注释版代码放到我github上。麻雀虽小,五脏俱全嘛。把diydb当做一个C++服务器去学习,还是有很多看点的。

2、另外,我在单机版本基础上增加了基于一致hash的数据分片功能,即基于一致性hash的多机机制,不过目前动态增删服务器节点还没有实现,等实现后也会放到github上。

注释版代码:http://git.oschina.net/superlike/diydb-annotation




0 0
原创粉丝点击