⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.h

📁 实现一个精简型单用户SQL引擎(DBMS)MiniSQL
💻 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 + -