/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* ========================================================================== */ /* */ /* Filename.c */ /* (c) 2001 Author */ /* */ /* Description */ /* */ /* ========================================================================== */ #include #include #ifndef _MSC_VER #include #endif #include "we_indexlist.h" using namespace std; namespace WriteEngine { /**************************************************************** * DESCRIPTION: * Private Function for getting the last Fbo on header * ***************************************************************/ const int IndexList::init() { memset( m_hdrBlock.data, 0, sizeof(m_hdrBlock.data)); memset( m_curBlock.data, 0, sizeof(m_curBlock.data)); memset( m_nextBlock.data, 0, sizeof(m_nextBlock.data)); memset( m_blockZero.data, 0, sizeof(m_blockZero.data)); memset( m_parentBlock.data, 0, sizeof(m_parentBlock.data)); memset( &m_curIdxRidListHdr, 0, LIST_HDR_SIZE ); m_curIdxRidListHdr.key = INVALID_KEY; memset( &m_idxRidListArrayPtr, 0, sizeof(IdxRidListArrayPtr) ); memset( &m_lastIdxRidListPtr, 0, sizeof(IdxRidListPtr) ); m_hdrBlock.dirty = false; m_curBlock.dirty = false; m_nextBlock.dirty = false; m_blockZero.dirty = false; m_parentBlock.dirty = false; m_hdrBlock.state = BLK_INIT; m_curBlock.state = BLK_INIT; m_nextBlock.state = BLK_INIT; m_blockZero.state = BLK_INIT; m_parentBlock.state = BLK_INIT; m_hdrBlock.lbid = INVALID_LBID; m_curBlock.lbid = INVALID_LBID; m_nextBlock.lbid = INVALID_LBID; m_blockZero.lbid = INVALID_LBID; m_parentBlock.lbid = INVALID_LBID; m_lbid =INVALID_LBID; m_sbid =INVALID_NUM; m_entry =INVALID_NUM; m_hdrLbid =INVALID_LBID; m_hdrSbid =INVALID_NUM; m_hdrEntry =INVALID_NUM; m_nextLbid =INVALID_LBID; m_nextSbid =INVALID_NUM; m_nextEntry =INVALID_NUM; m_parentLbid = INVALID_LBID; m_lastLbid = INVALID_LBID; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for getting the last Fbo on header * ***************************************************************/ const int IndexList::initBlksGetHdrBlk() { int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; memset( m_hdrBlock.data, 0, sizeof(m_hdrBlock.data)); memset( m_curBlock.data, 0, sizeof(m_curBlock.data)); memset( m_nextBlock.data, 0, sizeof(m_nextBlock.data)); memset( m_blockZero.data, 0, sizeof(m_blockZero.data)); memset( m_parentBlock.data, 0, sizeof(m_curBlock.data)); m_hdrBlock.dirty = false; m_curBlock.dirty = false; m_nextBlock.dirty = false; m_blockZero.dirty = false; m_parentBlock.dirty = false; m_hdrBlock.state = BLK_INIT; m_curBlock.state = BLK_INIT; m_nextBlock.state = BLK_INIT; m_blockZero.state = BLK_INIT; m_parentBlock.state = BLK_INIT; //Get the header info if the header exist already if (m_hdrLbid != (uint64_t)INVALID_LBID) { memset( &m_curIdxRidListHdr, 0, LIST_HDR_SIZE ); rc =readSubBlockEntry(cb,&m_hdrBlock,m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); m_hdrBlock.dirty = true; m_hdrBlock.lbid = m_hdrLbid; m_hdrBlock.state = BLK_READ; } return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting the last Fbo on header * ***************************************************************/ const int IndexList::initGetHdr(const uint64_t &key, IdxEmptyListEntry* curIdxRidListHdrPtr) { int rc; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; rc = init(); m_hdrLbid =curIdxRidListHdrPtr->fbo; m_hdrSbid =curIdxRidListHdrPtr->sbid; m_hdrEntry =curIdxRidListHdrPtr->entry; memset( &m_curIdxRidListHdr, 0, LIST_HDR_SIZE ); rc =readSubBlockEntry(cb, &m_hdrBlock,m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); m_hdrBlock.dirty = true; m_hdrBlock.lbid = m_hdrLbid; m_hdrBlock.state = BLK_READ; if (m_curIdxRidListHdr.nextIdxRidListPtr.type == (int)LIST_SUBBLOCK_TYPE) rc = getLastLbid(); else m_lastLbid = INVALID_LBID; return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting the header * ***************************************************************/ const int IndexList::getHdrInfo(IdxEmptyListEntry* curIdxRidListHdrPtr) { int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; //Get the Header block, sub-block and entry info from Index Tree m_hdrLbid = curIdxRidListHdrPtr->fbo; m_hdrSbid = curIdxRidListHdrPtr->sbid; m_hdrEntry = curIdxRidListHdrPtr->entry; memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data)); m_hdrBlock.dirty = false; m_hdrBlock.state = BLK_INIT; m_hdrBlock.no = INVALID_NUM; m_hdrBlock.lbid = INVALID_LBID; //header is 4 entries LIST_HDR_SIZE bytes memset( &m_curIdxRidListHdr, 0, LIST_HDR_SIZE ); //Get the old header out rc = readDBFile( cb, &m_hdrBlock, m_hdrLbid ); m_hdrBlock.dirty = true; m_hdrBlock.state = BLK_READ; m_hdrBlock.lbid = m_hdrLbid; getSubBlockEntry( m_hdrBlock.data, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr ); if (m_curIdxRidListHdr.nextIdxRidListPtr.type == (int)LIST_SUBBLOCK_TYPE) rc = getLastLbid(); else m_lastLbid = INVALID_LBID; return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting a segment for LIST * ***************************************************************/ const int IndexList::resetBlk(DataBlock* dataBlk) { memset( dataBlk->data, 0, sizeof(dataBlk->data)); dataBlk->dirty = false; dataBlk->state = BLK_INIT; dataBlk->lbid = INVALID_LBID; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for getting block zero * either it is 0 or get it from BRM * ***************************************************************/ const int IndexList::resetBlkZero(uint64_t& lbid0) { int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; memset( m_blockZero.data, 0, sizeof(m_blockZero.data)); m_blockZero.dirty = false; m_blockZero.state = BLK_INIT; #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID rc = BRMWrapper::getInstance()->getBrmInfo( m_oid, 0, lbid0 ); #endif if (rc != NO_ERROR) return rc; rc = readDBFile( cb, m_blockZero.data, lbid0 ); m_blockZero.lbid = lbid0; m_blockZero.state = BLK_READ; return rc; } /**************************************************************** * DESCRIPTION: * Private Function for writing block zero * ***************************************************************/ const int IndexList::writeBlkZero(uint64_t& lbid0) { int rc; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; rc = writeDBFile( cb, m_blockZero.data, lbid0 ); memset( m_blockZero.data, 0, sizeof(m_blockZero.data)); m_blockZero.dirty = false; m_blockZero.state = BLK_INIT; 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; } /**************************************************************** * DESCRIPTION: * Private Function for releasing a segment for LIST * Only block can be released, not subblock or header * ***************************************************************/ const int IndexList::releaseSegment() { IdxEmptyListEntry releasePtrEntry; int entryType = 0; int rc; uint64_t lbid0; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; memset(&releasePtrEntry,0, sizeof(IdxEmptyListEntry)); releasePtrEntry.fbo = m_lbid; releasePtrEntry.sbid = 0; releasePtrEntry.entry = 0; releasePtrEntry.spare =0; entryType =ENTRY_BLK; // The following is related to ptr releasePtrEntry.spare2=0 ; releasePtrEntry.type = EMPTY_PTR; releasePtrEntry.group = entryType; //release free manager rc = resetBlkZero(lbid0); rc = m_freemgr.releaseSegment( cb,&m_blockZero, LIST, (const IdxTreeGroupType)entryType, &releasePtrEntry ); rc = writeBlkZero(lbid0); return rc; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::setLastLbid( uint64_t& lastLbid) { int rc = NO_ERROR; uint64_t lbid; int sbid,entry; IdxRidListPtr lastFboListPtr; if (m_curIdxRidListHdr.nextIdxRidListPtr.type != (int)LIST_SUBBLOCK_TYPE) { m_lastLbid = INVALID_LBID; return NO_ERROR; } if (m_curType == LIST_SUBBLOCK_TYPE) { m_lastLbid = INVALID_LBID; return NO_ERROR; } else { m_lastLbid = lastLbid; } rc = getSubBlk(lbid, sbid, entry); //First link memset(&lastFboListPtr, 0, sizeof(lastFboListPtr)); lastFboListPtr.type = LIST_BLOCK_TYPE ; ((IdxEmptyListEntry*)&lastFboListPtr)->fbo = m_lastLbid; ((IdxEmptyListEntry*)&lastFboListPtr)->sbid = 0; ((IdxEmptyListEntry*)&lastFboListPtr)->entry = 0; lastFboListPtr.spare = 0x0; rc = setLastFboPtr(lbid, sbid, lastFboListPtr); return rc; } /**************************************************************** * 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; } /**************************************************************** * DESCRIPTION: * Private Function for getting the last Fbo on header * ***************************************************************/ const int IndexList::getLastLbid() { int rc = NO_ERROR; uint64_t lbid; int sbid,entry; IdxRidListPtr lastFboListPtr; if (m_curIdxRidListHdr.nextIdxRidListPtr.type !=(int)LIST_SUBBLOCK_TYPE) { m_lastLbid = INVALID_LBID; return NO_ERROR; } rc = getSubBlk(lbid, sbid, entry); //First link rc = getLastFboPtr(lbid, sbid, lastFboListPtr); if (lastFboListPtr.type == (int)LIST_BLOCK_TYPE) { m_lastLbid = ((IdxEmptyListEntry*)&lastFboListPtr)->fbo; } else m_lastLbid = INVALID_LBID; return rc; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::getLastFboPtr(uint64_t& lbid, int& sbid, IdxRidListPtr& lastFboListPtr) { int rc = NO_ERROR; CommBlock cb; DataBlock dataBlock; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if ((m_hdrBlock.lbid == lbid) && (m_hdrBlock.state>= BLK_READ)) { getSubBlockEntry(m_hdrBlock.data, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); } else if ((m_curBlock.lbid == lbid) && (m_curBlock.state>= BLK_READ)) { getSubBlockEntry(m_curBlock.data, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); } else { memset( dataBlock.data, 0, sizeof(dataBlock.data)); dataBlock.dirty = false; dataBlock.state = BLK_INIT; rc = readSubBlockEntry(cb, &dataBlock, lbid, sbid, LIST_LAST_LBID_POS, LIST_ENTRY_WIDTH, &lastFboListPtr); } return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting the sub block * ***************************************************************/ const int IndexList::getSubBlk() { int rc = NO_ERROR; uint64_t lbid; int sbid,entry; RID rowIdArray[ENTRY_PER_SUBBLOCK]; DataBlock dataBlk; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; memset( dataBlk.data, 0, sizeof(dataBlk.data)); rc = getSubBlk(lbid, sbid, entry); if (lbid != INVALID_LBID) rc = readSubBlockEntry(cb, &dataBlk, lbid, sbid, 0, BYTE_PER_SUBBLOCK, rowIdArray); return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting the sub block * ***************************************************************/ const int IndexList::getSubBlk(uint64_t& lbid, int& sbid, int& entry) { int rc = NO_ERROR; if (m_curIdxRidListHdr.nextIdxRidListPtr.type == (int)LIST_SUBBLOCK_TYPE) { lbid= ((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->fbo; sbid=((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->sbid; entry=((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->entry; } else { lbid = INVALID_LBID; sbid = INVALID_NUM; entry= INVALID_NUM; return ERR_IDX_LIST_GET_SUB_BLK; } return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting a particular block * ***************************************************************/ const int IndexList::getBlk(uint64_t& lbid) { int rc = NO_ERROR; RID rowIdArray[MAX_BLOCK_ENTRY]; DataBlock dataBlk; CommBlock cb; memset( dataBlk.data, 0, sizeof(dataBlk.data)); cb.file.oid = m_oid; cb.file.pFile = m_pFile; rc = readSubBlockEntry(cb, &dataBlk, lbid, 0, 0, BYTE_PER_BLOCK, rowIdArray); return rc; } /**************************************************************** * DESCRIPTION: * Update Write in one call * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateIndexListWrite() { int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; //Now write in one place if (m_hdrBlock.state == BLK_WRITE) {//A rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid ); if (rc!= NO_ERROR) return rc; m_hdrBlock.state = BLK_READ; } if (m_curBlock.state == BLK_WRITE) {//B rc = writeDBFile( cb, m_curBlock.data, m_lbid ); if (rc!= NO_ERROR) return rc; m_curBlock.state = BLK_READ; } if (m_parentBlock.state == BLK_WRITE) { rc = writeDBFile( cb, m_parentBlock.data, m_parentLbid ); if (rc!= NO_ERROR) return rc; m_parentBlock.state = BLK_READ; } if (m_nextBlock.state == BLK_WRITE) { rc = writeDBFile( cb, m_nextBlock.data, m_nextLbid ); if (rc!= NO_ERROR) return rc; m_nextBlock.state =BLK_READ; } return rc; } /************************************************ * Description: * Find a entry for the given rowId and Key * Converted * input * pFile -- File Handler * rowId -- row id * key -- value * curIdxRidListHdrPtr - point to the header * output * lbid -- File block id * sbid -- Sub Block id * entry -- Entry id * * * return value * true --found * false--not found ************************************************/ const int IndexList::findFirstBlk(FILE* pFile, const uint64_t& key, IdxEmptyListEntry* curIdxRidListHdrPtr, uint64_t& lbid) { int rc; CommBlock cb; int count; cb.file.oid = m_oid; cb.file.pFile = pFile; m_pFile = pFile; rc = getHdrInfo(curIdxRidListHdrPtr); if (key!= m_curIdxRidListHdr.key) { return ERR_IDX_LIST_INVALID_KEY;; } int type = m_curIdxRidListHdr.nextIdxRidListPtr.type; switch (type) { case LIST_NOT_USED_TYPE://Header is not full, no sub-block linked lbid = INVALID_LBID; return NO_ERROR; //not found case LIST_RID_TYPE:// There is a row id here, Check! lbid = INVALID_LBID; return NO_ERROR; //not found case LIST_SUBBLOCK_TYPE://Not found in header //get the lbid sbid and entry out from the header last entry rc = getSubBlk(m_lbid, m_sbid, m_entry ); m_curType = type; if (m_lbid != m_hdrLbid) rc =readCurBlk(); rc = getNextInfoFromBlk(m_lastIdxRidListPtr); count = m_lastIdxRidListPtr.count; //current count type = m_lastIdxRidListPtr.type; //block type if (type==LIST_BLOCK_TYPE) lbid = ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo; else lbid = INVALID_LBID; return NO_ERROR; break; default: //printf ("FIND FIRST BLOCK got no where, error out !! \n"); break; }; //end switch lbid =INVALID_LBID; return NO_ERROR; } //end function /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::readCurBlk() { int rc = NO_ERROR; CommBlock cb; if (m_lbid == m_hdrLbid) return NO_ERROR; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state != BLK_INIT)) return NO_ERROR; if (m_curBlock.state == BLK_WRITE) rc = writeCurBlk(); if ((m_curBlock.state == BLK_INIT) || (m_curBlock.lbid != m_lbid)) { memset(m_curBlock.data, 0, sizeof(m_curBlock.data ) ); rc = readDBFile(cb, m_curBlock.data, m_lbid); if (rc != NO_ERROR) return rc; m_curBlock.dirty = true; m_curBlock.lbid = m_lbid; m_curBlock.state = BLK_READ; } return rc; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::writeCurBlk() { int rc; CommBlock cb; if (m_curBlock.state == BLK_WRITE) { cb.file.oid = m_oid; cb.file.pFile = m_pFile; rc = writeDBFile(cb, m_curBlock.data, m_curBlock.lbid ); m_curBlock.state =BLK_READ; return rc; } else return NO_ERROR; } /************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateLastPtrAndParent(const int lastCount) { int rc = NO_ERROR; rc = updateLastPtr(lastCount); rc = updateParent(); return rc; } /************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::updateParent() { int rc; if (m_useNarray) { IdxRidParentListPtr parentIdxListPtr; memset(&parentIdxListPtr, 0, sizeof(parentIdxListPtr)); parentIdxListPtr.parentLbid = (uint64_t)INVALID_LBID; rc = getParentInfoFromArray(parentIdxListPtr); m_parentLbid = (uint64_t)parentIdxListPtr.parentLbid; //If this block has no parent, then it is the first block if ((m_parentLbid<= (uint64_t)0)|| (m_parentLbid == (uint64_t)INVALID_LBID)) m_parentLbid = m_lbid; //It is truly itself //The previous lbid m_lbid is full, so we have to go to nextLbid // and register it to the parent block rc= updateParentStatus(m_nextLbid); return rc; } else return NO_ERROR; } /************************************************ * 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; } /************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::addRidInBlk( const RID& newRid) { int maxCount, count=0; int rc = NO_ERROR; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if (m_useNarray) maxCount = MAX_BLK_NARRAY_RID_CNT; else maxCount = MAX_BLK_RID_CNT; //Find the last block that has a space or //No next block linked rc = findLastBlk(count); if ((count ==maxCount) && (m_nextType==LIST_SIZE_TYPE)) {//Full, also need a new segment IdxEmptyListEntry newIdxListEntryPtr; m_segType = LIST_BLOCK_TYPE; rc = getSegment( m_pFile, ENTRY_BLK, &newIdxListEntryPtr); m_nextLbid = ((IdxEmptyListEntry*)&newIdxListEntryPtr)->fbo; m_nextType = m_segType; m_lastIdxRidListPtr.llp=((IdxRidListPtr*)&newIdxListEntryPtr)->llp; rc = updateLastPtrAndParent(count); //the new block for insertion and count record m_lbid = m_nextLbid; m_sbid = 0; m_entry = 0; m_curType = m_nextType; rc = readCurBlk(); //free manager puts bad entry type at the last entry for new block //clean it up! IdxRidListPtr idxRidListPtr; memset(&idxRidListPtr, 0, sizeof(idxRidListPtr)); rc = setNextInfoFromBlk( idxRidListPtr); if (m_useNarray) { rc = initCurBlock(); } //Set the count to the beginning count = 0; }//end if FULL get new segment // insert in the current block at the location if (m_lastLbid != m_lbid) { rc = setLastLbid(m_lbid); } rc = insertRid(newRid, count); rc = updateCurCount(); rc = updateHdrCount(); return rc; } /************************************************ * No Change * RETURN: * success - successfully created the index list header * failure - it did not create the index list header ***********************************************************/ const int IndexList::findLastBlk(int& count) { int maxCount; int rc ; if (m_useNarray) maxCount = MAX_BLK_NARRAY_RID_CNT; else maxCount = MAX_BLK_RID_CNT; rc = readCurBlk(); rc = getNextInfo(count); while ((count == maxCount) &&(m_nextType==LIST_BLOCK_TYPE)) { //current is a Full link, No space to insert, go to the next one m_lbid = m_nextLbid; m_sbid = 0; m_entry =0; rc = readCurBlk(); rc = getNextInfo(count); }//end of while return rc; } /************************************************ * 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::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::getNextInfo(int& count) { int rc; if ((!m_useNarray) ||(m_curType == LIST_SUBBLOCK_TYPE )) { rc = getNextInfoFromBlk(m_lastIdxRidListPtr); count = m_lastIdxRidListPtr.count; m_nextType = m_lastIdxRidListPtr.type; m_nextLbid = ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo; } else { rc = getNextInfoFromArray(m_nextIdxListPtr ); count = m_nextIdxListPtr.count; m_nextType = m_nextIdxListPtr.type; m_nextLbid = m_nextIdxListPtr.nextLbid; } return rc; } /**************************************************************** * DESCRIPTION: * Private Function non-array * ***************************************************************/ const int IndexList::getNextInfoFromBlk( IdxRidListPtr& idxRidListPtr) { int rc = NO_ERROR; int pos = 0; memset(&idxRidListPtr, 0, sizeof(idxRidListPtr)); 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_hdrBlock.lbid == m_lbid) && (m_hdrBlock.state>= BLK_READ)) getSubBlockEntry(m_hdrBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListPtr); else if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state>= BLK_READ)) getSubBlockEntry(m_curBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, &idxRidListPtr); else return ERR_IDX_LIST_WRONG_BLK; if ((idxRidListPtr.type!= 0)&&(idxRidListPtr.type!= 4)&&(idxRidListPtr.type!= 5)) { //cout << "line 1028->m_lbid=" << m_lbid << " m_sbid =" << m_sbid << " m_entry" <idxRidListPtr.type = " << idxRidListPtr.type << endl; memset(&idxRidListPtr, 0, sizeof(idxRidListPtr)); } 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; } }//end namespace