/* 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 #include #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; } } // namespace WriteEngine