// ********************************************************** // Delete a record from a page. Returns OK if everything went okay. // Compacts remaining records but leaves a hole in the slot array. // Use memmove() rather than memcpy() as space may overlap. Status HFPage::deleteRecord(const RID& rid) { // fill in the body //--- deal with errors ---- if(rid.pageNo < 0 || rid.slotNo < 0) return MINIBASE_FIRST_ERROR(HEAPFILE, INVALID_SLOTNO); //return FAIL; if(rid.slotNo >= this->slotCnt) return MINIBASE_FIRST_ERROR(HEAPFILE, INVALID_SLOTNO); //return FAIL; //--- deal with empty page case --- if(empty()) return MINIBASE_FIRST_ERROR(HEAPFILE, NO_RECORDS); //return FAIL; //--- get record offset --- int offset = getRecordOffset(rid); //--- clean corresponding slot & get record length--- int len = cleanSlot(rid); //--- deal with already deleted case --- if(offset == INVALID_SLOT || len == EMPTY_SLOT) return MINIBASE_FIRST_ERROR(HEAPFILE, ALREADY_DELETED); //return FAIL; //-- shrink slot directory --- shrinkSlotDir(); //--- delete record & relocate behind records & slot dir --- //--- & update usedPtr, freeSpace ----- deleteRec(offset, len); return OK; }
char* Page::getRecord ( int index ){ int offset = getRecordOffset( index ); int length = getRecordLength( index ); tempStrCounter = length; memcpy( tempStr, content + offset, sizeof( char ) * length ); tempStr[ length ] = '\0'; return tempStr; }
// ********************************************************** // Delete a record from a page. Returns OK if everything went okay. // Compacts remaining records but leaves a hole in the slot array. // Use memmove() rather than memcpy() as space may overlap. Status HFPage::deleteRecord(const RID& rid) { // fill in the body //---?? 注意未处理delete不存在record得特殊情况---- //--- get record offset --- int offset = getRecordOffset(rid); //--- clean corresponding slot & get record length--- int len = cleanSlot(rid); //-- shrink slot directory --- shrinkSlotDir(); //--- delete record & relocate behind records & slot dir --- //--- & update usedPtr, freeSpace ----- deleteRec(offset, len); return OK; }
//compress a page, used for split page void Page::adjustPage( ){ int nextFree = 4; int slotSize = getSlotNumber(); int length, offset; int counter = getSlotNumber(); int location = 0; for ( int i = 0; i < slotSize; i ++ ) { length = getRecordLength( i ); //if the length is -1,it means that this data not in this page if ( length == -1 ) counter --; else{ bool flag = 0; //find a slot with record length of -1,if it succeed, then move the data into this slot for (int j = location; j < i; j ++ ) if ( getRecordLength( j ) == -1 ) { location = j; flag = 1; break; } if ( flag == 1 ){ offset = getRecordOffset( i ); memcpy( content + nextFree, content + offset, sizeof( char ) * length ); setRecordOffset( location, nextFree ); setRecordLength( location, length ); setRecordLength( i, -1 ); } nextFree += length; } } //update free offset and slot number setSlotNumber( counter ); setFreeOffset( nextFree ); }
XAttrList* getAllExtendedAttributes(HFSCatalogNodeID CNID, Volume* volume) { BTree* tree; HFSPlusAttrKey key; HFSPlusAttrRecord* record; uint32_t nodeNumber; int recordNumber; BTNodeDescriptor* descriptor; HFSPlusAttrKey* currentKey; off_t recordOffset; XAttrList* list = NULL; XAttrList* lastItem = NULL; XAttrList* item = NULL; if(!volume->attrTree) return NULL; memset(&key, 0 , sizeof(HFSPlusAttrKey)); key.fileID = CNID; key.startBlock = 0; key.name.length = 0; key.keyLength = sizeof(HFSPlusAttrKey) - sizeof(HFSUniStr255) + sizeof(key.name.length) + (sizeof(uint16_t) * key.name.length); tree = volume->attrTree; record = (HFSPlusAttrRecord*) search(tree, (BTKey*)(&key), NULL, &nodeNumber, &recordNumber); if(record == NULL) return NULL; free(record); while(nodeNumber != 0) { descriptor = readBTNodeDescriptor(nodeNumber, tree); while(recordNumber < descriptor->numRecords) { recordOffset = getRecordOffset(recordNumber, nodeNumber, tree); currentKey = (HFSPlusAttrKey*) READ_KEY(tree, recordOffset, tree->io); if(currentKey->fileID == CNID) { item = (XAttrList*) malloc(sizeof(XAttrList)); item->name = (char*) malloc(currentKey->name.length + 1); int i; for(i = 0; i < currentKey->name.length; i++) { item->name[i] = currentKey->name.unicode[i]; } item->name[currentKey->name.length] = '\0'; item->next = NULL; if(lastItem != NULL) { lastItem->next = item; } else { list = item; } lastItem = item; free(currentKey); } else { free(currentKey); free(descriptor); return list; } recordNumber++; } nodeNumber = descriptor->fLink; recordNumber = 0; free(descriptor); } return list; }
CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume) { BTree* tree; HFSPlusCatalogThread* record; HFSPlusCatalogKey key; uint32_t nodeNumber; int recordNumber; BTNodeDescriptor* descriptor; off_t recordOffset; off_t recordDataOffset; HFSPlusCatalogKey* currentKey; CatalogRecordList* list; CatalogRecordList* lastItem; CatalogRecordList* item; char pathBuffer[1024]; HFSPlusCatalogRecord* toReturn; HFSPlusCatalogKey nkey; int exact; tree = volume->catalogTree; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); key.parentID = CNID; key.nodeName.length = 0; list = NULL; record = (HFSPlusCatalogThread*) search(tree, (BTKey*)(&key), NULL, &nodeNumber, &recordNumber); if(record == NULL) return NULL; free(record); ++recordNumber; while(nodeNumber != 0) { descriptor = readBTNodeDescriptor(nodeNumber, tree); while(recordNumber < descriptor->numRecords) { recordOffset = getRecordOffset(recordNumber, nodeNumber, tree); currentKey = (HFSPlusCatalogKey*) READ_KEY(tree, recordOffset, tree->io); recordDataOffset = recordOffset + currentKey->keyLength + sizeof(currentKey->keyLength); if(currentKey->parentID == CNID) { item = (CatalogRecordList*) malloc(sizeof(CatalogRecordList)); item->name = currentKey->nodeName; item->record = (HFSPlusCatalogRecord*) READ_DATA(tree, recordDataOffset, tree->io); if(item->record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)item->record)->userInfo.fileType) == kHardLinkFileType) { sprintf(pathBuffer, "iNode%d", ((HFSPlusCatalogFile*)item->record)->permissions.special.iNodeNum); nkey.parentID = volume->metadataDir; ASCIIToUnicode(pathBuffer, &nkey.nodeName); nkey.keyLength = sizeof(nkey.parentID) + sizeof(nkey.nodeName.length) + (sizeof(uint16_t) * nkey.nodeName.length); toReturn = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&nkey), &exact, NULL, NULL); free(item->record); item->record = toReturn; } item->next = NULL; if(list == NULL) { list = item; } else { lastItem->next = item; } lastItem = item; free(currentKey); } else { free(currentKey); free(descriptor); return list; } recordNumber++; } nodeNumber = descriptor->fLink; recordNumber = 0; free(descriptor); } return list; }
CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume) { BTree* tree; HFSPlusCatalogThread* record; HFSPlusCatalogKey key; uint32_t nodeNumber; int recordNumber; BTNodeDescriptor* descriptor; off_t recordOffset; off_t recordDataOffset; HFSPlusCatalogKey* currentKey; CatalogRecordList* list; CatalogRecordList* lastItem; CatalogRecordList* item; tree = volume->catalogTree; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); key.parentID = CNID; key.nodeName.length = 0; list = NULL; record = (HFSPlusCatalogThread*) search(tree, (BTKey*)(&key), NULL, &nodeNumber, &recordNumber); if(record == NULL) return NULL; free(record); ++recordNumber; while(nodeNumber != 0) { descriptor = readBTNodeDescriptor(nodeNumber, tree); while(recordNumber < descriptor->numRecords) { recordOffset = getRecordOffset(recordNumber, nodeNumber, tree); currentKey = (HFSPlusCatalogKey*) READ_KEY(tree, recordOffset, tree->io); recordDataOffset = recordOffset + currentKey->keyLength + sizeof(currentKey->keyLength); if(currentKey->parentID == CNID) { item = (CatalogRecordList*) malloc(sizeof(CatalogRecordList)); item->name = currentKey->nodeName; item->record = (HFSPlusCatalogRecord*) READ_DATA(tree, recordDataOffset, tree->io); item->next = NULL; if(list == NULL) { list = item; } else { lastItem->next = item; } lastItem = item; free(currentKey); } else { free(currentKey); free(descriptor); return list; } recordNumber++; } nodeNumber = descriptor->fLink; recordNumber = 0; free(descriptor); } return list; }