Buffer.cpp
上传用户:lkd6667
上传日期:2015-05-13
资源大小:1448k
文件大小:21k
源码类别:

其他数据库

开发平台:

C/C++

  1. #include "Buffer.h"
  2. _M_Buffer  Buffer;
  3. unsigned int SizeOfPageHead = sizeof(_TB_PAGEHEAD);
  4. unsigned int BTreeNodeSize = (FILE_PAGESIZE - SizeOfPageHead)/4;
  5. //////////////////////////////////////////////////////////////////
  6. //初始化文件页的头信息
  7. void _TB_PAGEHEAD::Initial(unsigned long mypageid,bool myisfixed)
  8. {
  9. this->ulPageID = mypageid;
  10. this->bIsFixed = myisfixed;
  11. }
  12. //////////////////////////////////////////////////////////////////
  13. //初始化文件头信息
  14. void _TB_FILECOND::InitialFileCond()
  15. {
  16.     this->ulPageTotal = 1;
  17.     this->DelFirst.Initialize();
  18.     this->DelLast.Initialize();
  19.     this->NewInsert.ulFilePageID = 1;
  20.     this->NewInsert.uiOffset = SizeOfPageHead;
  21. }
  22. //////////////////////////////////////////////////////////////////
  23. //class _M_Page
  24. //取得文件头信息
  25. _TB_FILECOND* _M_Page::Ptr2FileCond()
  26. {
  27.     return (_TB_FILECOND* )((char*)this->Ptr2PageBegin + SizeOfPageHead);
  28. }
  29. //构造函数
  30. _M_Page::_M_Page()
  31. {
  32. this->Ptr2PageBegin = malloc(FILE_PAGESIZE);
  33.     if(!this->Ptr2PageBegin)  throw 1000;   // 内存开辟失败
  34. this->Ptr2Head = (_TB_PAGEHEAD*)this->Ptr2PageBegin;
  35. this->ulFilePageID = 0;
  36. this->uiFileID = 0;
  37. }
  38. //析构函数
  39. _M_Page::~_M_Page()
  40. {
  41.     this->ulFilePageID = 0;
  42. this->uiFileID = 0;
  43. free(this->Ptr2PageBegin);
  44.     this->Ptr2Head = 0;
  45.     this->Ptr2PageBegin = 0;
  46. }
  47. //把内存中的页写回到文件中
  48. void _M_Page::Back2File() const
  49. {
  50.     int temp = 0;
  51. temp = lseek(Buffer.GetPtr2File(this->uiFileID),this->ulFilePageID*FILE_PAGESIZE,0);
  52.     if(temp==-1L) throw 1005; 
  53. temp = write(Buffer.GetPtr2File(this->uiFileID),this->Ptr2PageBegin,FILE_PAGESIZE); // 写回文件
  54.     if(temp!= FILE_PAGESIZE) throw 1002;  // 写失败
  55. }
  56. //从文件中调入页至开辟好的内存空间中
  57. void _M_Page::LoadFromFile(unsigned int fileid, unsigned long filepageid)
  58. {
  59.     this->uiFileID = fileid;
  60.     this->ulFilePageID = filepageid;
  61.     if( Buffer.GetIsNew(fileid) )   //  文件新建,只有一个页
  62.     {
  63.         this->Ptr2Head->Initial(filepageid,1);   // 初始化页头信息
  64.         this->Ptr2FileCond()->InitialFileCond(); // 初始化文件头信息
  65.         Buffer.SetIsNew(fileid,0);               // 设置使文件不再为新建状态(以免下次访问这个内存页又要进行头信息初始化)
  66.     }
  67. //文件页是新建的,不是新建文件
  68.     else if( filepageid >= Buffer.GetPageTotal(fileid) ) // 比现有文件总页面要多,那么开辟新的页面加到文件末尾
  69.     {
  70.         if( filepageid - Buffer.GetPageTotal(fileid) > 0) 
  71. {
  72. //cout<<"";
  73. throw 1004; // 页编号比现有文件最后一个页编号+1 还要大(浪费磁盘空间)
  74. }
  75.         this->Ptr2Head->Initial(filepageid,0);   // 初始化页头信息
  76.         Buffer.AddPageTotal(fileid,1);           // 使文件总页数加1
  77.     }
  78. // 其他情况从磁盘中读信息
  79.     else     
  80.     {
  81. // 定位到将要取出的文件页的首地址
  82.     lseek(Buffer.GetPtr2File(fileid),filepageid*FILE_PAGESIZE,0); 
  83. // 读到内存中
  84.     int temp = read(Buffer.GetPtr2File(fileid),this->Ptr2PageBegin,FILE_PAGESIZE); 
  85.         if( temp!= FILE_PAGESIZE)  
  86. {
  87. //cout<<"
  88. throw 1031; // 读失败
  89. //return;
  90. }
  91.     }
  92. }
  93. //////////////////////////////////////////////////////////////////
  94. //class _M_Clock
  95. //construct _M_Clock 成员初始化
  96. _M_Clock::_M_Clock()
  97. {
  98. uiClockSize=MEM_PAGEAMOUNT;
  99. uiCurrClockPtr=1;
  100. for(int i=0;i<=MEM_PAGEAMOUNT;i++)
  101. {
  102. Ptr2MemPageInfo[i]= new  _M_PageInfo;
  103. }
  104. }
  105. //destruct  _M_Clock  析构
  106. _M_Clock::~_M_Clock()
  107. {
  108. for(unsigned int i=0;i<=this->uiClockSize;i++)
  109. delete  Ptr2MemPageInfo[i];
  110. }
  111. //查找Clock中尚未分配内存空间的页
  112. unsigned int _M_Clock::GetNullPage()
  113. {
  114.     for(unsigned int i=this->uiCurrClockPtr;i<=this->uiClockSize;i++)
  115.     {
  116.         if( !this->Ptr2MemPageInfo[i]->Ptr2Page ) // 尚未分配内存页
  117.         {
  118.             this->uiCurrClockPtr = i;
  119.             return this->uiCurrClockPtr;
  120.         }
  121.     }
  122.     return 0;
  123. }
  124. //查找Clock中已经被抛弃的页
  125. unsigned int _M_Clock::GetFreePage()
  126. {
  127.     for(unsigned int i=1;i<=this->uiClockSize;i++)
  128.     {
  129.         // 被抛弃内存页已经把文件编号置为 0 做为标记
  130.         if( this->Ptr2MemPageInfo[i]->Ptr2Page && !this->Ptr2MemPageInfo[i]->GetFileID() )
  131.         {
  132.             this->uiCurrClockPtr = i;
  133.             return this->uiCurrClockPtr;
  134.         }
  135.     }
  136.     return 0;
  137. }
  138. // 查找Clock中最近一页可被替换的页
  139. unsigned int _M_Clock::GetSwapPage(unsigned int fileid)
  140. {
  141.     if(! this->GetFreePage() )   // 查找被抛弃的内存页
  142.         // 查找Clock中最早打开的文件所占用的内存页,如果是常驻内存页则关闭该文件(该写回的写回)
  143.     if(! this->NR_Search(fileid) )
  144.     if(! this->U_M_Search(0,0,0) ) // 上次没有用,没有被修改,不变动bIsLastUsed,返回符合这样条件的内存页
  145.     if(! this->U_M_Search(0,1,1) ) // 上次没有用,有被修改,变动bIsLastUsed,返回符合这样条件的内存页
  146.     if(! this->U_M_Search(0,0,0) ) // 上次没有用,没有被修改,不变动bIsLastUsed,返回符合这样条件的内存页
  147.      this->U_M_Search(0,1,1);  // 上次没有用,有被修改,变动bIsLastUsed,返回符合这样条件的内存页
  148. return this->uiCurrClockPtr;
  149. }
  150. // 查找Clock中最早打开的文件所占用的内存页,如果是常驻内存页则关闭该文件(该写回的写回)
  151. // 所有打开的文件已经由_M_Buffer类组织成链表
  152. unsigned int _M_Clock::NR_Search(unsigned int tarfileid)
  153. {
  154.     unsigned int NR_FileIDTemp = 0;     // 临时文件编号
  155.     unsigned int NR_FileID = 20000;     // 欲替换的内存页所属文件编号(程序运行期分配),20000为不可能的一个数字(打开20000个文件方有可能)
  156.     unsigned int ClockPtr = 0;          // 与替换的页编号
  157.     unsigned int relativefileid = Buffer[tarfileid]->GetRelativeFileID(); // 取得关联文件编号
  158. for(unsigned int i=1;i<=this->uiClockSize;i++)
  159. {
  160.         NR_FileIDTemp = this->Ptr2MemPageInfo[i]->GetFileID();
  161.         // 文件编号不能为当前文件编号及其关联文件的编号,在符合这个条件的基础上,文件编号越小,越早打开,所以更适合被替换
  162. if( NR_FileIDTemp < NR_FileID && NR_FileIDTemp != tarfileid && NR_FileIDTemp != relativefileid )
  163.         {
  164.             NR_FileID = NR_FileIDTemp;
  165.             ClockPtr = i;
  166.         }
  167. }
  168.     if( NR_FileID != 20000 )
  169.     {
  170.         // 如果被替换页是第 0 页,则关闭该文件及其关联文件
  171.         if( this->Ptr2MemPageInfo[ClockPtr]->GetFilePageID() == 0 )
  172.             Buffer[NR_FileID]->Close();
  173.         this->uiCurrClockPtr = ClockPtr;
  174.         return this->uiCurrClockPtr;
  175.     }
  176.     else
  177.     return 0;
  178. }
  179. // Clock算法实现,通过U_M_Search()四次调用,完成Clock算法
  180. unsigned int _M_Clock::U_M_Search(bool islastused,bool ismodified,bool changeused)
  181. {
  182. for(unsigned int i=1;i<=this->uiClockSize;i++)
  183. {
  184. if( this->Ptr2MemPageInfo[this->uiCurrClockPtr]->GetPtr2Head()->bIsFixed == 0 &&
  185. this->Ptr2MemPageInfo[this->uiCurrClockPtr]->bIsLastUsed == islastused &&
  186. this->Ptr2MemPageInfo[this->uiCurrClockPtr]->bIsModified == ismodified )
  187. return this->uiCurrClockPtr;
  188. else
  189. {
  190. if( changeused ) this->Ptr2MemPageInfo[this->uiCurrClockPtr]->bIsLastUsed = 0;
  191. this->uiCurrClockPtr = (this->uiCurrClockPtr+1)%this->uiClockSize;
  192. if(!this->uiCurrClockPtr)
  193. this->uiCurrClockPtr = this->uiClockSize;
  194. }
  195. }
  196. return 0;
  197. }
  198. // 查找已经存在的页(假设要找的页已经存在的话)
  199. unsigned int _M_Clock::GetExsitPage(unsigned int fileid,unsigned long filepageid)
  200. {
  201. if( this->Ptr2MemPageInfo[this->uiCurrClockPtr]->Ptr2Page &&
  202. this->Ptr2MemPageInfo[this->uiCurrClockPtr]->GetFileID() == fileid &&
  203. this->Ptr2MemPageInfo[this->uiCurrClockPtr]->GetFilePageID() == filepageid )
  204. return this->uiCurrClockPtr;
  205. for(unsigned int i=1;i<=this->uiClockSize;i++)
  206. {
  207.         if(!this->Ptr2MemPageInfo[i]->Ptr2Page) break;
  208. if( this->Ptr2MemPageInfo[i]->GetFileID() == fileid &&
  209. this->Ptr2MemPageInfo[i]->GetFilePageID() == filepageid )
  210. {
  211. this->uiCurrClockPtr = i;
  212. return this->uiCurrClockPtr;
  213. }
  214. }
  215. return 0;
  216. }
  217. // 根据文件编号和页号取得内存页(通过上面各种方法)
  218. _M_PageInfo* _M_Clock::GetTargetPage(unsigned int fileid,unsigned long filepageid)
  219. {
  220.     unsigned int tempint = this->GetExsitPage(fileid,filepageid);  // 先找内存页是否已经存在
  221. if(tempint) return this->Ptr2MemPageInfo[tempint];
  222. tempint = this->GetNullPage();         // 看看有没有空的内存页尚未开辟使用
  223.     if(!tempint) tempint = this->GetSwapPage(fileid); // 得到替换页
  224. this->Ptr2MemPageInfo[tempint]->UpdatePageInfo(fileid,filepageid); // 调入文件页至内存,并更新相关信息
  225.     return this->Ptr2MemPageInfo[tempint];
  226. }
  227. //关闭内存中的文件页 文件id==fileid
  228. void _M_Clock::CloseFilePages(unsigned int fileid)
  229. {
  230. for(unsigned int i=1;i<this->uiClockSize;i++)
  231. {
  232. if( !this->Ptr2MemPageInfo[i]->Ptr2Page ) break;
  233. if(Ptr2MemPageInfo[i]->GetFileID()==fileid)
  234. {
  235. //如果是dirty data写回磁盘 并将 ifmodified 改回0;
  236. if(Ptr2MemPageInfo[i]->bIsModified)
  237. {
  238. Ptr2MemPageInfo[i]->Ptr2Page->Back2File();
  239. Ptr2MemPageInfo[i]->bIsModified=0;
  240. }
  241. //放弃内存页的使用
  242. this->Ptr2MemPageInfo[i]->SetFileID(0);
  243. }
  244. }
  245. }
  246. // 设置当前页使之为脏页
  247. void _M_Clock::SetPageModified()
  248. {
  249.     this->Ptr2MemPageInfo[this->uiCurrClockPtr]->bIsModified = 1;
  250. }
  251. ///////////////////////////////////////////////////////////////////////////////////////
  252. //class _M_PageInfo
  253. //构造函数,初始化成员
  254. _M_PageInfo::_M_PageInfo()
  255. {
  256. this->bIsLastUsed = 0;
  257. this->bIsModified = 0;
  258. this->Ptr2Page = 0;
  259. }
  260. // 析构,根据bIsModified决定是否需要写会文件
  261. _M_PageInfo::~_M_PageInfo()
  262. {
  263.     if(this->Ptr2Page){
  264.         if(this->Ptr2Page->uiFileID && this->Ptr2Page->ulFilePageID==0)
  265.             // 把文件页总数写到磁盘中,已备下次读取
  266.             this->Ptr2Page->Ptr2FileCond()->ulPageTotal = Buffer.GetPageTotal(this->Ptr2Page->uiFileID);
  267.         if(this->Ptr2Page->uiFileID && this->bIsModified){ // 若为脏页,写回
  268.             this->Ptr2Page->Back2File();
  269.         }
  270.         delete this->Ptr2Page;
  271.         this->Ptr2Page = 0;
  272.     }
  273.     this->bIsLastUsed = 0;
  274.     this->bIsModified = 0;
  275. }
  276. // 页替换、开辟等
  277. void _M_PageInfo::UpdatePageInfo(unsigned int fileid,unsigned long filepageid)
  278. {
  279. if( this->bIsModified) // 若为脏页,写回
  280. this->Ptr2Page->Back2File();
  281. this->bIsLastUsed = 1;
  282. this->bIsModified = 0;
  283.     if( !this->Ptr2Page ){ // 尚未开辟内存空间
  284. this->Ptr2Page = new _M_Page; // 新的内存页对象
  285.     }
  286.     
  287.     // 若文件新建 或者 该页为文件第0页 后者 该页在原来文件中不存在 则要求写回
  288.     if( Buffer.GetIsNew(fileid) || filepageid >= Buffer.GetPageTotal(fileid) || filepageid==0 )
  289.         this->bIsModified = 1;
  290.     
  291. this->Ptr2Page->LoadFromFile(fileid,filepageid);  // 读到内存中
  292. }
  293. // 取得文件头信息地址
  294. _TB_FILECOND* _M_PageInfo::GetPtr2FileCond() const
  295. {
  296.     return this->Ptr2Page->Ptr2FileCond();
  297. }
  298. // 取得页头信息地址
  299. _TB_PAGEHEAD* _M_PageInfo::GetPtr2Head() const
  300. {
  301.     return this->Ptr2Page->Ptr2Head;
  302. }
  303. // 取得所分配的内存页目前内容所属的文件编号
  304. unsigned int _M_PageInfo::GetFileID() const
  305. {
  306.     return this->Ptr2Page->uiFileID;
  307. }
  308. // 设置新的文件编号(抛弃页时设为0即可)
  309. void _M_PageInfo::SetFileID(unsigned int fileid)
  310. {
  311.   this->Ptr2Page->uiFileID = fileid;
  312. }
  313. // 取得所分配的内存页目前内容在文件中的页编号
  314. unsigned long _M_PageInfo::GetFilePageID() const
  315. {
  316.     return this->Ptr2Page->ulFilePageID;
  317. }
  318. ///////////////////////////////////////////////////////////////////////////////////////
  319. //class _M_File
  320. // 初始化,打开和新建文件,若当前文件开的太多,导致无法再打开新文件,可自动关闭最早打开的文件
  321. _M_File::_M_File(const char *name,unsigned int fileid)
  322. {
  323. this->uiFileID = fileid;
  324.         this->IsNew = 0;
  325.         this->ulPageTotal = 1;
  326. strcpy(this->FileName,name);
  327. this->Ptr2File = open(name,_O_BINARY|O_RDWR,0664); 
  328.         if(this->Ptr2File==-1){ // 文件不存在
  329.             this->Ptr2File = open(name,_O_BINARY|O_RDWR|O_CREAT,0664); // 新建文件(打开文件)
  330.             if(this->Ptr2File==-1)  // 文件不能被打开(新建)
  331.             {
  332.                 if( Buffer._F_First) 
  333.                     Buffer._F_First->Close(); // 关闭最早打开的文件
  334.                 this->Ptr2File = open(name,_O_BINARY|O_RDWR|O_CREAT,0664); // 新建文件(打开文件)
  335.     if(this->Ptr2File==-1)  // 文件不能被新建(打开)
  336.                     throw 1006; // 文件还是不能被打开(新建),可能为磁盘空间不足等意外
  337.             }
  338.             this->IsNew = 1;
  339.         }
  340. this->_F_Next = 0;
  341. }
  342. //取相关文件
  343. unsigned int _M_File::GetRelativeFileID() const
  344. {
  345. int FNLength =strlen(this->FileName);//记录文件名长度,以便修改文件扩展名
  346. char FNTemp1[MAX_FILENAME_LEN];//存文件名
  347. char FNTemp2[MAX_FILENAME_LEN];
  348. strcpy(FNTemp1,this->FileName);
  349. FNTemp1[FNLength-3]='';//除去扩展名
  350. _M_File * pMFTemp;
  351. pMFTemp=Buffer._F_First;
  352. while(pMFTemp)//对所有打开文件进行搜索
  353. {
  354. strcpy(FNTemp2,pMFTemp->FileName);
  355. FNTemp2[FNLength-3]='';//除去扩展名
  356. if((strcmp(FNTemp1,FNTemp2)==0)&&(pMFTemp->uiFileID!=this->uiFileID))
  357. return pMFTemp->uiFileID;
  358. pMFTemp=pMFTemp->_F_Next;
  359. }
  360. //error
  361. //throw:没有找到相关文件
  362. return 0;
  363. }
  364. // 析构,关闭文件
  365. void _M_File::Deconstruct()
  366. {
  367.     if(this->Ptr2File)
  368.         close(this->Ptr2File);
  369. }
  370. // 关闭文件,同时属于该文件的内存页改写回的写回.为保证一致性,同时关闭关联文件
  371. void _M_File::Close()
  372. {
  373. Buffer.CloseTable(this->uiFileID);
  374. }
  375. // 根据页号取得属于该文件的内存页
  376. _M_PageInfo* _M_File::GetPageInfo(unsigned long filepageid) const
  377. {
  378.     return Buffer.MemPageClock->GetTargetPage(this->uiFileID,filepageid);
  379. }
  380. // 取得目前总的页数
  381. unsigned long _M_File::GetPageTotal() const
  382. {
  383.       return this->ulPageTotal;
  384. }
  385. // 取得文件内记录删除维护信息
  386. _F_FileAddr _M_File::GetDelListCond() const
  387. {
  388.     _F_FileAddr temp;
  389.     temp.ulFilePageID = 0;
  390.     temp.uiOffset = SizeOfPageHead;
  391.     return temp;
  392. }
  393. // 取得Catalog模块在文件中可写的第一个位置
  394. _F_FileAddr _M_File::GetCataPoint() const
  395. {
  396.     _F_FileAddr temp;
  397.     temp.ulFilePageID = 0;
  398.     temp.uiOffset = SizeOfPageHead + sizeof(_TB_FILECOND);
  399.     return temp;
  400. }
  401. // 取得Catalog模块在文件中可写的第一个位置
  402. _F_FileAddr _M_File::GetIdxPoint() const
  403. {
  404.     _F_FileAddr temp;
  405.     temp.ulFilePageID = 0;
  406.     temp.uiOffset = SizeOfPageHead + sizeof(_TB_FILECOND);
  407.     return temp;
  408. }
  409. ///////////////////////////////////////////////////////////////////////////////////////
  410. //_F_FileAddr
  411. //初始化
  412. void _F_FileAddr::Initialize()
  413. {
  414.     this->ulFilePageID = 0;
  415.     this->uiOffset = 0;
  416. }
  417. //根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
  418. //根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
  419. void* _F_FileAddr::MemAddr() const
  420. {
  421.  if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
  422. return (void*)((char*)Buffer._F_Current->GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
  423. }
  424. //根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
  425. void* _F_FileAddr::MemAddr(_M_File *TargetMFile) const
  426. {
  427. if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
  428. return (void*)((char*)TargetMFile->GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
  429. }
  430. //根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
  431. void* _F_FileAddr::MemAddr(_M_File &TargetMFile) const
  432. {
  433. if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
  434. return (void*)((char*)TargetMFile.GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
  435. }
  436. // _F_FileAddr >= 操作
  437. bool _F_FileAddr::operator>=(_F_FileAddr& other) const
  438. {
  439. if( (this->ulFilePageID > other.ulFilePageID) || (this->uiOffset >= other.uiOffset && this->ulFilePageID >= other.ulFilePageID))
  440. return true;
  441. return false;
  442. }
  443. // _F_FileAddr > 操作
  444. bool _F_FileAddr::operator>(_F_FileAddr& other) const
  445. {
  446. if( (this->ulFilePageID > other.ulFilePageID) || (this->uiOffset > other.uiOffset && this->ulFilePageID >= other.ulFilePageID))
  447. return true;
  448. return false;
  449. }
  450. // _F_FileAddr == 操作
  451. bool _F_FileAddr::operator==(_F_FileAddr& other) const
  452. {
  453. if((this->ulFilePageID == other.ulFilePageID) && (this->uiOffset == other.uiOffset))
  454. return true;
  455. return false;
  456. }
  457. // _F_FileAddr != 操作
  458. bool _F_FileAddr::operator!=(_F_FileAddr& other) const
  459. {
  460. if((this->ulFilePageID != other.ulFilePageID) || (this->uiOffset != other.uiOffset))
  461. return true;
  462. return false;
  463. }
  464. // _F_FileAddr == const int 操作只对0操作
  465. bool _F_FileAddr::operator==(const int zero) const
  466. {
  467. if( (this->ulFilePageID==0) &&( this->uiOffset==0) )
  468. return true;
  469. return false;
  470. }
  471. //在当前页中滑动offset量(可正可负)
  472. void _F_FileAddr::ShiftOffset(int offset)
  473. {
  474. int temp=(int)this->uiOffset+offset;
  475. //if temp <0 出错
  476. this->uiOffset =(unsigned int) temp;
  477. }
  478. /////////////////////////////////////////////////////////////////////////////////////////
  479. //class _M_Buffer
  480. // Buffer初始化
  481. void _M_Buffer::Start()
  482. {
  483.     if( MEM_PAGEAMOUNT < 3) throw 1033; // 至少要求有 3 页,2页头信息(目录管理和索引管理各一页),另外 1 页记录存取
  484. this->_F_First = 0;
  485. this->_F_Last = 0;
  486.     this->_F_Current = 0;
  487. this->uiFileCount = 0;
  488.     this->MemPageClock = new _M_Clock();
  489. }
  490. // Buffer结束,写回内存页,关闭文件
  491. void _M_Buffer::End()
  492. {
  493.     delete this->MemPageClock;
  494.     this->_F_Last = 0;
  495.     this->uiFileCount = 0;
  496. _M_File* temp = this->_F_First;
  497.     this->_F_First = 0;
  498.     _M_File* temp2 = 0;
  499. while(temp)
  500. {
  501. temp2 = temp->_F_Next;
  502.         temp->Deconstruct();
  503. temp = temp2;
  504. }
  505. }
  506. // 根据文件编号返回内存文件对象是否为新建
  507. bool _M_Buffer::GetIsNew(unsigned int fileid) const
  508. {
  509.     return (*this)[fileid]->IsNew;
  510. }
  511. // 根据文件编号设置内存文件对象是否为新建
  512. void _M_Buffer::SetIsNew(unsigned int fileid,bool isnew)
  513. {
  514.     (*this)[fileid]->IsNew = isnew;
  515. }
  516. unsigned long _M_Buffer::GetPageTotal(unsigned int fileid) const
  517. {
  518.     return (*this)[fileid]->ulPageTotal;
  519. }
  520. void _M_Buffer::AddPageTotal(unsigned int fileid,int add)
  521. {
  522.     (*this)[fileid]->ulPageTotal += add;
  523. }
  524. int _M_Buffer::GetPtr2File(unsigned int fileid) const
  525. {
  526.     return (*this)[fileid]->Ptr2File;
  527. }
  528. // 根据文件编号返回内存文件对象
  529. _M_File* _M_Buffer::operator [](unsigned int fileid) const
  530. {
  531. //Error Dispatch 0< fileid <= Buffer->uiFileCount
  532.     _M_File* temp = 0;
  533.     _M_File* temp2 = this->_F_First;
  534.     while( temp2 )
  535.     {
  536.         if( temp2->uiFileID == fileid ){
  537.             temp = temp2;
  538.             break;
  539.         }
  540.         temp2 = temp2->_F_Next;
  541.     }
  542. return temp;
  543. }
  544. //找到文件名为filename的_M_File
  545. _M_File _M_Buffer::operator [](const char* filename)
  546. {
  547. //先找当前文件,概率比较大
  548. if( this->_F_Current && strcmp(filename,this->_F_Current->FileName)==0)
  549.         return *(this->_F_Current);
  550. _M_File * pMFTemp;
  551. pMFTemp = this->_F_First;
  552. while(pMFTemp)                    //对所有打开文件进行遍历
  553. {
  554. if(strcmp(filename,pMFTemp->FileName)==0)
  555. {
  556. this->_F_Current=pMFTemp;
  557. return *pMFTemp;            //找到返回文件信息并将当前Buffer的指针针向当前文件
  558. }
  559. pMFTemp=pMFTemp->_F_Next;
  560. }
  561. //在打开文件中没有要找的文件开始如下操作
  562. pMFTemp = new _M_File(filename,++this->uiFileCount);
  563. if(!this->_F_First)//没有文件打开
  564. this->_F_First=this->_F_Last=pMFTemp;
  565. else
  566. {
  567. this->_F_Last->_F_Next=pMFTemp;
  568. this->_F_Last=pMFTemp;
  569. }
  570. this->_F_Current=pMFTemp;
  571. if(pMFTemp->IsNew)
  572. this->MemPageClock->GetTargetPage(pMFTemp->uiFileID,0);
  573. else //将文件的总页数读到_M_File 中
  574. pMFTemp->ulPageTotal=this->MemPageClock->GetTargetPage(pMFTemp->uiFileID,0)->GetPtr2FileCond()->ulPageTotal;
  575. return *pMFTemp;
  576. }
  577. // 根据文件编号关闭内存文件对象
  578. void _M_Buffer::CloseFile(unsigned int fileid)
  579. {
  580. this->MemPageClock->CloseFilePages(fileid);
  581. _M_File* temp = this->_F_First;
  582. _M_File* temp2 = 0;
  583. while(temp->uiFileID != fileid)
  584. {
  585. temp2 = temp;
  586. temp = temp->_F_Next;
  587. }
  588. if( temp == this->_F_First )
  589. this->_F_First = this->_F_First->_F_Next;
  590. else
  591. temp2->_F_Next = temp->_F_Next;
  592. temp->Deconstruct();
  593. }
  594. void _M_Buffer::CloseTable(unsigned int fileid)
  595. {
  596.     unsigned int tempfileid = (*this)[fileid]->GetRelativeFileID();
  597.     if( tempfileid )
  598.         this->CloseFile(tempfileid);
  599.     this->CloseFile(fileid);
  600. }
  601. //根据欲写入的文件地址,把其他模块内存中的数据写入buffer中,最终自动写入文件中
  602. _F_FileAddr MemWrite(const void* source,size_t length,_F_FileAddr* dest)
  603. {
  604.     if( (int)(FILE_PAGESIZE - dest->uiOffset) - (int)length < 0) // 判断是否溢出
  605.     {
  606.         dest->ulFilePageID = Buffer._F_Current->GetPageTotal(); // 若溢出修正 dest
  607. //Buffer.MemPageClock->GetTargetPage(Buffer._F_Current->uiFileID,dest->ulFilePageID);
  608.         dest->uiOffset = sizeof(_TB_PAGEHEAD);
  609.     }
  610.     memcpy(dest->MemAddr(),source,length);
  611.     Buffer.MemPageClock->SetPageModified();
  612.     _F_FileAddr end = *dest;
  613.     end.ShiftOffset((int)length);
  614.     return end;
  615. }
  616. //根据欲写入的文件地址,测试把其他模块内存中的数据写入实际未写入。
  617. _F_FileAddr MemWriteTest(size_t length,_F_FileAddr* dest)
  618. {
  619. if((int)(FILE_PAGESIZE - dest->uiOffset) - (int)length < 0) // 判断是否溢出
  620.    {
  621. dest->ulFilePageID = Buffer._F_Current->GetPageTotal(); // 若溢出修正 dest
  622. dest->uiOffset = SizeOfPageHead;
  623. }
  624. _F_FileAddr end = *dest;
  625. end.ShiftOffset((int)length);
  626. return end;
  627. }