?? buffer.h
字號:
/******************************************************************
** 文件名: Buffer.h
** Copyright (c) 2001-2002 計算機99F MiniSQL開發小組其一
** 創建人: 郭振宇
** 日 期: 2001-11-28
** 修改人: 郭振宇
** 日 期: 2002-01-05
** 描 述: 申明了MiniSQL buffer模塊所有類和結構,為保證類
方法私有(未經授權不允訪問),多申明為私有,授
權采用申明友元類,友元函數的方法
** 版 本: 1.00
******************************************************************/
#ifndef _BUFFER_H_
#define _BUFFER_H_
//-------------------------------------------------------
extern "C"{
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
};
//-------------------------------------------------------
#define FILE_PAGESIZE 4096 // 內存頁大小
#define MEM_PAGEAMOUNT 1000 // 內存頁數量
#ifndef MAX_FILENAME_LEN
#define MAX_FILENAME_LEN 256 // 文件(包含路徑)最大長度
#endif
//-------------------------------------------------------
/*********************************************************
* 頁頭信息,用以標識文件頁
**********************************************************/
typedef struct {
unsigned long ulPageID; // 頁編號
bool bIsFixed; // 頁是否常駐內存
void Initial(unsigned long mypageid,bool myisfixed); // 初始化操作
}_TB_PAGEHEAD;
//-------------------------------------------------------
/*********************************************************
* 文件內地址(相當于內存地址),用以標識數據在文件中
* 的具體存放地址,做為對象可持續化的一個重要一環,通
* 過調用其中的MemAddr()方法可以得到數據在內存中的地址
* 是整個buffer模塊成功與其他模塊整合的關鍵
**********************************************************/
class _F_FileAddr{
public:
unsigned long ulFilePageID; // 頁編號
unsigned int uiOffset; // 頁內偏移量
void Initialize(); // 初始化 (0,0)
//**根據頁編號和偏移量,取出當前文件該地址在內存中的地址,同時測試頁偏移量是否溢出
void* MemAddr() const;
//**根據頁編號和偏移量,取出文件該地址在內存中的地址,同時測試頁偏移量是否溢出
void* MemAddr(class _M_File&) const;
//**根據頁編號和偏移量,取出文件該地址在內存中的地址,同時測試頁偏移量是否溢出
void* MemAddr(class _M_File*) const;
bool operator>=(_F_FileAddr& other) const; // _F_FileAddr >= 操作
bool operator> (_F_FileAddr& other) const; // _F_FileAddr > 操作
bool operator==(_F_FileAddr& other) const; // _F_FileAddr == 操作
bool operator!=(_F_FileAddr& other) const; // _F_FileAddr != 操作
bool operator==(const int zero) const; // _F_FileAddr == 操作
//**在當前頁中滑動offset量(可正可負)
void ShiftOffset(int offset);
};
//-------------------------------------------------------
/*********************************************************
* 文件頭信息
**********************************************************/
typedef struct{
_F_FileAddr DelFirst; // 第一條被刪除記錄地址
_F_FileAddr DelLast; // 最后一條被刪除記錄地址
_F_FileAddr NewInsert; // 文件末尾可插入新數據的地址
unsigned long ulPageTotal; // 目前文件中共有頁數
void InitialFileCond(); // 初始化
}_TB_FILECOND;
//-------------------------------------------------------
/*********************************************************
* 內存頁,用以從文件中讀取頁和往文件中寫回頁
* 同時也提供頁頭信息等相關信息
**********************************************************/
class _M_Page{
friend class _M_PageInfo;
friend class _F_FileAddr;
friend class _M_Clock;
private:
unsigned int uiFileID; // 所屬文件編號(程序動態分配)
unsigned long ulFilePageID; // 在文件中的PageID
void* Ptr2PageBegin; // 調入內存后的頁首地址
_TB_PAGEHEAD* Ptr2Head; // 頁頭信息
_TB_FILECOND* Ptr2FileCond(); // 文件頭信息(若頁PageID==0,則有,否則返回空)
_M_Page(); // 成員初始化,開辟內存空間
~_M_Page(); // 釋放內存空間
//**從文件中調入頁至開辟好的內存空間中
void LoadFromFile(unsigned int fileid,unsigned long filepageid);
//**把內存中的頁寫回到文件中
void Back2File() const;
};
//-------------------------------------------------------
/*********************************************************
* 內存頁管理信息,用以管理內存頁的開辟,釋放等
* 之所以和內存頁類分開,為在不必要的情況下可以
* 避免開辟內存頁,減少內存的浪費
**********************************************************/
class _M_PageInfo{
friend class _M_Clock;
friend class _F_FileAddr;
friend class _M_Buffer;
private:
bool bIsLastUsed; // 最近一次訪問內存是否被使用,用于Clock算法
bool bIsModified; // 從調入內存開始,是否被修改,用于決定是否需要寫會文件
class _M_Page* Ptr2Page; // 所分配的內存頁對象
_M_PageInfo(); // 成員初始化
~_M_PageInfo(); // 析構,根據bIsModified決定是否需要寫會文件
void UpdatePageInfo(unsigned int fileid,unsigned long filepageid); // 頁替換、開辟等
_TB_PAGEHEAD* GetPtr2Head() const; // 取得頁頭信息地址
_TB_FILECOND* GetPtr2FileCond() const; // 取得文件頭信息地址
unsigned int GetFileID() const; // 取得所分配的內存頁目前內容所屬的文件編號
void SetFileID(unsigned int fileid); // 設置新的文件編號(拋棄頁時設為0即可)
unsigned long GetFilePageID() const; // 取得所分配的內存頁目前內容在文件中的頁編號
};
//------------------------------------------------------------
/*********************************************************
* 內存頁置換算法實現類,采用Clock算法
* 開辟內存頁管理對象數組,每個內存頁管
* 理對象對應一個內存頁對象,需要的時候
* 才開辟,避免內存的浪費
**********************************************************/
class _M_Clock
{
friend class _M_Buffer;
friend class _M_File;
friend _F_FileAddr MemWrite(const void*,size_t,_F_FileAddr*);
private:
unsigned int uiClockSize; // 內存中頁總數,即Clock鐘點總數
unsigned int uiCurrClockPtr; // 目前正在使用的內存頁
class _M_PageInfo* Ptr2MemPageInfo[MEM_PAGEAMOUNT+1]; // 內存頁管理對象(不包含內存頁空間)
_M_Clock(); // 成員初始化
~_M_Clock(); // 析構
void SetPageModified(); // 設置當前頁使之為臟頁
void CloseFilePages(unsigned int fileid); // 關閉文件并拋棄所屬內存頁(適用于欲刪除一個文件的時候)
unsigned int GetNullPage(); // 查找Clock中尚未分配內存空間的頁
unsigned int GetFreePage(); // 查找Clock中已經被拋棄的頁
unsigned int GetSwapPage(unsigned int fileid); // 查找Clock中最近一頁可被替換的頁
// 查找Clock中最早打開的文件所占用的內存頁,如果是常駐內存頁則關閉該文件(該寫回的寫回)
// 所有打開的文件已經由_M_Buffer類組織成鏈表
unsigned int NR_Search(unsigned int tarfileid);
// Clock算法實現,通過U_M_Search()四次調用,完成Clock算法
unsigned int U_M_Search(bool islastused,bool ismodified,bool changeused);
// 查找已經存在的頁(假設要找的頁已經存在的話)
unsigned int GetExsitPage(unsigned int fileid,unsigned long filepageid);
// 根據文件編號和頁號取得內存頁(通過上面各種方法)
_M_PageInfo* GetTargetPage(unsigned int fileid,unsigned long filepageid);
};
//-------------------------------------------------------
/*********************************************************
* 內存文件類,與其他模塊的主要接口,將
* 通過此類得到欲訪問文件中的數據的內存首地址
**********************************************************/
class _M_File{
friend class _M_Buffer;
friend class _F_FileAddr;
friend class _M_Clock;
private:
unsigned int uiFileID; // 文件編號
unsigned long ulPageTotal; // 目前文件總的頁數
bool IsNew; // 該文件是否新建
char FileName[MAX_FILENAME_LEN]; // 文件名稱(包含路徑)
_M_File* _F_Next; // 下一個打開的文件
int Ptr2File; // 文件指針
void Deconstruct(); // 析構,關閉文件
_M_PageInfo* GetPageInfo(unsigned long filepageid) const; // 根據頁號取得屬于該文件的內存頁
// 初始化,打開和新建文件,若當前文件開的太多,導致無法再打開新文件,可自動關閉最早打開的文件
_M_File(const char *name,unsigned int fileid);
// 取得相關文件,由于一個表包含兩個文件(.idx,.dbf),故查找關聯的文件編號
unsigned int GetRelativeFileID() const;
public:
_F_FileAddr GetCataPoint() const; // 取得Catalog模塊在文件中可寫的第一個位置
_F_FileAddr GetIdxPoint() const; // 取得Catalog模塊在文件中可寫的第一個位置
_F_FileAddr GetDelListCond() const; // 取得文件內記錄刪除維護信息
unsigned long GetPageTotal() const; // 取得目前總的頁數
// 關閉文件,同時屬于該文件的內存頁改寫回的寫回.為保證一致性,同時關閉關聯文件
void Close();
};
//-------------------------------------------------------
/*********************************************************
* Buffer模塊管理類,包含兩部分數據的管理
* 一、內存頁的管理,通過一個_M_Clock對象實現
* 二、打開文件的管理,組織所有的文件
**********************************************************/
class _M_Buffer{
friend class _M_Page;
friend class _M_PageInfo;
friend class _M_File;
friend class _M_Clock;
friend class _F_FileAddr;
friend _F_FileAddr MemWrite(const void*,size_t,_F_FileAddr*);
friend _F_FileAddr MemWriteTest(size_t,_F_FileAddr*);
private:
unsigned int uiFileCount; // 打開文件總數
_M_File* _F_First; // 第一個文件
_M_File* _F_Last; // 最后一個文件
_M_File* _F_Current; // 當前使用文件
class _M_Clock* MemPageClock; // Clock算法實現類(管理所有內存頁)
_M_File* operator[](unsigned int fileid) const; // 根據文件編號返回內存文件對象
void CloseFile(unsigned int fileid); // 根據文件編號關閉內存文件對象
void CloseTable(unsigned int fileid); // 根據文件編號關閉內存文件對象及其關聯內存文件對象
bool GetIsNew(unsigned int fileid) const; // 根據文件編號返回內存文件對象是否為新建
void SetIsNew(unsigned int fileid,bool isnew); // 根據文件編號設置內存文件對象是否為新建
unsigned long GetPageTotal(unsigned int fileid) const; // 根據文件編號返回內存文件對象總頁數
void AddPageTotal(unsigned int fileid,int add); // 根據文件編號色設置內存文件對象的總頁數
int GetPtr2File(unsigned int fileid) const; // 根據文件編號返回內存文件對象的文件指針
public:
_M_File operator[](const char* filename); // 根據文件名稱返回內存文件對象
void Start(); // Buffer初始化
void End(); // Buffer結束,寫回內存頁,關閉文件
};
//-------------------------------------------------------
/*****************************************************************
** 函數名: MemWrite
** 輸 入: const void*,size_t,_F_FileAddr*
** const void* --- 欲寫入buffer的對象(數據)的內存地址
** size_t --- 數據總長度
** _F_FileAddr* ---文件內地址,測試判斷后,若越界、跨塊等情
況下,將自動修正為最終寫入文件的地址
** 輸 出: _F_FileAddr --- 文件內地址,為下一個文件末尾可寫的地址
** 功能描述: 根據欲寫入的文件地址,把其他模塊內存中的數據寫
入buffer中,最終自動寫入文件中
** 全局變量: 無
**********************************************************/
_F_FileAddr MemWrite(const void*,size_t,_F_FileAddr*);
//-------------------------------------------------------
/*****************************************************************
** 函數名: MemWriteTest
** 輸 入: const void*,size_t,_F_FileAddr*
** const void* --- 欲寫入buffer的對象(數據)的內存地址
** size_t --- 數據總長度
** _F_FileAddr* ---文件內地址,測試判斷后,若越界、跨塊等情
況下,將自動修正為最終寫入文件的地址
** 輸 出: _F_FileAddr --- 文件內地址,為下一個文件末尾可寫的地址
** 功能描述: 根據欲寫入的文件地址,測試把其他模塊內存中的數據寫入
實際未寫入。用于當整個數據對象不能跨快寫的時候又不能
一次寫入(如鏈表結構(各字段)的一條記錄,在內存中不連
續)的場合。
*****************************************************************/
_F_FileAddr MemWriteTest(size_t,_F_FileAddr*);
//-------------------------------------------------------
#endif //define _BUFFER_H_
//-------------------------------------------------------
//-------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -