📄 buffer.cpp
字号:
// 取得所分配的内存页目前内容在文件中的页编号
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 + -