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

📄 buffer.cpp

📁 设计并实现一个精简型单用户SQL引擎(DBMS)MiniSQL
💻 CPP
📖 第 1 页 / 共 2 页
字号:

// 取得所分配的内存页目前内容在文件中的页编号
unsigned long _M_PageInfo::GetFilePageID() const
{
    return this->Ptr2Page->ulFilePageID;
}
///////////////////////////////////////////////////////////////////////////////////////
//class _M_File
// 初始化,打开和新建文件,若当前文件开的太多,导致无法再打开新文件,可自动关闭最早打开的文件
_M_File::_M_File(const char *name,unsigned int fileid)
{
		this->uiFileID = fileid;
        this->IsNew = 0;
        this->ulPageTotal = 1;
		strcpy(this->FileName,name);
		this->Ptr2File = open(name,_O_BINARY|O_RDWR,0664); 
        if(this->Ptr2File==-1){ // 文件不存在
            this->Ptr2File = open(name,_O_BINARY|O_RDWR|O_CREAT,0664); // 新建文件(打开文件)
            if(this->Ptr2File==-1)  // 文件不能被打开(新建)
            {
                if( Buffer._F_First) 
                    Buffer._F_First->Close(); // 关闭最早打开的文件
                this->Ptr2File = open(name,_O_BINARY|O_RDWR|O_CREAT,0664); // 新建文件(打开文件)
			    if(this->Ptr2File==-1)  // 文件不能被新建(打开)
                    throw 1006; // 文件还是不能被打开(新建),可能为磁盘空间不足等意外
            }
            this->IsNew = 1;
        }
		this->_F_Next = 0;
}

//取相关文件
unsigned int _M_File::GetRelativeFileID() const
{
	int FNLength =strlen(this->FileName);//记录文件名长度,以便修改文件扩展名
	char FNTemp1[MAX_FILENAME_LEN];//存文件名
	char FNTemp2[MAX_FILENAME_LEN];
	strcpy(FNTemp1,this->FileName);
	FNTemp1[FNLength-3]='\0';//除去扩展名
	_M_File * pMFTemp;
	pMFTemp=Buffer._F_First;
	while(pMFTemp)//对所有打开文件进行搜索
	{
		strcpy(FNTemp2,pMFTemp->FileName);
		FNTemp2[FNLength-3]='\0';//除去扩展名
		if((strcmp(FNTemp1,FNTemp2)==0)&&(pMFTemp->uiFileID!=this->uiFileID))
			return pMFTemp->uiFileID;
		pMFTemp=pMFTemp->_F_Next;
	}
	//error
	//throw:没有找到相关文件
	return 0;
}
// 析构,关闭文件
void _M_File::Deconstruct()
{
    if(this->Ptr2File)
        close(this->Ptr2File);
}
// 关闭文件,同时属于该文件的内存页改写回的写回.为保证一致性,同时关闭关联文件
void _M_File::Close()
{
	Buffer.CloseTable(this->uiFileID);	
}

// 根据页号取得属于该文件的内存页
_M_PageInfo* _M_File::GetPageInfo(unsigned long filepageid) const
{
    return Buffer.MemPageClock->GetTargetPage(this->uiFileID,filepageid);
}
// 取得目前总的页数
unsigned long _M_File::GetPageTotal() const
{
      return this->ulPageTotal;
}

// 取得文件内记录删除维护信息
_F_FileAddr _M_File::GetDelListCond() const
{
    _F_FileAddr temp;
    temp.ulFilePageID = 0;
    temp.uiOffset = SizeOfPageHead;
    return temp;
}

// 取得Catalog模块在文件中可写的第一个位置
_F_FileAddr _M_File::GetCataPoint() const
{
    _F_FileAddr temp;
    temp.ulFilePageID = 0;
    temp.uiOffset = SizeOfPageHead + sizeof(_TB_FILECOND);
    return temp;
}

// 取得Catalog模块在文件中可写的第一个位置
_F_FileAddr _M_File::GetIdxPoint() const
{
    _F_FileAddr temp;
    temp.ulFilePageID = 0;
    temp.uiOffset = SizeOfPageHead + sizeof(_TB_FILECOND);
    return temp;
}

///////////////////////////////////////////////////////////////////////////////////////
//_F_FileAddr
//初始化
void _F_FileAddr::Initialize()
{
    this->ulFilePageID = 0;
    this->uiOffset = 0;
}

//根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
//根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
void* _F_FileAddr::MemAddr() const
{
	 if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
	return (void*)((char*)Buffer._F_Current->GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
}

//根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
void* _F_FileAddr::MemAddr(_M_File *TargetMFile) const
{
	if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
	return (void*)((char*)TargetMFile->GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
}

//根据页编号和偏移量,取出当前文件该地址在内存中的地址,同时测试页偏移量是否溢出
void* _F_FileAddr::MemAddr(_M_File &TargetMFile) const
{
	if( this->ulFilePageID==0 && this->uiOffset==0 )return NULL;
	return (void*)((char*)TargetMFile.GetPageInfo(this->ulFilePageID)->Ptr2Page->Ptr2PageBegin + this->uiOffset);
}

// _F_FileAddr >= 操作
bool _F_FileAddr::operator>=(_F_FileAddr& other) const
{
	if( (this->ulFilePageID > other.ulFilePageID) || (this->uiOffset >= other.uiOffset && this->ulFilePageID >= other.ulFilePageID))
		return true;
	return false;
}

// _F_FileAddr > 操作
bool _F_FileAddr::operator>(_F_FileAddr& other) const
{
	if( (this->ulFilePageID > other.ulFilePageID) || (this->uiOffset > other.uiOffset && this->ulFilePageID >= other.ulFilePageID))
		return true;
	return false;
}

// _F_FileAddr == 操作
bool _F_FileAddr::operator==(_F_FileAddr& other) const
{
	if((this->ulFilePageID == other.ulFilePageID) && (this->uiOffset == other.uiOffset))
		return true;
	return false;
}

// _F_FileAddr != 操作
bool _F_FileAddr::operator!=(_F_FileAddr& other) const
{
	if((this->ulFilePageID != other.ulFilePageID) || (this->uiOffset != other.uiOffset))
		return true;
	return false;
}

// _F_FileAddr == const int 操作只对0操作
bool _F_FileAddr::operator==(const int zero) const
{
	if( (this->ulFilePageID==0) &&( this->uiOffset==0) )
		return true;
	return false;
}

//在当前页中滑动offset量(可正可负)
void _F_FileAddr::ShiftOffset(int offset)
{
	int temp=(int)this->uiOffset+offset;
	//if temp <0 出错
	this->uiOffset =(unsigned int) temp;
}


/////////////////////////////////////////////////////////////////////////////////////////
//class _M_Buffer
// Buffer初始化
void _M_Buffer::Start()
{
    if( MEM_PAGEAMOUNT < 3) throw 1033; // 至少要求有 3 页,2页头信息(目录管理和索引管理各一页),另外 1 页记录存取
	this->_F_First = 0;
	this->_F_Last = 0;
    this->_F_Current = 0;
	this->uiFileCount = 0;
    this->MemPageClock = new _M_Clock();
}

// Buffer结束,写回内存页,关闭文件
void _M_Buffer::End()
{
    delete this->MemPageClock;
    this->_F_Last = 0;
    this->uiFileCount = 0;
	_M_File* temp = this->_F_First;
    this->_F_First = 0;
    _M_File* temp2 = 0;
	while(temp)
	{
		temp2 = temp->_F_Next;
        temp->Deconstruct();
		temp = temp2;
	}
}

// 根据文件编号返回内存文件对象是否为新建
bool _M_Buffer::GetIsNew(unsigned int fileid) const
{
    return (*this)[fileid]->IsNew;
}
// 根据文件编号设置内存文件对象是否为新建
void _M_Buffer::SetIsNew(unsigned int fileid,bool isnew)
{
    (*this)[fileid]->IsNew = isnew;
}
unsigned long _M_Buffer::GetPageTotal(unsigned int fileid) const
{
    return (*this)[fileid]->ulPageTotal;
}
void _M_Buffer::AddPageTotal(unsigned int fileid,int add)
{
    (*this)[fileid]->ulPageTotal += add;
}
int _M_Buffer::GetPtr2File(unsigned int fileid) const
{
    return (*this)[fileid]->Ptr2File;
}
// 根据文件编号返回内存文件对象
_M_File* _M_Buffer::operator [](unsigned int fileid) const
{
	//Error Dispatch 0< fileid <= Buffer->uiFileCount
    _M_File* temp = 0;
    _M_File* temp2 = this->_F_First;
    while( temp2 )
    {
        if( temp2->uiFileID == fileid ){
            temp = temp2;
            break;
        }
        temp2 = temp2->_F_Next;
    }
	return temp;
}

//找到文件名为filename的_M_File
_M_File _M_Buffer::operator [](const char* filename)
{
	//先找当前文件,概率比较大
	if( this->_F_Current && strcmp(filename,this->_F_Current->FileName)==0)
        return *(this->_F_Current);
	_M_File * pMFTemp;
	pMFTemp = this->_F_First;
	while(pMFTemp)                    //对所有打开文件进行遍历
	{
		if(strcmp(filename,pMFTemp->FileName)==0)
		{
			this->_F_Current=pMFTemp;
			return *pMFTemp;            //找到返回文件信息并将当前Buffer的指针针向当前文件
		}
		pMFTemp=pMFTemp->_F_Next;
	}
//在打开文件中没有要找的文件开始如下操作
	pMFTemp = new _M_File(filename,++this->uiFileCount);
	if(!this->_F_First)//没有文件打开
		this->_F_First=this->_F_Last=pMFTemp;
	else
	{
		this->_F_Last->_F_Next=pMFTemp;
		this->_F_Last=pMFTemp;
	}
	this->_F_Current=pMFTemp;
	if(pMFTemp->IsNew)
		this->MemPageClock->GetTargetPage(pMFTemp->uiFileID,0);
	else //将文件的总页数读到_M_File 中
		pMFTemp->ulPageTotal=this->MemPageClock->GetTargetPage(pMFTemp->uiFileID,0)->GetPtr2FileCond()->ulPageTotal;
	return *pMFTemp;
}

// 根据文件编号关闭内存文件对象
void _M_Buffer::CloseFile(unsigned int fileid)
{
	this->MemPageClock->CloseFilePages(fileid);
	_M_File* temp = this->_F_First;
	_M_File* temp2 = 0;
	while(temp->uiFileID != fileid)
	{
		temp2 = temp;
		temp = temp->_F_Next;
	}
	if( temp == this->_F_First )
		this->_F_First = this->_F_First->_F_Next;
	else
		temp2->_F_Next = temp->_F_Next;
	temp->Deconstruct();
}
void _M_Buffer::CloseTable(unsigned int fileid)
{
    unsigned int tempfileid = (*this)[fileid]->GetRelativeFileID();
    if( tempfileid )
        this->CloseFile(tempfileid);
    this->CloseFile(fileid);
}

//根据欲写入的文件地址,把其他模块内存中的数据写入buffer中,最终自动写入文件中
_F_FileAddr MemWrite(const void* source,size_t length,_F_FileAddr* dest)
{
    if( (int)(FILE_PAGESIZE - dest->uiOffset) - (int)length < 0) // 判断是否溢出
    {
        dest->ulFilePageID = Buffer._F_Current->GetPageTotal(); // 若溢出修正 dest
		//Buffer.MemPageClock->GetTargetPage(Buffer._F_Current->uiFileID,dest->ulFilePageID);
        dest->uiOffset = sizeof(_TB_PAGEHEAD);
    }
    memcpy(dest->MemAddr(),source,length);
    Buffer.MemPageClock->SetPageModified();

    _F_FileAddr end = *dest;
    end.ShiftOffset((int)length);
    return end;
}

//根据欲写入的文件地址,测试把其他模块内存中的数据写入实际未写入。
_F_FileAddr MemWriteTest(size_t length,_F_FileAddr* dest)
{
	if((int)(FILE_PAGESIZE - dest->uiOffset) - (int)length < 0) // 判断是否溢出
  	{
		dest->ulFilePageID = Buffer._F_Current->GetPageTotal(); // 若溢出修正 dest
		dest->uiOffset = SizeOfPageHead;
	}

	_F_FileAddr end = *dest;
	end.ShiftOffset((int)length);
	return end;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -