📄 databasefile.cpp
字号:
// DatabaseFile.cpp: implementation of the CDatabaseFile class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Database.h"
#include "DatabaseFile.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDatabaseFile::CDatabaseFile()
{
}
CDatabaseFile::CDatabaseFile(LPCTSTR lpszFileName, UINT nOpenFlags,UINT id)
{
CFile file(lpszFileName,nOpenFlags);
UINT filelength=file.GetLength();
if(filelength==0)//是新文件
{
const char *magic="DAT";
file.SetLength(2*MAIN_BLOCK);//初始8192字节
ID=id;
end=MAIN_BLOCK;//4096
start=MAIN_BLOCK;
wBlockNum=1;
NextFile=0;
UINT FirstSpaceOffset=0;
WORD FirstSpaceLarge=0;
file.SeekToBegin();
file.Write(magic,MAGIC);
file.Write(&ID,sizeof(UINT));
file.Write(&wBlockNum,sizeof(WORD));
file.Write(&end,sizeof(UINT));
file.Write(&start,sizeof(UINT));
file.Write(&NextFile,sizeof(UINT));
file.Write(&FirstSpaceOffset,sizeof(UINT));
file.Write(&FirstSpaceLarge,sizeof(UINT));
sfirst=slast=NULL;
}
else
{
sfirst=slast=NULL;
UINT s_off;
UINT s_large;
char *magic[4];
file.SeekToBegin();
file.Read(magic,MAGIC);
//if(strcmp(magic,"DAT"))
//::AfxThrowFileException(
file.Read(&ID,sizeof(UINT));
file.Read(&wBlockNum,sizeof(WORD));
//Read(&PriorFile,sizeof(UINT));
file.Read(&end,sizeof(UINT));
file.Read(&start,sizeof(UINT));
file.Read(&NextFile,sizeof(UINT));
//读空闲表
do
{
file.Read(&s_off,sizeof(UINT));
file.Read(&s_large,sizeof(UINT));
if(s_off!=0&&s_large!=0)//断言:这两个条件同成立或...
{
Space *s=new Space(s_off,s_large);
InsertSpace(s);
file.Seek(s_off,CFile::begin);
}
ASSERT(s_off!=0&&s_large!=0||s_off==0&&s_large==0);
}
while(s_off!=0&&s_large!=0);
}
}
void CDatabaseFile::DeleteSpace(Space *s)
{
Space *before=NULL;
Space *ps=sfirst;
while(ps&&ps!=s)
{
before=ps;
ps=ps->next;
}
if(!ps)
return;
else//ps==s
{
if(ps==sfirst)
sfirst=ps->next;
if(ps==slast)
slast=before;
if(before)
before->next=s->next;
delete(s);
}
}
CDatabaseFile::~CDatabaseFile()
{
Close();
}
//为记录分配数据库地址
//暂且认为字段长度比块小
PDB CDatabaseFile::Allocate(Record *rcd, Relationship *R)
{
PDB Ret=0;
Space *s=sfirst;
CString filename("");
filename.Format("D:\\DB\\%d.db",ID);
CFile file(LPCTSTR(filename),CFile::modeReadWrite);
UINT FileLength=file.GetLength();
file.Close();
UINT RcdLength=rcd->m_length;
Space *s1=NULL;
//UINT FitOffset=0;
//UINT FitLarge=0;
while(s)
{
if((s->uLarge-RECORD_HEAD-RcdLength)>=0)
{
if( (s->uLarge/2) >= (RECORD_HEAD+RcdLength) )
{
s1=new Space(s->uOffset,RECORD_HEAD+RcdLength);
s->uOffset+=(RECORD_HEAD+RcdLength);
s->uLarge-=(RECORD_HEAD+RcdLength);
}
else
{
s1=new Space(s->uOffset,s->uLarge);
DeleteSpace(s);
}
if(InsertRecord(s1,rcd))
{
Ret=(PDB(ID)<<32)+PDB(s1->uOffset);
return Ret;
}
}
else
s=s->next;
}
//此时必然没有s1
WORD wBlockNum1=wBlockNum;
Space *space_end=new Space(end,0);
while( !s1 && ((end+RECORD_HEAD+RcdLength) > FileLength) )
{
if(wBlockNum1 < FILE_MAX/MAIN_BLOCK)
{
file.Open(LPCTSTR(filename),CFile::modeReadWrite);
file.SetLength(FileLength+MAIN_BLOCK);
FileLength=file.GetLength();
wBlockNum1++;
file.Close();
}
else
{
delete(space_end);
return DB_NULL;
}
}
wBlockNum=wBlockNum1;
s1=space_end;
if(InsertRecord(s1,rcd))
{
Ret=(PDB(ID)<<32)+PDB(s1->uOffset);
delete s1;
return Ret;
}//要改变end
}
int CDatabaseFile::GetTime()
{
return 0;
}
BOOL CDatabaseFile::InsertRecord(Space *s, Record *r/*, Relationship *R*/)
//可能要改变文件尾
{
CBlock *cb;
PDB db_addr=PDB(ID);
BYTE exist=1;
UINT RcdLength=r->m_length;
UINT RcdID=CMemory::AllocateID(RECORD_ID,r->pattern->ID);
int time=CMemory::GetTime();
r->ID=RcdID;
r->time=time;
ASSERT(s&&(!s->next));//一个空闲块搞定
//写记录
db_addr=(db_addr<<32) + PDB(s->uOffset);
cb=CMemory::ReadDBBlock(db_addr);
cb->WriteRecord(r,OFFSET(db_addr));
if(s->uOffset==MAIN_BLOCK&&s->uLarge!=0)//插在文件首,却不是末
{
this->start=MAIN_BLOCK;
}
if(s->uLarge==0)//这是s为文件尾的标志,而不是s大小真的为0
{
this->end+=RcdLength+RECORD_HEAD;
}
return TRUE;
}
Record *CDatabaseFile::DeleteRecord(PDB db_addr,Relationship *R,bool bRet)//只能由CBlock负责通知CMemory删除记录号
{
CBlock *cb=CMemory::ReadDBBlock(db_addr);
BYTE exist=0;
UINT RcdLength;
ASSERT(UINT(db_addr>>32)==ID);
CString filename("");
filename.Format("D:\\DB\\%d.db",this->ID);
CFile f(LPCTSTR(filename),CFile::modeReadWrite);
UINT RecordOff=UINT(db_addr&0xFFFFFFFF);
f.Seek(RecordOff,CFile::begin);
f.Read(&RcdLength,sizeof(UINT));
Space *s=new Space(RecordOff,RECORD_HEAD+RcdLength);
InsertSpace(s);//可能会改变end或start
if(!bRet)
return NULL;
else
return (cb->DeleteRecord(OFFSET(db_addr),R));
}
void CDatabaseFile::InsertSpace(Space *s)
{
Space *after=sfirst;
Space *before=NULL;
if(!sfirst)
sfirst=slast=s;
else
{
while(after && after->uOffset < (s->uOffset+s->uLarge) )
{
before=after;
after=after->next;
}
if( before&&(before->uOffset+before->uLarge)==s->uOffset )
{
before->uLarge=before->uLarge+s->uLarge;
delete(s);
s=NULL;//s被前吸收
}
else if( after&&(s->uOffset+s->uLarge)==after->uOffset )
{
after->uOffset=s->uOffset;
after->uLarge=after->uLarge+s->uLarge;
delete(s);
s=NULL;//s被后吸收
}
else
{
s->next=after;
if(sfirst==after)
sfirst=s;
if(before)
before->next=s;
if(slast==before)
slast=s;
}
if( before&&after&&(before->uOffset+before->uLarge)==after->uOffset)
{
ASSERT(!s);
before->uLarge=before->uLarge+after->uLarge;
before->next=after->next;
if(after==slast)
slast=before;
delete(after);
}
}
if( (slast->uOffset+slast->uLarge)==end)
{
end=slast->uOffset;
DeleteSpace(slast);//???????????????????????????
}
if( sfirst&&(sfirst->uOffset==start) )
{
start=sfirst->uOffset+sfirst->uLarge;
}
if(start>=end)
start=end=MAIN_BLOCK;
}
/* after->uOffset=s->uOffsetafter->uLarge+s->
}
while(after->uOffset<(s->uOffset+s->uLarge)) && after->uOffset!=0)
{
before=after;
after=after->next;
}
if(s->uOffset==
if(after->offset==(s->offset+s->large))//完成一部分ResetSpace()的功能
{
after->offset=s->offset;
after->large=after->large+s->large;
}
s->next=after;
s->prior=after->prior;
if(after->prior)
after->prior->next=s;
after->prior=s;
if(after==st)
st=s;*/
void CDatabaseFile::Close()
{
CString filename("");
filename.Format("D:\\DB\\%d.db",ID);
CFile file(LPCTSTR(filename),CFile::modeReadWrite);
file.Seek(MAGIC,CFile::begin);
//if(strcmp(magic,"IDX"))
//::AfxThrowFileException(
file.Write(&ID,sizeof(UINT));
file.Write(&wBlockNum,sizeof(WORD));
//Read(&PriorFile,sizeof(UINT));
file.Write(&end,sizeof(UINT));
file.Write(&start,sizeof(UINT));
file.Write(&NextFile,sizeof(UINT));
//写空闲表
Space *s=sfirst;
bool stop=0;
while(!stop)
{
if(!s)
{
UINT off=0,lar=0;
file.Write(&off,sizeof(UINT));
file.Write(&lar,sizeof(UINT));
stop=1;
}
else
{
file.Write(&s->uOffset,sizeof(UINT));
file.Write(&s->uLarge,sizeof(UINT));
file.Seek(s->uOffset,CFile::begin);
sfirst=sfirst->next;
if(s==slast)
slast=NULL;
delete(s);
s=sfirst;
}
}
}
/*Record CDatabaseFile::UpdateRecord(PDB db_addr, CUpdate up,Relationship *R)
{
CBlock *cb=CMemory::ReadDBBlock(db_addr);
ASSERT(UINT(db_addr>>32)==ID);
return (cb->UpdateRecord(OFFSET(db_addr),up,R));
}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -