📄 heapfile.c
字号:
#include "heapfile.h"#include "error.h"// routine to create a heapfileconst Status createHeapFile(const string fileName){ File* file; Status status; FileHdrPage* hdrPage; int hdrPageNo; int newPageNo; Page* newPage; int i; db.createFile(fileName) ; db.openFile( fileName, file) ; if ((status = bufMgr->allocPage( file, hdrPageNo, newPage)) != OK) return status ; hdrPage = (FileHdrPage *)newPage ; for (i = 0; i < MAXNAMESIZE; i++) hdrPage->fileName[i] = fileName[i] ; hdrPage->recCnt = 0 ; hdrPage->pageCnt = 0 ; for (i = 0; i < DIRCNT; i++){ hdrPage->pages[i].pageNo = -1 ; hdrPage->pages[i].freeSpace = -1 ; } if ((status = bufMgr->allocPage( file, newPageNo, newPage)) != OK) return status ; newPage->init(newPageNo) ; hdrPage->pages[0].pageNo = newPageNo ; hdrPage->pages[0].freeSpace = newPage->getFreeSpace() ; hdrPage->pageCnt = 0 ; if((status = bufMgr->unPinPage( file, hdrPageNo, true, true)) != OK) return status ; if((status = bufMgr->unPinPage( file, newPageNo, true, true)) != OK) return status ;// if ((status = bufMgr->flushFile(file)) != OK) return status ; if ((status = db.closeFile(file)) != OK) return status ; return OK ;}// routine to destroy a heapfileconst Status destroyHeapFile(const string fileName){ return (db.destroyFile (fileName));}// constructor opens the underlying fileHeapFile::HeapFile(const string & fileName, Status& returnStatus){ Status status; Page* pagePtr; if((status = db.openFile( fileName, filePtr)) == OK){ if((status = filePtr->getFirstPage(headerPageNo)) == OK){ if ((status = bufMgr->readPage( filePtr, headerPageNo, pagePtr)) == OK){ headerPage = (FileHdrPage *)pagePtr ; hdrDirtyFlag = false ; if ((status = bufMgr->readPage( filePtr, headerPage->pages[0].pageNo, curPage)) == OK){ curPageNo = headerPage->pages[0].pageNo ; curIdx = 0 ; curDirtyFlag = false ; curRec = NULLRID ; } } } } returnStatus = status ;}// the destructor closes the fileHeapFile::~HeapFile(){ Status status; //cout << "invoking heapfile destructor on file " << headerPage->fileName << endl; status = bufMgr->unPinPage( filePtr, headerPageNo, hdrDirtyFlag, true) ; status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, true) ; status = bufMgr->flushFile(filePtr) ; status = db.closeFile(filePtr) ; }// Return number of records in heap fileconst int HeapFile::getRecCnt() const{ return headerPage->recCnt;}// retrieve an arbitrary record from a file.// if record is not on the currently pinned page, the current page// is unpinned and the required page is read into the buffer pool// and pinned. returns a pointer to the record via the rec parameterconst Status HeapFile::getRecord(const RID & rid, Record & rec){ Status status; // cout<< "getRecord. record (" << rid.pageNo << "." << rid.slotNo << ")" << endl; if (rid.pageNo == curPageNo){ if ((status = curPage->getRecord( rid, rec)) != OK) return status ; curRec = rid ; return OK ; } if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, true)) != OK) return status ; if ((status = bufMgr->readPage( filePtr, rid.pageNo, curPage)) != OK){ curPage = NULL ; curRec = NULLRID ; curDirtyFlag = false ; curIdx = -1 ; return status ; } curPageNo = rid.pageNo ; for (int i = 0; i <= headerPage->pageCnt; i++){ if (headerPage->pages[i].pageNo == rid.pageNo){ curIdx = i ; break ; } } curDirtyFlag = false ; curRec = NULLRID ; if ((status == curPage->getRecord( rid, rec)) != OK) return status ; curRec = rid ; return OK ;}HeapFileScan::HeapFileScan(const string & name, Status & status) : HeapFile(name, status){ filter = NULL;}const Status HeapFileScan::startScan(const int offset_, const int length_, const Datatype type_, const char* filter_, const Operator op_){ Status status; // start by making sure the first page of the file is in the buffer pool // if not, unpin the currently pinned page and then read the // first page of the file into the buffer pool // your code to do the above goes here if ((curPageNo != headerPage->pages[0].pageNo)){ if (curPage != NULL) if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, true)) != OK) return status ; if ((status = bufMgr->readPage( filePtr, headerPage->pages[0].pageNo, curPage)) != OK){ curPage = NULL ; curPageNo = -1 ; curIdx = -1 ; curRec = NULLRID ; curDirtyFlag = false ; return status ; } curPageNo = headerPage->pages[0].pageNo ; curIdx = 0 ; curDirtyFlag = false ; curRec = NULLRID ; } curRec = NULLRID ; // then check the rest of the paramters if (!filter_) { // no filtering requested filter = NULL; return OK; } if ((offset_ < 0 || length_ < 1) || (type_ != STRING && type_ != INTEGER && type_ != FLOAT) || (type_ == INTEGER && length_ != sizeof(int) || type_ == FLOAT && length_ != sizeof(float)) || (op_ != LT && op_ != LTE && op_ != EQ && op_ != GTE && op_ != GT && op_ != NE)) { return BADSCANPARM; } offset = offset_; length = length_; type = type_; filter = filter_; op = op_; return OK;}const Status HeapFileScan::endScan(){ // nothing really to do here as we want to leave to leave the last page pinned return OK;}HeapFileScan::~HeapFileScan(){ Status status; if (curPage != NULL) { status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag, false); curPage = NULL; curPageNo = -1; curDirtyFlag = false; }}const Status HeapFileScan::markScan(){ // make a snapshot of the state of the scan markedPageNo = curPageNo; markedRec = curRec; markedIdx = curIdx; return OK;}const Status HeapFileScan::resetScan(){ Status status; if (markedPageNo == curPageNo){ curPageNo = markedPageNo ; curRec = markedRec ; curIdx = markedIdx ; status = OK ; return status ; } if (curPage != NULL) if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, true )) != OK) return status ; if ((status = bufMgr->readPage( filePtr, markedPageNo, curPage)) != OK){ curPage = NULL ; curPageNo = 0 ; curDirtyFlag = false ; curRec = NULLRID ; return status ; } curPageNo = markedPageNo ; curRec = markedRec ; curIdx = markedIdx ; curDirtyFlag = false ; return OK ;}const Status HeapFileScan::scanNext(RID& outRid){ Status status = OK ; RID tmpRid; Record rec; int i ; // cout << "in ScanNext(), curPageNo is " << curPageNo << endl; for (i = curIdx; i <= headerPage->pageCnt; i++){ if ((status = curPage->firstRecord(tmpRid)) == OK){ if (curRec.slotNo == -1){ if ((status = curPage->firstRecord(tmpRid)) != OK) return status ; if ((status = HeapFile::getRecord(tmpRid,rec)) != OK) return status ; if (matchRec(rec) == true){ outRid = tmpRid ; curRec = tmpRid ; return OK ; } curRec = tmpRid ; } while((curPage->nextRecord( curRec, tmpRid)) == OK){ if ((status = HeapFile::getRecord(tmpRid,rec)) != OK) return status ; if (matchRec(rec) == true){ outRid = tmpRid ; curRec = tmpRid ; return OK ; } } } if ( i + 1 > headerPage->pageCnt) return FILEEOF ; if (curPage != NULL) if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, true)) != OK) return status ; if ((status = bufMgr->readPage( filePtr, headerPage->pages[i + 1].pageNo, curPage)) != OK){ curPageNo = -1 ; curPage = NULL ; curRec = NULLRID ; curIdx = -1 ; return status ; } curPageNo = headerPage->pages[i + 1].pageNo ; curIdx = i + 1 ; curDirtyFlag = false ; curRec = NULLRID ; } }// returns pointer to the current record. page is left pinned// and the scan logic is required to unpin the page const Status HeapFileScan::getRecord(Record & rec){ return curPage->getRecord(curRec, rec);}// delete record from file. const Status HeapFileScan::deleteRecord(){ Status status; if (curRec.pageNo != curPageNo) return BADPAGENO ; if ((status = curPage->deleteRecord(curRec)) != OK) return status ; headerPage->recCnt -= 1 ; headerPage->pages[curIdx].freeSpace = curPage->getFreeSpace() ; hdrDirtyFlag = true ; curDirtyFlag = true ; return OK ; }// update record from file.const Status HeapFileScan::updateRecord(const Record &rec){ Status status ; if (curRec.pageNo != curPageNo) return BADPAGENO ; if ((status = curPage->updateRecord( rec, curRec)) != OK) return status ; hdrDirtyFlag = true ; curDirtyFlag = true ; return OK ;}// mark current page of scan dirtyconst Status HeapFileScan::markDirty(){ curDirtyFlag = true; return OK;}const bool HeapFileScan::matchRec(const Record & rec) const{ // no filtering requested if (!filter) return true; // see if offset + length is beyond end of record // maybe this should be an error??? if ((offset + length -1 ) >= rec.length) return false; float diff = 0; // < 0 if attr < fltr switch(type) { case INTEGER: int iattr, ifltr; // word-alignment problem possible memcpy(&iattr, (char *)rec.data + offset, length); memcpy(&ifltr, filter, length); diff = iattr - ifltr; break; case FLOAT: float fattr, ffltr; // word-alignment problem possible memcpy(&fattr, (char *)rec.data + offset, length); memcpy(&ffltr, filter, length); diff = fattr - ffltr; break; case STRING: diff = strncmp((char *)rec.data + offset, filter, length); break; } switch(op) { case LT: if (diff < 0.0) return true; break; case LTE: if (diff <= 0.0) return true; break; case EQ: if (diff == 0.0) return true; break; case GTE: if (diff >= 0.0) return true; break; case GT: if (diff > 0.0) return true; break; case NE: if (diff != 0.0) return true; break; } return false;}InsertFileScan::InsertFileScan(const string & name, Status & status) : HeapFile(name, status){ //cout << "doing insertfile scan constuctor " << endl; // the heapfile constructor will make sure that the header page // and the first page of the file are in the buffer pool curRec = NULLRID;}InsertFileScan::~InsertFileScan(){ Status status; // unpin last page of the scan if (curPage != NULL) { status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag, false); curPage = NULL; curRec = NULLRID; curPageNo = -1; if (status != OK) cerr << "error in unpin of data page\n"; }}// Insert a record into the fileconst Status InsertFileScan::insertRecord(const Record & rec, RID& outRid){ Status status ; RID rid ; if ((status = curPage->insertRecord(rec,rid)) == OK){ outRid = rid ; curRec = rid ; headerPage->pages[curIdx].freeSpace = curPage->getFreeSpace() ; headerPage->recCnt += 1 ; hdrDirtyFlag = true ; curDirtyFlag = true ; return OK ; } for (int i = 0; i <= headerPage->pageCnt; i++){ if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, false)) != OK) return status ; if ((status = bufMgr->readPage( filePtr, headerPage->pages[i].pageNo, curPage)) != OK){ curPage = NULL ; curRec = NULLRID ; curIdx = -1 ; curPageNo = -1 ; return status ; } curPageNo = headerPage->pages[i].pageNo ; curRec = NULLRID ; curIdx = i ; curDirtyFlag = false ; if ((status = curPage->insertRecord(rec,rid)) == OK){ outRid = rid ; curRec = rid ; headerPage->pages[curIdx].freeSpace = curPage->getFreeSpace() ; headerPage->recCnt += 1 ; hdrDirtyFlag = true ; curDirtyFlag = true ; return OK ; } } if (headerPage->pageCnt == DIRCNT - 1) return FILEHDRFULL ; if ((status = bufMgr->unPinPage( filePtr, curPageNo, curDirtyFlag, false)) != OK) return status ; curRec = NULLRID ; curPage = NULL ; curPageNo = -1 ; curIdx = -1 ; curDirtyFlag = false ; if((status = bufMgr->allocPage( filePtr, curPageNo, curPage)) != OK) return status ; curPage->init(curPageNo) ; curRec = NULLRID ; curDirtyFlag = false ; headerPage->pageCnt++ ; hdrDirtyFlag = true ; headerPage->pages[headerPage->pageCnt].pageNo = curPageNo ; headerPage->pages[headerPage->pageCnt].freeSpace = curPage->getFreeSpace() ; curIdx = headerPage->pageCnt ; if ((status = curPage->insertRecord(rec,rid)) == OK){ outRid = rid ; curRec = rid ; headerPage->recCnt += 1 ; headerPage->pages[curIdx].freeSpace = curPage->getFreeSpace() ; hdrDirtyFlag = true ; curDirtyFlag = true ; return OK ; } return NOSPACE ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -