/************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::insertRid(const RID& newRid, int& pos) { int rc = NO_ERROR; IdxRidListEntry idxRidListEntry; if (m_curType == LIST_BLOCK_TYPE) { m_sbid = 0; m_entry = 0; } memset(&idxRidListEntry, 0, LIST_ENTRY_WIDTH) ; idxRidListEntry.type =LIST_RID_TYPE; idxRidListEntry.spare =0; //cout << "line 910:newRid->" << newRid << endl; idxRidListEntry.rid =newRid; if (m_lbid != m_hdrLbid) { rc = readCurBlk(); setSubBlockEntry( m_curBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListEntry ); m_curBlock.state = BLK_WRITE; } else { setSubBlockEntry( m_hdrBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListEntry ); m_hdrBlock.state = BLK_WRITE; } return rc; }
/************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateLastPtr(const int lastCount) { int rc; if (m_curBlock.state == BLK_INIT) readCurBlk(); if (m_useNarray) { rc = setCurBlkNextPtr(m_nextLbid, lastCount); rc = writeCurBlk(); } else { ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo = m_nextLbid; ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->sbid = 0; ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->entry= 0; m_lastIdxRidListPtr.type= LIST_BLOCK_TYPE; m_lastIdxRidListPtr.spare=0x0; m_lastIdxRidListPtr.count = lastCount; setSubBlockEntry( m_curBlock.data, m_sbid, LIST_BLOCK_LLP_POS, LIST_ENTRY_WIDTH , &m_lastIdxRidListPtr ); m_curBlock.state = BLK_WRITE; rc = writeCurBlk(); } return rc; }
const int DbFileOp::writeSubBlockEntry( CommBlock& cb, DataBlock* block, const uint64_t lbid, const int sbid, const int entryNo, const int width, void* pStruct ) { setSubBlockEntry( block->data, sbid, entryNo, width, pStruct ); block->dirty = false; return writeDBFile( cb, block->data, lbid ); }
/**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::setLastFboPtr(uint64_t& lbid, int& sbid, IdxRidListPtr& lastFboListPtr) { int rc = NO_ERROR; CommBlock cb; DataBlock dataBlock; IdxRidListPtr oldFboListPtr; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if ((m_hdrBlock.lbid == lbid) && (m_hdrBlock.state>= BLK_READ)) { setSubBlockEntry(m_hdrBlock.data, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); m_hdrBlock.state = BLK_WRITE; } else if ((m_curBlock.lbid == lbid) && (m_curBlock.state>= BLK_READ)) { setSubBlockEntry(m_curBlock.data, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); m_curBlock.state = BLK_WRITE; } else { memset( dataBlock.data, 0, sizeof(dataBlock.data)); rc = readSubBlockEntry(cb, &dataBlock, lbid, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &oldFboListPtr); if (((IdxEmptyListEntry*)&oldFboListPtr)->fbo !=m_lastLbid) { setSubBlockEntry(dataBlock.data, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); rc = writeDBFile(cb, dataBlock.data, lbid); } else return NO_ERROR; } return rc; }
/**************************************************************************** * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***************************************************************************/ const int IndexList::updateHdrCount() { int rc=NO_ERROR; if (m_hdrBlock.state == BLK_INIT) return ERR_IDX_LIST_UPDATE_HDR_COUNT; m_curIdxRidListHdr.idxRidListSize.size++; setSubBlockEntry( m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); m_hdrBlock.state = BLK_WRITE; return rc; }
/************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateCurCount(int frequency) { int rc = NO_ERROR; int pos = 0; if (m_curType == LIST_SUBBLOCK_TYPE) pos = LIST_SUB_LLP_POS; else if (m_curType == LIST_BLOCK_TYPE) { pos = LIST_BLOCK_LLP_POS; m_sbid = 0; m_entry = 0; } if ((m_useNarray) && (m_curType == LIST_BLOCK_TYPE)) rc = updateCurCountInArray(); else { rc = getNextInfoFromBlk(m_lastIdxRidListPtr); for (int i=0; i< frequency; i++) m_lastIdxRidListPtr.count++; if (m_lbid==m_hdrLbid) { setSubBlockEntry( m_hdrBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &m_lastIdxRidListPtr ); m_hdrBlock.state = BLK_WRITE; } else { setSubBlockEntry(m_curBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &m_lastIdxRidListPtr ); m_curBlock.state =BLK_WRITE; }; } return rc; }
/**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::setNextInfoFromBlk( IdxRidListPtr& idxRidListPtr) { int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; int pos = 0; if (m_curType == LIST_SUBBLOCK_TYPE) pos = LIST_SUB_LLP_POS; else if (m_curType == LIST_BLOCK_TYPE) pos = LIST_BLOCK_LLP_POS; if (m_lbid==m_hdrLbid) {//when sub == hdr setSubBlockEntry( m_hdrBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListPtr ); m_hdrBlock.state =BLK_WRITE; } else { readCurBlk(); if (m_lbid == m_curBlock.lbid) { setSubBlockEntry( m_curBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListPtr ); rc = writeDBFile(cb, m_curBlock.data, m_lbid ); m_curBlock.state =BLK_READ; } else return ERR_IDX_LIST_WRONG_LBID_WRITE; } return rc; }
/**************************************************************** * DESCRIPTION: * Private Function for getting a segment for LIST * ***************************************************************/ const int IndexList::getSegment( FILE* pFile, const IdxTreeGroupType segmentType, IdxEmptyListEntry* assignPtr ) { int rc = ERR_IDX_LIST_GET_SEGMT; CommBlock cb; uint64_t lbid0; m_pFile = pFile; cb.file.oid = m_oid; cb.file.pFile = m_pFile; /* DataBlock tmpBlock; IdxEmptyListEntry tmpEntry; memset(tmpBlock.data,0, 8192); rc = readSubBlockEntry( pFile, &tmpBlock, 1492798, 31, 31, 8, &tmpEntry ); cout << "common273->tmpEntry.fbo=" << tmpEntry.fbo << " tmpEntry.sbid=" << tmpEntry.sbid << " tmpEntry.entry=" << tmpEntry.entry << endl; */ if (m_hdrLbid != INVALID_LBID) { setSubBlockEntry(m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); m_hdrBlock.state = BLK_WRITE; } //write everything out before calling free space manager rc = updateIndexListWrite(); rc = resetBlkZero(lbid0); rc = m_freemgr.assignSegment( cb, &m_blockZero, LIST, segmentType, assignPtr); if (rc!= NO_ERROR) return rc; rc = writeBlkZero(lbid0); if (segmentType==ENTRY_4) { m_hdrLbid = assignPtr->fbo; m_hdrSbid = assignPtr->sbid; m_hdrEntry = assignPtr->entry; return rc; } //get the header back for sure //recover other blocks as it goes rc = initBlksGetHdrBlk(); return rc; }
/** * * blank out all stats, set types and groups of null pointers in block zero */ const int FreeMgr::initBlockzero( DataBlock* blockZero) { IdxEmptyListEntry Pointer; uint64_t blankVal = 0; memset(blockZero->data, 0, sizeof(blockZero->data)); nullPtr( &Pointer ); Pointer.type = EMPTY_LIST; Pointer.group = ENTRY_BLK; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_BLK), 8, &Pointer); Pointer.group = ENTRY_32; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_32), 8, &Pointer); Pointer.group = ENTRY_16; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_16), 8, &Pointer); Pointer.group = ENTRY_8; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_8), 8, &Pointer); Pointer.group = ENTRY_4; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_4), 8, &Pointer); Pointer.group = ENTRY_2; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_2), 8, &Pointer); Pointer.group = ENTRY_1; setSubBlockEntry( blockZero->data, 0, calcPtrOffset(ENTRY_1+ENTRY_1), 8, &Pointer); //all stat locations are contiguous and after the pointers in block zero for (int idx = calcStatOffset( ENTRY_1 ); idx < calcStatOffset( ENTRY_32 )+1; idx++) { setSubBlockEntry( blockZero->data, 0, idx, 8, &blankVal); } return NO_ERROR; }
const int FreeMgr::releaseSubblock( CommBlock &cb, DataBlock* blockZero, const int freemgr_type, IdxEmptyListEntry* assignPtr ) { int rc; // return code from file ops DataBlock workBlock; DataBlock extraBlock; int listOffset; // entry in block zero of head pointer IdxEmptyListEntry emptyPtr, emptyMap ; uint64_t numBlocks; FILE* indexFile; indexFile = cb.file.pFile; /** * Release sub-block - handle de-allocation of only sub-blocks * This makes the assign/release code for smaller segments simpler and * separates the tasks of handling the list containers and the list contents * When called, we look at the bucket indicated as head of chain and if it full * or not present (no room left in chain) then insert the returned SB as a bucket and * move the head pointer **/ //if( isDebug( DEBUG_1 )) { printf("DBG: releaseSubblock\n"); } if( isDebug( DEBUG_2 )) { cout<<"DBG: releasing sb fbo "<<assignPtr->fbo<<" sbid "<<assignPtr->sbid<<" entry "<<assignPtr->entry<<" from "<<((freemgr_type==LIST)?"LIST":"TREE")<<" (type is "<<((assignPtr->type==EMPTY_PTR)?"EMPTY_PTR":"Not EMPTY_PTR")<<")\n"; } if (!assignPtr){ // printf ("DBG: Bad pointer: assignPtr is zero\n"); return ERR_INVALID_PARAM; } if (!blockZero){ printf ("DBG: Bad pointer: pointer for blockZero is zero\n"); return ERR_INVALID_PARAM; } numBlocks = getFileSize( indexFile )/BYTE_PER_BLOCK ; /* if (assignPtr->fbo > numBlocks) { if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSubblock.. assignPtr.fbo > numBlocks (%llu %llu)\n", assignPtr->fbo, numBlocks );} return ERR_FM_BAD_FBO; }*/ if (assignPtr->type != EMPTY_PTR) { printf("DBG: Weirdness in releaseSubblock.. tried to return a pointer with type %i (expected %i)\n", (unsigned int)assignPtr->type, EMPTY_PTR ); return ERR_FM_BAD_TYPE; } if ( assignPtr->group != ENTRY_32 ) { printf("DBG: Weirdness in releaseSubblock.. tried to return a pointer from group %i to subblock group\n", (unsigned int)assignPtr->group ); return ERR_INVALID_PARAM; } //find the start of the chain listOffset = calcPtrOffset( ENTRY_32 ); getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); if( isDebug( DEBUG_2 )) { cout<<"DBG: EM (sb release 1) sb fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } //sub block is full or chain empty if (emptyPtr.entry == ENTRY_PER_SUBBLOCK-1 || emptyPtr.fbo==0) { // change type from EMPTY_PTR to EMPTY_LIST assignPtr->type = EMPTY_LIST; //if( isDebug( DEBUG_1 )) { printf("DBG: No room in subblock chain - need to add a sub-block\n"); } if( isDebug( DEBUG_2 )) { cout<<"DBG: Change head pointer to fbo "<<assignPtr->fbo<<" sbid "<<assignPtr->sbid<<" entry "<<assignPtr->entry<<"\n"; } // change head pointer to released segment setSubBlockEntry( blockZero, 0, listOffset, 8, assignPtr ); blockZero->dirty = 1; // read in released segment to set llp of new block to point to current head of chain rc = readDBFile( cb, extraBlock.data, assignPtr->fbo ); if (rc != NO_ERROR){ if (isDebug( DEBUG_1 )){ cout<<"DBG: File error during releaseSegment (2), rc: "<<rc<<" fbo/lbid: "<<assignPtr->fbo<<"\n"; } return rc; } if( isDebug( DEBUG_2 )) { cout<<"DBG: Set LLP for fbo "<<assignPtr->fbo<<" sbid "<<assignPtr->sbid<<" entry "<<assignPtr->entry<<"to fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } if( isDebug( DEBUG_3)){ printf("Before\n"); printMemSubBlock( &extraBlock, assignPtr->sbid ); } emptyPtr.type = EMPTY_LIST; //memset( extraBlock.data, 0, BYTE_PER_SUBBLOCK); setSubBlockEntry( extraBlock.data, assignPtr->sbid, 0, 8, &emptyPtr ); rc = writeDBFile( cb, &extraBlock, assignPtr->fbo ); if (rc != NO_ERROR){ return rc; } if( isDebug( DEBUG_2 )) { getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyMap ); cout<<"DBG: EM (sb release 2) sb fbo "<<emptyMap.fbo<<" sbid "<<emptyMap.sbid<<" entry "<<emptyMap.entry<<"\n"; } if( isDebug( DEBUG_3)){ printf("After\n"); printMemSubBlock( &extraBlock, assignPtr->sbid ); } } else { // emptyPtr.entry++; rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR) { if (isDebug( DEBUG_1 )) { printf("DBG: File error during releaseSubblock\n"); } return rc; } if( isDebug( DEBUG_3)){ printf("Before\n"); printMemSubBlock( &workBlock, emptyPtr.sbid ); } setSubBlockEntry( workBlock.data, emptyPtr.sbid, emptyPtr.entry, 8, assignPtr ); rc = writeDBFile( cb, &workBlock, emptyPtr.fbo ); if (rc != NO_ERROR){ return rc; } if( isDebug( DEBUG_2 )) { cout<<"DBG: setting emptyPtr sb fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } if( isDebug( DEBUG_3)){ printf("After\n"); printMemSubBlock( &workBlock, emptyPtr.sbid ); } emptyPtr.type = EMPTY_LIST; emptyPtr.group = ENTRY_32; setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); blockZero->dirty = 1; } uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(ENTRY_32) , 8, &count ); count++; setSubBlockEntry( blockZero, 0, calcStatOffset(ENTRY_32) , 8, &count ); return NO_ERROR; }
const int FreeMgr::releaseSegment( CommBlock &cb, DataBlock* blockZero, const int freemgr_type, const IdxTreeGroupType segmentType, IdxEmptyListEntry* assignPtr ) { int rc; // return code from file ops DataBlock workBlock; DataBlock extraBlock; int listOffset; // entry in block zero of head pointer IdxEmptyListEntry emptyPtr; IdxEmptyListEntry newSb; uint64_t numBlocks; FILE* indexFile; indexFile = cb.file.pFile; if (!assignPtr){ // printf ("DBG: Bad pointer: assignPtr is zero\n"); return ERR_INVALID_PARAM; } if (!blockZero){ // printf ("DBG: Bad pointer: blockZero is zero\n"); return ERR_INVALID_PARAM; } if( isDebug( DEBUG_3 )) { printf("DBG: release ENTRY_%i segment \n", 1<<(unsigned int)segmentType); } if( isDebug( DEBUG_2 )) { cout<<"DBG: releasing fbo "<<assignPtr->fbo<<" sbid "<<assignPtr->sbid<<" entry "<<assignPtr->entry<<" from "<<((freemgr_type==LIST)?"LIST":"TREE")<<" chain ENTRY_"<<(1<<segmentType)<<" (type is "<<((assignPtr->type==EMPTY_PTR)?"EMPTY_PTR":"Not EMPTY_PTR")<<")\n"; } numBlocks = getFileSize( indexFile )/BYTE_PER_BLOCK ; /* if (assignPtr->fbo > numBlocks) { if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSegment.. assignPtr.fbo > numBlocks (%llu %llu)\n", assignPtr->fbo, numBlocks );}; return ERR_FM_BAD_FBO; }*/ if (assignPtr->type != EMPTY_PTR) { // printf("DBG: Weirdness in releaseSegment.. tried to return a pointer with type %i (expected %i)\n", (unsigned int)assignPtr->type, EMPTY_PTR ); assignPtr->type = EMPTY_PTR; // return ERR_FM_BAD_TYPE; // do not exit } if ( assignPtr->group != (uint64_t)segmentType ) { // printf("DBG: Weirdness in releaseSegment.. tried to return a pointer from group %i to group %i\n", (unsigned int)assignPtr->group, segmentType ); return ERR_FM_RELEASE_ERR; } //find the start of the chain if (segmentType == ENTRY_32) { rc = releaseSubblock( cb, blockZero, freemgr_type, assignPtr); if (rc != NO_ERROR) { // printf("DBG: Error releasing sb\n"); } return rc; } listOffset = calcPtrOffset( segmentType ); if (freemgr_type==LIST && !(segmentType== ENTRY_4 || segmentType== ENTRY_BLK)) { printf("DBG: Assign segment size illegal %i\n", (unsigned int)segmentType); return ERR_INVALID_PARAM; // should not have got here so quit with error } getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); /* if (emptyPtr.fbo > numBlocks) { if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSegment.. emptyPtr.fbo > numBlocks (%llu %llu)\n", emptyPtr.fbo, numBlocks );} return ERR_FM_BAD_FBO; }*/ //sub block is full or chain never started if (emptyPtr.entry == ENTRY_PER_SUBBLOCK-1 || emptyPtr.fbo==0) { if( isDebug( DEBUG_3 )) { printf("DBG: No room in chain %i - need to add a sub-block\n", (unsigned int)segmentType); } if( isDebug( DEBUG_2 )) { cout<<"DBG: Empty ptr fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } //ask for a new sb to extend chain rc = assignSubblock( cb, blockZero, freemgr_type, &newSb); if (rc != NO_ERROR) { printf("DBG: Error extending chain\n"); return rc; } if( isDebug( DEBUG_2 )) { cout<<"DBG: release segment, new SB is fbo "<<newSb.fbo<<" sbid "<<newSb.sbid<<" entry "<<newSb.entry<<"\n"; } rc = readDBFile( cb, extraBlock.data, newSb.fbo ); if (rc != NO_ERROR) { if (isDebug( DEBUG_1 )){printf("DBG: File error during releaseSegment (3)\n");} return rc; } emptyPtr.type = EMPTY_LIST; // writing into the LLP field so set type accordingly setSubBlockEntry( extraBlock.data, newSb.sbid, 0, 8, &emptyPtr ); setSubBlockEntry( extraBlock.data, newSb.sbid, 1, 8, assignPtr ); rc = writeDBFile( cb, &extraBlock, newSb.fbo ); if (rc != NO_ERROR) { if (isDebug( DEBUG_1 )){printf("DBG: File error during releaseSegment (4)\n");} return rc; } newSb.entry = 1; newSb.type = EMPTY_LIST; newSb.group = segmentType; setSubBlockEntry( blockZero, 0, listOffset, 8, &newSb ); blockZero->dirty = 1; uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); count++; setSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); return NO_ERROR ; } else { // emptyPtr.entry++; rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR){ if (isDebug( DEBUG_1 )){ printf("DBG: File error during releaseSegment\n"); } return rc; } if( isDebug( DEBUG_2 )) { cout<<"DBG: Empty map ENTRY_"<<( 1<<segmentType)<<" is fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } setSubBlockEntry( workBlock.data, emptyPtr.sbid, emptyPtr.entry, 8, assignPtr ); rc = writeDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR){ return rc; } emptyPtr.type = EMPTY_LIST; emptyPtr.group = segmentType; setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); blockZero->dirty = 1;//sub block is full or chain never started } uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); count++; setSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); return NO_ERROR; }
const int FreeMgr::assignSubblock( CommBlock &cb, DataBlock* blockZero, const int freemgrType, IdxEmptyListEntry* assignPtr ) { int rc; // return code from file ops DataBlock workBlock, tempBlock; int listOffset; // entry in block zero of head pointer IdxEmptyListEntry emptyEntry; IdxEmptyListEntry emptyPtr, emptyMap; IdxEmptyListEntry newBlock; uint64_t numBlocks; FILE* indexFile; indexFile = cb.file.pFile; /** * Separated subblock assignment out from general segment assignment * Reduces the hoops to jump through **/ numBlocks = getFileSize( indexFile )/BYTE_PER_BLOCK ; if( isDebug( DEBUG_3 )) { printf("DBG: Assign subblock \n"); } //find the start of the chain listOffset = calcPtrOffset( ENTRY_32 ); getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); if( isDebug( DEBUG_2 )) { cout<<"DBG: EM (start assign) sb fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } if (emptyPtr.type != EMPTY_LIST ){ return ERR_FM_BAD_TYPE; } // if (emptyPtr.fbo > numBlocks) // { // if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in assignSubblock.. emptyPtr.fbo > numBlocks\n"); } // return ERR_FM_BAD_FBO; // } // follow the chain to the empty entry rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR) { // printf("DBG: RC Weirdness: rc is %i", rc); return rc; } getSubBlockEntry( &workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry ); if( isDebug( DEBUG_2 )) { cout<<"DBG: Next avail sb fbo "<<emptyEntry.fbo<<" sbid "<<" entry "<<emptyEntry.entry<<"\n"; } if (emptyEntry.fbo == 0) // then nowhere to go.. exit { //if( isDebug( DEBUG_1 )) { printf("DBG: No space in subblock list\n"); } if( isDebug( DEBUG_2 )) { cout<<"DBG: fbo "<<emptyEntry.fbo<<" sbid "<<emptyEntry.sbid<<" entry "<<emptyEntry.entry<<"\n"; } //-- try and assign from BLOCK list // printf("Go ask for a block\n"); rc = assignSegment( cb, blockZero, freemgrType, ENTRY_BLK, &newBlock); // rc = extendFreespace( indexFile, blockZero, freemgrType ); if (rc != NO_ERROR){ if( isDebug( DEBUG_1 )) { printf("DBG: Could not get block from block list\n"); } return rc; } // got a block so now split it newBlock.entry = 0; newBlock.group = ENTRY_32; newBlock.type = EMPTY_PTR; emptyEntry = newBlock; //-- assign almost all sub blocks - keep last one int sbIdx; for (sbIdx=BYTE_PER_BLOCK/BYTE_PER_SUBBLOCK-1; sbIdx >0; sbIdx--) { if( isDebug( DEBUG_3 )) { cout<<"DBG: Working on fbo "<<newBlock.fbo<<" sbid "<<sbIdx<<"\n"; } emptyEntry.sbid = sbIdx; emptyEntry.type = EMPTY_PTR; rc = releaseSubblock( cb, blockZero, freemgrType, &emptyEntry ); if (rc != NO_ERROR) { printf("DBG: Error releasing sb\n"); return rc; } } emptyEntry.sbid=0; } if ((emptyEntry.type != EMPTY_LIST) && (emptyEntry.type != EMPTY_PTR)) { if( isDebug( DEBUG_0 )) { printf("WTF: Bad entry in in subblock list- type is %i (expected %i or %i)\n", (unsigned int)emptyEntry.type, EMPTY_PTR, EMPTY_LIST); } if( isDebug( DEBUG_2 )) { cout<<"DBG: fbo "<<emptyEntry.fbo<<" sbid "<<emptyEntry.sbid<<" entry "<<emptyEntry.entry<<"\n"; } return ERR_FM_BAD_TYPE; } if (emptyEntry.type == EMPTY_PTR) { // this is what we expect normally emptyPtr.entry--; // only decrement if we didn't just drain a bucket setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); memcpy(assignPtr, &emptyEntry, 8); } else if (emptyEntry.type == EMPTY_LIST && emptyPtr.entry == 0 ) { if (emptyPtr.entry >0) printf("\nWTF!! %i\n", (unsigned int) emptyPtr.entry); // reached end of this bucket (should release it for re-use) // this is not the typical case.. if( isDebug( DEBUG_3 )) { cout<<"DBG: Drained bucket sb fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } //blank the llp rc = readDBFile( cb, tempBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR) { if (isDebug( DEBUG_1 )){ cout<<"DBG: File error during releaseSubblock, fbo/lbid: "<<emptyPtr.fbo<<"\n"; } return rc; } nullPtr(&emptyMap); // zero out the entry setSubBlockEntry( tempBlock.data, emptyPtr.sbid, 0, 8, &emptyMap ); rc = writeDBFile( cb, &tempBlock, emptyPtr.fbo ); if (rc != NO_ERROR){ return rc; } memcpy(assignPtr, &emptyPtr, 8); assignPtr->type = EMPTY_PTR; if( isDebug( DEBUG_2 )) { cout<<"DBG: Change head pointer to fbo "<<emptyEntry.fbo<<" sbid "<<emptyEntry.sbid<<" entry "<<emptyEntry.entry<<"\n"; } setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyEntry ); } else { printf("DBG: Weirdness - not list and not ptr\n"); } // printf("DBG: Assigned sb fbo %llu sbid %u entry %u\n", assignPtr->fbo, (unsigned int)assignPtr->sbid, (unsigned int)assignPtr->entry); getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyMap ); if(isDebug(DEBUG_3)){ cout<<"DBG: EM (sb assign 1) sb fbo "<<emptyMap.fbo<<" sbid "<<emptyMap.sbid<<" entry "<<emptyMap.entry<<"\n"; } blockZero->dirty = 1; uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(ENTRY_32) , 8, &count ); count--; setSubBlockEntry( blockZero, 0, calcStatOffset(ENTRY_32) , 8, &count ); // -- workblock may have changed on disk since it was read.. making the writeDBfile dangerous without a readDBfile first nullPtr(&emptyMap); // zero out the entry readDBFile( cb, &workBlock, emptyPtr.fbo ); setSubBlockEntry( workBlock.data, emptyPtr.sbid, emptyPtr.entry+1, 8, &emptyMap ); rc = writeDBFile( cb, &workBlock, emptyPtr.fbo ); // -- // if( isDebug( DEBUG_3 )) { printf("DBG: Assign subblock -- all done\n"); } return NO_ERROR; }
const int FreeMgr::assignSegment( CommBlock &cb, DataBlock* blockZero, const int freemgr_type, const IdxTreeGroupType segmentType, IdxEmptyListEntry* assignPtr ) { int rc; // return code from file ops DataBlock workBlock; int listOffset; // entry in block zero of head pointer IdxEmptyListEntry emptyEntry; IdxEmptyListEntry emptyPtr; IdxEmptyListEntry emptyMap; uint64_t numBlocks; IdxEmptyListEntry newSb; FILE* indexFile; indexFile = cb.file.pFile; if( isDebug( DEBUG_3 )) { printf("DBG: Assign ENTRY_%i segment in %s\n", 1<<(unsigned int)segmentType,(freemgr_type==LIST)?"LIST":"TREE"); } /* Check all input parameters are ok */ if (!blockZero){ if( isDebug( DEBUG_1 )) { printf ("DBG: Bad pointer: blockZero is zero\n"); } return ERR_INVALID_PARAM; } if (!assignPtr) { if( isDebug( DEBUG_1 )) { printf ("DBG: Bad pointer: assignPtr is zero\n"); } return ERR_INVALID_PARAM; } if (freemgr_type != TREE && freemgr_type!= LIST) { if( isDebug( DEBUG_0 )) { printf ("DBG: assignSegment: Must be TREE or LIST\n");} return ERR_INVALID_PARAM; } numBlocks = getFileSize( indexFile )/BYTE_PER_BLOCK ; //find the start of the chain if (segmentType == ENTRY_32) { rc = assignSubblock( cb, blockZero, freemgr_type, assignPtr); if (rc != NO_ERROR) { if( isDebug( DEBUG_1 )) { printf("DBG: Error assigning sb (rc=%i)\n", rc); } } return rc; } listOffset = calcPtrOffset( segmentType ); if (freemgr_type==LIST && !(segmentType== ENTRY_4 || segmentType== ENTRY_BLK)) { if( isDebug( DEBUG_1 )) { printf("DBG: Assign segment size illegal %i\n", (unsigned int)segmentType); } return ERR_INVALID_PARAM; // should not have got here so quit with error } // read Empty Map in sb0 getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); if( isDebug( DEBUG_2 )) { cout<<"DBG: Empty map ENTRY_"<<(1<<segmentType)<<" was fbo "<<emptyPtr.fbo<<" sbid "<<(unsigned int)emptyPtr.sbid<<" entry "<<(unsigned int)emptyPtr.entry<<"\n"; } /* if (emptyPtr.fbo > numBlocks) { printf("DBG: Weirdness in assignSegment.. emptyPtr.fbo > numBlocks\n"); return ERR_FM_BAD_FBO; }*/ // check to see if queue has been built // if not then assign a container block, add LLP in entry 0 pointing to nothing if (emptyPtr.fbo == 0){ if( isDebug( DEBUG_3 )) { printf("DBG: Need to add sb to chain and entries to sb\n"); } // cannot assign more space to block list from a smaller list.. need to extend the file if ( segmentType == ENTRY_BLK ) { if ( isDebug( DEBUG_1 )){ printf("Out of space in BLOCK list, quitting\n"); } rc = extendFreespace( cb, blockZero, freemgr_type ); if (rc != NO_ERROR){ if (isDebug( DEBUG_3 )){ printf("DBG: Error extending file\n"); } return rc; } } rc = assignSubblock( cb, blockZero, freemgr_type, &emptyPtr); if (rc != NO_ERROR){ printf("DBG: Error extending chain\n"); return rc; } rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR){ /*printf("DBG: Error reading newly allocated sb\n");*/ return rc; } // update map to point to new bucket setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr); nullPtr(&emptyEntry); emptyEntry.type = EMPTY_LIST; emptyEntry.group = segmentType; setSubBlockEntry( workBlock.data, emptyPtr.sbid, 0, 8, &emptyEntry); // store head ptr rc = writeDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR){ return rc; } if( isDebug( DEBUG_2 )) { cout<<"DBG: Added fbo "<<emptyPtr.fbo<<" sbid "<<(unsigned int)emptyPtr.sbid<<" as bucket to chain ENTRY_"<<(1<<segmentType)<<"in"<<((freemgr_type==LIST)?"LIST":"TREE")<<"\n"; } } // follow the chain to the head container rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR) { if( isDebug( DEBUG_1 )) { cout<<"DBG: Error reading block ("<<emptyPtr.fbo<<") during segmentAssign: rc is "<<rc; } return rc; } getSubBlockEntry( &workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry ); if ((emptyEntry.type != EMPTY_LIST) && (emptyEntry.type != EMPTY_PTR)) { if( isDebug( DEBUG_0 )) { printf("WTF: Bad entry in ENTRY_%i chain - type is %i (expected %i or %i)\n", 1<<segmentType, (unsigned int)emptyEntry.type, EMPTY_PTR, EMPTY_LIST ); printMemSubBlock( &workBlock, emptyPtr.sbid ); } if( isDebug( DEBUG_2 )) { cout<<"DBG: fbo "<<emptyEntry.fbo<<" sbid "<<(unsigned int)emptyEntry.sbid<<" entry "<< (unsigned int)emptyEntry.entry<<" chain ENTRY_"<<(1<<segmentType)<<"in"<<((freemgr_type==LIST)?"LIST":"TREE")<<"\n"; } return ERR_FM_BAD_TYPE; } if ((emptyEntry.fbo == 0) && (emptyEntry.type == EMPTY_PTR)) { if ( isDebug( DEBUG_0 )) {printf("DBG: Bad entry in %i list - found EMPTY_PTR but indicates block 0\n", 1<<segmentType );} return ERR_FM_BAD_TYPE; } if ((emptyEntry.fbo == 0) && (emptyEntry.type == EMPTY_LIST)) { /** * if at the end of the rainbow, in a bucket with no entries, fill the bucket * Allocate a sub block and split it into parts **/ // cannot assign more space to block list from a smaller list.. need to extend the file if ( segmentType == ENTRY_BLK ) { if ( isDebug( DEBUG_1 )){ printf("\nNeed to extend block\n");} if ( isDebug( DEBUG_1 )){ printf("Out of space in BLOCK list\n"); } rc = extendFreespace( cb, blockZero, freemgr_type ); if (rc != NO_ERROR){ if (isDebug( DEBUG_3 )){ printf("DBG: Error extending file\n"); } return rc; } getSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); getSubBlockEntry( &workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry ); } else { rc = assignSubblock( cb, blockZero, freemgr_type, &newSb); if (rc != NO_ERROR){ // printf("DBG: Error extending chain\n"); return rc; } if (newSb.entry != 0){ printf("WTF: Entry should be 0 after assign from sb list, instead is %i", (unsigned int)newSb.entry); return ERR_FM_ASSIGN_ERR; } if (isDebug(DEBUG_2)){ cout<<"DBG: added fbo "<<newSb.fbo<<" sbid "<<(unsigned int)newSb.sbid<<" entry "<<(unsigned) newSb.entry<<" to "<<segmentType<<" list - need to split "<<(1<<(ENTRY_32-segmentType))<<"times\n"; } newSb.entry = 0; newSb.group = segmentType; newSb.type = EMPTY_PTR; emptyEntry = newSb; int idx, inc; inc = 1<<segmentType; for (idx=0; idx < ENTRY_PER_SUBBLOCK - inc; idx+= inc){ if( isDebug( DEBUG_3 )) { printf ("DBG: split..%i-%i\n", idx, idx+inc-1 );} newSb.entry = idx; releaseSegment( cb, blockZero, freemgr_type, segmentType, &newSb ); } emptyEntry.entry = idx; if( isDebug( DEBUG_3 )) { printf ("DBG: split and return..%i-%i\n", idx, idx+inc-1); } if( isDebug( DEBUG_2 )) { cout<<"DBG: Assigned fbo "<< emptyEntry.fbo<<" sbid "<<(unsigned int)emptyEntry.sbid<<" entry "<<(unsigned int)emptyEntry.entry<<" to chain ENTRY_"<<(1<<segmentType)<<"\n"; } memcpy(assignPtr, &emptyEntry, 8); uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); count--; setSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); return NO_ERROR; } } /** * got here because we didn't need to populate a chain and did not fall into any traps * so either we are at the end of bucket or we have a valid entry **/ if (emptyEntry.type == EMPTY_LIST) // reached end of this segment (should release it for re-use) { /** * release bucket **/ if( isDebug( DEBUG_2 )) { cout<<"DBG: Need to release sb fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" from chain ENTRY_"<<(1<<segmentType)<<" in "<<((freemgr_type==LIST)?"LIST":"TREE")<<"\n"; } // when we stored the ptr in the empty map, we tweaked group, must change it back emptyPtr.type = EMPTY_PTR; emptyPtr.group = ENTRY_32; rc = releaseSubblock( cb, blockZero, freemgr_type, &emptyPtr ); if (rc != NO_ERROR) { printf("Error releasing sb\n"); return rc; } emptyPtr = emptyEntry; rc = readDBFile( cb, workBlock.data, emptyPtr.fbo ); if (rc != NO_ERROR){ printf("DBG: Error following chain\n"); return rc; } getSubBlockEntry( &workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry ); } if (emptyEntry.type == EMPTY_PTR) { emptyPtr.entry--; blockZero->dirty = 1; setSubBlockEntry( blockZero, 0, listOffset, 8, &emptyPtr ); if( isDebug( DEBUG_3 )) { printf("DBG: Empty entry is now %u\n",(unsigned int)emptyPtr.entry); } if( isDebug( DEBUG_2 )) { cout<<"DBG: Assigned fbo "<<emptyEntry.fbo<<" sbid "<<emptyEntry.sbid<<" entry "<<emptyEntry.entry<<" from chain ENTRY_"<<(1<<segmentType)<<"\n"; cout<<"DBG: Empty map ENTRY_"<<(1<<segmentType)<<" now fbo "<<emptyPtr.fbo<<" sbid "<<emptyPtr.sbid<<" entry "<<emptyPtr.entry<<"\n"; } memcpy(assignPtr, &emptyEntry, 8); // -- workblock may have changed on disk since it was read.. making the writeDBfile dangerous without a readDBfile first nullPtr(&emptyMap); // zero out the entry readDBFile( cb, &workBlock, emptyPtr.fbo ); setSubBlockEntry( workBlock.data, emptyPtr.sbid, emptyPtr.entry+1, 8, &emptyMap ); rc = writeDBFile( cb, &workBlock, emptyPtr.fbo ); // -- uint64_t count; getSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); count--; setSubBlockEntry( blockZero, 0, calcStatOffset(segmentType) , 8, &count ); return NO_ERROR; } return ERR_FM_ASSIGN_ERR; }
const int FreeMgr::init( CommBlock &cb, int freemgrType) { /** * Tree has 6 chains, (1,2,4,8,16,32 entries) starting at entry 1 in sb0 of block0 * List has 3 chains (4,32,1024 entries) starting at first entry of file * * Starting at Block 1, add each subblock after sb0 to the free list in sb0 * then go back and build the smaller chains on demand. This way we make sure all SBs * are in a chain somewhere.. but this is not best behaviour when allocating blocks * **/ int rc; // return code from file ops DataBlock blockZero; DataBlock workBlock; int sbIdx; uint64_t blkIdx; IdxEmptyListEntry emptyEntry; // populate the chains with pointer to empty entries IdxEmptyListEntry nextPointer; // pointer at end of sub-block of pointers to emptyEntries uint64_t numBlocks; FILE* indexFile; indexFile = cb.file.pFile; if (!indexFile) // Make sure that we have non-null filehandle { // printf("DBG: File handle is null\n"); return ERR_INVALID_PARAM; } if (freemgrType!=TREE && freemgrType!=LIST){ // printf("DBG: Bad type in freeMgr Init\n"); return ERR_INVALID_PARAM; } numBlocks = getFileSize( indexFile )/BYTE_PER_BLOCK ; // printf ("DBG: File size: %lu Total blocks: %llu (%u)\n", getFileSize( indexFile ), numBlocks, BYTE_PER_BLOCK); // printf ("DBG: Adding sub-blocks: %llu \n", numBlocks * 32); // Clear the list of pointers in sb0 initBlockzero( &blockZero ); // initialize the non varying fields nullPtr(&emptyEntry); emptyEntry.type = EMPTY_PTR; emptyEntry.group = ENTRY_32; // nextPointer identifies next sub-block with empty pointers // initially there is no next sub-block so zero it out nullPtr(&nextPointer); nextPointer.type = EMPTY_LIST; nextPointer.group = ENTRY_32; nextPointer.entry = ENTRY_PER_SUBBLOCK-1; // last entry on the list.. think of the list as a stack if (initType == 0){ if( isDebug( DEBUG_3 )) { printf("\nOld style init\n"); } for ( blkIdx = numBlocks-1; blkIdx > 0; blkIdx-- ) { emptyEntry.fbo = blkIdx;// map fbo to lbid before storage // emptyEntry.fbo = mapLBID( cb, blkIdx, rc );// map fbo to lbid before storage // if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n", cb.file.oid, blkIdx-1 ); return rc; } if( isDebug( DEBUG_3 )) { cout<<"DBG: Working on block "<<emptyEntry.fbo<<"\n"; } memset(workBlock.data, 0, sizeof(workBlock.data)); /** * each block after zeroth block uses sb0 to store entry list * first entry (#0) is the llp to additional sblks with entries * entries 1-31 are pointers **/ // sb0 is used for initial map, so start at sb1 for (sbIdx=1; sbIdx < BYTE_PER_BLOCK/BYTE_PER_SUBBLOCK; sbIdx++) { if( isDebug( DEBUG_3 )) { printf("DBG: Working on subblock %u\n", sbIdx); } emptyEntry.sbid = sbIdx; emptyEntry.type = EMPTY_PTR; // store pointer in sb0 - replace this with a releaseSubblock call setSubBlockEntry( workBlock.data, 0, sbIdx, 8, &emptyEntry); if( isDebug( DEBUG_2 )) { cout<<"DBG: Init sb fbo "<<emptyEntry.fbo<<" sbid "<<emptyEntry.sbid<<" entry "<<emptyEntry.entry<<"\n"; } } // having stored all pointers, store linkptr setSubBlockEntry( workBlock.data, 0, 0, 8, &nextPointer); // nextPointer.fbo = mapLBID( cb, blkIdx, rc ); // remember this block ID nextPointer.fbo = blkIdx; // remember this block ID // if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n", cb.file.oid, blkIdx-1 ); return rc; } rc = writeDBFile( cb, workBlock.data, emptyEntry.fbo ); if (rc != NO_ERROR){ return rc; } } // chain for segments of sub block size setSubBlockEntry( blockZero.data, 0, calcPtrOffset(ENTRY_32), 8, &nextPointer); /** * the next algorithm uses the release sub-block method and does not layout the map on particular boundaries. **/ } else if (initType == 1) { // new style - use release if( isDebug( DEBUG_3 )) { printf("\nNew style\n"); } for ( blkIdx = numBlocks-1; blkIdx > 0; blkIdx-- ) { emptyEntry.fbo = blkIdx;// map fbo to lbid before storage // emptyEntry.fbo = mapLBID( cb, blkIdx, rc );// map fbo to lbid before storage // if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n", cb.file.oid, blkIdx-1 ); return rc; } if( isDebug( DEBUG_3 )) { cout<<"DBG: Working on block "<<emptyEntry.fbo<<"\n"; } memset(workBlock.data, 0, sizeof(workBlock.data)); for (sbIdx=BYTE_PER_BLOCK/BYTE_PER_SUBBLOCK-1; sbIdx >-1; sbIdx--) { if( isDebug( DEBUG_3 )) { printf("DBG: Working on subblock %u\n", sbIdx); } emptyEntry.sbid = sbIdx; emptyEntry.type = EMPTY_PTR; // store pointer in sb0 - replace this with a releaseSubblock call rc = releaseSubblock( cb, &blockZero, freemgrType, &emptyEntry ); if (rc != NO_ERROR){ printf("Error releasing sb\n"); return rc; } } } /** * the next algorithm uses the release sub-block method and does not layout the map on particular boundaries. * It also allows pieces to be allocated **/ } else if (initType == 2){ /** The following calls to init accept FBO not LBID.. * This makes it easier to work on a range of blocks **/ // use the first block of the new range for sub-block chain // and the rest for block chain rc = init( cb, &blockZero, freemgrType, ENTRY_32, 1, 50); if ( rc != NO_ERROR ) { return rc; } rc = init( cb, &blockZero, freemgrType, ENTRY_BLK, 51, numBlocks-52); if ( rc != NO_ERROR ) { return rc; } } // now write sb0 back to disk if ( isDebug( DEBUG_2 )) { printf("Writing SB0 back to disk\n"); printMemSubBlock( &blockZero, 0 ); } uint64_t lbid = mapLBID( cb, 0, rc); if (rc != NO_ERROR ){ return rc; } rc = writeDBFile( cb, blockZero.data, lbid ); if (rc != NO_ERROR) { return rc; } return NO_ERROR; }
const int IndexList::deleteInBlock(const RID& rowId) { int width =LIST_ENTRY_WIDTH; int rc =ERR_IDX_LIST_INVALID_DELETE; IdxRidListPtr* lastIdxRidListPtr; IdxRidListPtr lastSubIdxRidListPtr; bool found; int type, count; IdxRidListPtr prevIdxRidListPtr; int prevSbid, prevEntry, prevType; uint64_t prevLbid; DataBlock prevDataBlock; int pos =0, totalbytes=0; int preTotalBytes, prevPos ; //IdxRidNextListPtr *nextIdxListPtr; IdxRidListEntry rowIdArray[MAX_BLOCK_ENTRY]; IdxRidListEntry newRowIdArray[MAX_BLOCK_ENTRY]; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; //This is the sub block info prevLbid = m_lbid; prevSbid = m_sbid; prevEntry = m_entry; prevPos = LIST_SUB_LLP_POS; preTotalBytes = SUBBLOCK_TOTAL_BYTES; if (prevLbid == m_hdrLbid) { if (m_hdrBlock.state >=BLK_READ) getSubBlockEntry(m_hdrBlock.data, m_sbid, prevPos, LIST_ENTRY_WIDTH, &lastSubIdxRidListPtr ); else return ERR_IDX_LIST_INVALID_DELETE; } else { if (m_curBlock.state >=BLK_READ) getSubBlockEntry(m_curBlock.data, m_sbid, prevPos, LIST_ENTRY_WIDTH, &lastSubIdxRidListPtr ); else return ERR_IDX_LIST_INVALID_DELETE; } found = false; m_lbid = ((IdxEmptyListEntry*)&lastSubIdxRidListPtr)->fbo; m_sbid = 0; m_entry = 0; type = lastSubIdxRidListPtr.type; count = lastSubIdxRidListPtr.count; pos = LIST_BLOCK_LLP_POS; totalbytes = BYTE_PER_BLOCK; //Not found in the first sub while ((!found) &&(type==LIST_BLOCK_TYPE)) { rc = readSubBlockEntry(cb, &m_curBlock, m_lbid, 0, 0, totalbytes, rowIdArray); if (rc != NO_ERROR) return rc; m_curBlock.dirty = true; m_curBlock.state =BLK_READ; m_curBlock.lbid = m_lbid; prevType = type; //Save it just in case not found here lastIdxRidListPtr =(IdxRidListPtr *) &rowIdArray[pos]; type = lastIdxRidListPtr->type; count = lastIdxRidListPtr->count; //prepared for not found in current block //find out what is the next type //Next Type is needed here for (int i=0; i<count; i++) { if (rowIdArray[i].rid == rowId) {//found the rowid memcpy(&newRowIdArray[0],&rowIdArray[0],totalbytes); found = true; m_dLbid = m_lbid; m_dSbid = m_sbid; m_dEntry = i; lastIdxRidListPtr->count--; if (lastIdxRidListPtr->count==0) { if (!m_useNarray) { //get the previous value out, could be a sub block if (prevLbid == m_hdrLbid) getSubBlockEntry(m_hdrBlock.data, prevSbid, prevPos, LIST_ENTRY_WIDTH, &prevIdxRidListPtr); else if (prevLbid == m_lbid) getSubBlockEntry(m_curBlock.data, prevSbid, prevPos, LIST_ENTRY_WIDTH, &prevIdxRidListPtr); else rc = readSubBlockEntry(cb, &prevDataBlock, prevLbid, prevSbid, prevPos, LIST_ENTRY_WIDTH, &prevIdxRidListPtr); if (rc != NO_ERROR) return rc; //check the type before set if (type == LIST_BLOCK_TYPE) { ((IdxEmptyListEntry*)&prevIdxRidListPtr)->fbo = ((IdxEmptyListEntry*)lastIdxRidListPtr)->fbo; ((IdxEmptyListEntry*)&prevIdxRidListPtr)->sbid = ((IdxEmptyListEntry*)lastIdxRidListPtr)->sbid; ((IdxEmptyListEntry*)&prevIdxRidListPtr)->entry = ((IdxEmptyListEntry*)lastIdxRidListPtr)->entry; //safety check prevIdxRidListPtr.type= type; } else // If no more links, the current one is gone also { if (prevIdxRidListPtr.count>0) { prevIdxRidListPtr.type =0; prevIdxRidListPtr.llp = 0; } else {//In case it is a sub block, not released with 0 count prevIdxRidListPtr.type =LIST_NOT_USED_TYPE; prevIdxRidListPtr.llp = 0; } }//end if type =LIST_SUBBLOCK_TYPE,LIST_BLOCK_TYPE //;set to LIST_NOT_USED_TYPE--unused before release lastIdxRidListPtr->type=LIST_NOT_USED_TYPE; lastIdxRidListPtr->llp =0; if (prevPos == LIST_BLOCK_LLP_POS) { if (prevLbid<m_lastLbid) rc = setLastLbid(prevLbid); } } } //end if count==0 else { memcpy(&rowIdArray[i],&newRowIdArray[i+1],(count-(i+1))*LIST_ENTRY_WIDTH); if (m_lastLbid > m_lbid) rc = setLastLbid(m_lbid); }//count check //Found rowId rowIdArray[count-1].type=LIST_NOT_USED_TYPE; rowIdArray[count-1].rid =0; m_curIdxRidListHdr.idxRidListSize.size--; //Write Out Put in another routine if ((prevLbid==m_hdrLbid) && (m_lbid != m_hdrLbid)) {// AAC --3 if (!m_useNarray) { if (lastIdxRidListPtr->count ==0) { setSubBlockEntry( m_hdrBlock.data, prevSbid, prevPos, width, &prevIdxRidListPtr ); } } setSubBlockEntry( m_curBlock.data, m_sbid, 0, totalbytes, rowIdArray ); setSubBlockEntry( m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid); if (rc != NO_ERROR) return rc; rc = writeDBFile( cb, m_curBlock.data, m_lbid); if (rc != NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; m_curBlock.state = BLK_READ; } else { //ABC -- if (!m_useNarray) { if (lastIdxRidListPtr->count ==0) { setSubBlockEntry( prevDataBlock.data, prevSbid, prevPos, LIST_ENTRY_WIDTH, &prevIdxRidListPtr ); rc = writeDBFile( cb, prevDataBlock.data,prevLbid); if (rc != NO_ERROR) return rc; } } setSubBlockEntry( m_curBlock.data, m_sbid, 0, totalbytes, rowIdArray ); setSubBlockEntry( m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid); if (rc != NO_ERROR) return rc; rc = writeDBFile( cb, m_curBlock.data, m_lbid); memset(m_hdrBlock.data,0, sizeof(m_hdrBlock.data)); if (rc != NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; m_curBlock.state = BLK_READ; } //last case A B C --end 5 //Done with writing to disk // Now we need to release the segment if (!m_useNarray) { if (lastIdxRidListPtr->count ==0) { rc = releaseSegment(); if (rc != NO_ERROR) return rc; }// end release segment when count ==0 } m_entry =i; //for use in findRow ID return rc; //DONE !!!found then we return, no need to go on }//FOUND THE ROWID returned !!!! }//for loop i not found continue to i++ //NOT FOUND in this block go to next block //assigning the current llp as previous llp:lbid, sbid, entry prevLbid = m_lbid; prevSbid = 0; prevEntry = 0; prevPos = pos; preTotalBytes = totalbytes; m_lbid = ((IdxEmptyListEntry*)lastIdxRidListPtr)->fbo; m_sbid = 0; m_entry = 0; }// end while if (!found) rc = ERR_IDX_LIST_INVALID_DELETE; return rc; }
/**************************************************************** * DESCRIPTION: * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateHdrSub(const RID& newRid, const uint64_t &key) { int rc = ERR_IDX_LIST_INVALID_UP_HDR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if (m_curIdxRidListHdr.firstIdxRidListEntry.type == (int)LIST_NOT_USED_TYPE) { m_curIdxRidListHdr.firstIdxRidListEntry.type =LIST_RID_TYPE; m_curIdxRidListHdr.firstIdxRidListEntry.rid = newRid; m_curIdxRidListHdr.idxRidListSize.size++; if (m_hdrBlock.lbid == m_hdrLbid) rc = writeSubBlockEntry( cb, &m_hdrBlock, m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); else return ERR_IDX_LIST_WRONG_LBID_WRITE; m_hdrBlock.state = BLK_READ; return rc; };//Done //Check Header last entry's type and go to different next step m_nextType = m_curIdxRidListHdr.nextIdxRidListPtr.type; switch (m_nextType) { case LIST_NOT_USED_TYPE://Header is not full //insert row id into header last enty m_curIdxRidListHdr.nextIdxRidListPtr.type=LIST_RID_TYPE; m_curIdxRidListHdr.nextIdxRidListPtr.llp= newRid; m_curIdxRidListHdr.idxRidListSize.size++; if (m_hdrBlock.lbid == m_hdrLbid) rc =writeSubBlockEntry( cb, &m_hdrBlock,m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr); else return ERR_IDX_LIST_WRONG_LBID_WRITE; m_hdrBlock.state = BLK_READ; m_lastLbid = INVALID_LBID; break; case LIST_RID_TYPE://Header is full, need a new sub-block RID oldRid ; IdxEmptyListEntry newIdxListEntry; oldRid = m_curIdxRidListHdr.nextIdxRidListPtr.llp; //need a sub block m_segType = LIST_SUBBLOCK_TYPE; rc= moveRidsToNewSub(m_pFile, oldRid,newRid,&newIdxListEntry); if (rc!=NO_ERROR) return rc; //update header count twice m_curIdxRidListHdr.nextIdxRidListPtr.type = m_segType; m_curIdxRidListHdr.nextIdxRidListPtr.llp = ((IdxRidListHdrPtr*)&newIdxListEntry)->llp; m_curIdxRidListHdr.nextIdxRidListPtr.spare= 0; m_curIdxRidListHdr.idxRidListSize.size++; setSubBlockEntry(m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid ); if (rc!=NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; m_lastLbid = INVALID_LBID; if (m_curBlock.state==BLK_WRITE) { rc = writeDBFile( cb, m_curBlock.data, m_lbid ); m_curBlock.state = BLK_READ; } break; case LIST_SUBBLOCK_TYPE: //first one is a sub block m_lbid= ((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->fbo; m_sbid=((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->sbid; m_entry=((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->entry; m_curType = m_nextType; m_segType = LIST_BLOCK_TYPE; rc =readCurBlk(); rc = getNextInfoFromBlk(m_lastIdxRidListPtr); rc = addRidInSub(newRid, m_lastIdxRidListPtr); break; default: rc=ERR_IDX_LIST_INVALID_UP_HDR; break; } //end of switch return rc; }
/************************************************ * Description: * Find a entry for the given rowId and Key * Then Delete it from the list * Move the rest of the row id up in the same * sub block an decrement the count in that subblock * decrement the header size * Converted * input * pFile -- File Handler * rowId -- row id * key -- value * curIdxRidListHdrPtr - point to the header * * return value * Success -- 0 * Fail -- ERR_IDX_LIST_INVALID_DELETE ************************************************/ const int IndexList::deleteInSub( const RID& rowId) { int rc =ERR_IDX_LIST_INVALID_DELETE; DataBlock prevDataBlock; int pos =0, totalbytes=0; IdxRidListPtr* lastIdxRidListPtr; int type; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; //get thelbid sbid and entry out from the header last entry //First Sub-block m_lbid=((IdxEmptyListEntry*)&(m_curIdxRidListHdr.nextIdxRidListPtr))->fbo; m_sbid=((IdxEmptyListEntry*)&(m_curIdxRidListHdr.nextIdxRidListPtr))->sbid; m_entry=((IdxEmptyListEntry*)&(m_curIdxRidListHdr.nextIdxRidListPtr))->entry; //Read the pointer entry at LIST_SUB_LLP_POS location IdxRidListEntry rowIdArray[MAX_BLOCK_ENTRY]; IdxRidListEntry newRowIdArray[MAX_BLOCK_ENTRY]; memset(rowIdArray,0,BYTE_PER_BLOCK); memset(newRowIdArray,0,BYTE_PER_BLOCK); //First link pos = LIST_SUB_LLP_POS; totalbytes = SUBBLOCK_TOTAL_BYTES; m_entryGroup = ENTRY_32; if (m_lbid!=m_hdrLbid) { rc = readDBFile(cb, &m_curBlock, m_lbid ); if (rc != NO_ERROR) return rc; rc = readSubBlockEntry(cb, &m_curBlock, m_lbid, m_sbid, 0, totalbytes, rowIdArray); if (rc != NO_ERROR) return rc; m_curBlock.dirty=true; m_curBlock.lbid = m_lbid; m_curBlock.state = BLK_READ; } else { if (m_hdrBlock.state >= BLK_READ) getSubBlockEntry(m_hdrBlock.data, m_sbid, 0, totalbytes, rowIdArray ); else return ERR_IDX_LIST_INVALID_DELETE; } lastIdxRidListPtr=(IdxRidListPtr*)&rowIdArray[pos]; int count; type = lastIdxRidListPtr->type; //next type count = lastIdxRidListPtr->count;//current count for (int i=0; i<count; i++) { if (rowIdArray[i].rid == rowId) {//found m_dLbid = m_lbid; m_dSbid = m_sbid; m_dEntry= i; rc = NO_ERROR; memcpy(&newRowIdArray[0], &rowIdArray[0], totalbytes); lastIdxRidListPtr->count--; if (lastIdxRidListPtr->count==0) { if (type == LIST_SIZE_TYPE) { //header has no link m_curIdxRidListHdr.nextIdxRidListPtr.type =LIST_NOT_USED_TYPE; m_curIdxRidListHdr.nextIdxRidListPtr.llp= 0; } }//header's link block has nothing now else //still have more { memcpy(&rowIdArray[i],&newRowIdArray[i+1],(count-(i+1))*LIST_ENTRY_WIDTH); } //last row id entry now moved up, so not used rowIdArray[count-1].type =LIST_NOT_USED_TYPE; rowIdArray[count-1].rid =0; rowIdArray[count-1].spare =0; //header update the size m_curIdxRidListHdr.idxRidListSize.size--; if (m_lbid!=m_hdrLbid) { setSubBlockEntry( m_curBlock.data, m_sbid,0, totalbytes, rowIdArray ); rc = writeDBFile( cb, m_curBlock.data, m_lbid); if (rc != NO_ERROR) return rc; m_curBlock.state =BLK_READ; rc = writeSubBlockEntry(cb,&m_hdrBlock, m_hdrLbid,m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); if (rc != NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; } else {//m_lbid==m_hdrLbid setSubBlockEntry( m_hdrBlock.data, m_sbid,0, totalbytes, rowIdArray ); setSubBlockEntry( m_hdrBlock.data, m_hdrSbid,m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr); m_hdrBlock.state = BLK_WRITE; rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid); if (rc != NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; } //end if m_lbid==m_hdrHdrLbid m_dEntry = i; return rc; }//endif found }//end for return rc; }