/* 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. */ /* ========================================================================== */ /* */ /* we_indexlist_narray.cpp */ /* */ /* */ /* Description */ /* */ /* ========================================================================== */ #include //#include #include #include #include #include "we_indextree.h" #include "we_indexlist.h" using namespace std; namespace WriteEngine { /**************************************************************** * DESCRIPTION: * Private Function for print the block trees * ***************************************************************/ const int IndexList::printBlocks(uint64_t& lbid) { int rc; IdxRidListArrayPtr idxRidListArrayPtr; int curLevel = 0, curCount = 0; memset(&idxRidListArrayPtr, 0, sizeof(idxRidListArrayPtr)); m_lbid = lbid; rc = readCurBlk(); getSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS, LIST_BLK_LLP_ENTRY_WIDTH, &idxRidListArrayPtr); curLevel = idxRidListArrayPtr.nextIdxListPtr.curLevel; curCount = idxRidListArrayPtr.nextIdxListPtr.count; for (int i = 0; i < curLevel; i++) { cout << " "; } cout << " Lbid->" << lbid << " curLevel->" << curLevel << " curCount->" << curCount << endl; for (int i = 0; i < TOTAL_NUM_ARRAY_PTR; i++) { uint64_t lbid; lbid = idxRidListArrayPtr.childIdxRidListPtr[i].childLbid; if (lbid != (uint64_t)INVALID_LBID) printBlocks(lbid); } return rc; } /**************************************************************** * DESCRIPTION: * Private Function for getting the last Fbo on header * ***************************************************************/ const int IndexList::setCurBlkNextPtr(uint64_t& nextLbid, int count) { int rc; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if (nextLbid == (uint64_t)INVALID_LBID) return ERR_IDX_LIST_SET_NEXT_LBID; m_idxRidListArrayPtr.nextIdxListPtr.type = (int)LIST_BLOCK_TYPE; m_idxRidListArrayPtr.nextIdxListPtr.curLevel = m_curLevel; m_idxRidListArrayPtr.nextIdxListPtr.count = count; m_idxRidListArrayPtr.nextIdxListPtr.nextLbid = nextLbid; m_idxRidListArrayPtr.nextIdxListPtr.spare = 0; if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state >= BLK_READ)) { rc = writeSubBlockEntry(cb, &m_curBlock, m_lbid, 0, BEGIN_LIST_BLK_LLP_POS + NEXT_BLK_PTR_OFFSET, LIST_ENTRY_WIDTH, &m_idxRidListArrayPtr.nextIdxListPtr); m_curBlock.state = BLK_READ; if (rc != NO_ERROR) return rc; } else return ERR_IDX_LIST_SET_NEXT_LBID; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::initCurBlock() { if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state >= BLK_READ)) { memset(&m_idxRidListArrayPtr, 0, sizeof(m_idxRidListArrayPtr)); for (int i = 0; i < TOTAL_NUM_ARRAY_PTR; i++) { m_idxRidListArrayPtr.childIdxRidListPtr[i].type = LIST_NOT_USED_TYPE; m_idxRidListArrayPtr.childIdxRidListPtr[i].llpStat = LLP_NOT_FULL; m_idxRidListArrayPtr.childIdxRidListPtr[i].spare = 0; m_idxRidListArrayPtr.childIdxRidListPtr[i].childLbid = INVALID_LBID; } m_idxRidListArrayPtr.nextIdxListPtr.type = LIST_SIZE_TYPE; m_idxRidListArrayPtr.nextIdxListPtr.spare = 0; m_idxRidListArrayPtr.nextIdxListPtr.curLevel = m_curLevel; m_idxRidListArrayPtr.nextIdxListPtr.count = 0; m_idxRidListArrayPtr.nextIdxListPtr.nextLbid = INVALID_LBID; m_idxRidListArrayPtr.parentIdxListPtr.type = LIST_LLP_TYPE; m_idxRidListArrayPtr.parentIdxListPtr.spare = 0; m_idxRidListArrayPtr.parentIdxListPtr.curLevelPos = m_curLevelPos; m_idxRidListArrayPtr.parentIdxListPtr.curBlkPos = m_curBlkPos; m_idxRidListArrayPtr.parentIdxListPtr.parentLbid = m_parentLbid; setSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS, LIST_BLK_LLP_ENTRY_WIDTH, &m_idxRidListArrayPtr); } else return ERR_IDX_LIST_INIT_LINK_BLKS; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::getNextInfoFromArray(IdxRidNextListPtr& nextIdxListPtr) { if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state >= BLK_READ)) getSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + NEXT_BLK_PTR_OFFSET, LIST_ENTRY_WIDTH, &nextIdxListPtr); else return ERR_IDX_LIST_GET_NEXT; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::getParentInfoFromArray(IdxRidParentListPtr& parentIdxListPtr) { int rc; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state >= BLK_READ)) getSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + PARENT_PTR_OFFSET, LIST_ENTRY_WIDTH, &parentIdxListPtr); else return ERR_IDX_LIST_GET_PARENT; m_curLevelPos = parentIdxListPtr.curLevelPos; m_curBlkPos = parentIdxListPtr.curBlkPos; m_parentLbid = parentIdxListPtr.parentLbid; if (m_parentLbid == (uint64_t)INVALID_LBID) return NO_ERROR; memset(m_parentBlock.data, 0, sizeof(m_parentBlock.data)); rc = readDBFile(cb, &m_parentBlock, m_parentLbid); m_parentBlock.lbid = m_parentLbid; m_parentBlock.state = BLK_READ; m_parentBlock.dirty = true; return NO_ERROR; } /**************************************************************** * DESCRIPTION: * Private Function for setting the last Fbo on header * ***************************************************************/ const int IndexList::updateCurCountInArray(int insCnt) { int rc = NO_ERROR; IdxRidNextListPtr nextIdxListPtr; memset(&nextIdxListPtr, 0, sizeof(IdxRidNextListPtr)); if ((m_curBlock.lbid == m_lbid) && (m_curBlock.state >= BLK_READ)) { getSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + NEXT_BLK_PTR_OFFSET, LIST_ENTRY_WIDTH, &nextIdxListPtr); nextIdxListPtr.count = nextIdxListPtr.count + insCnt; setSubBlockEntry(m_curBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + NEXT_BLK_PTR_OFFSET, LIST_ENTRY_WIDTH, &nextIdxListPtr); m_curBlock.state = BLK_WRITE; } else return ERR_IDX_LIST_GET_COUNT; return rc; } /**************************************************************** * DESCRIPTION: * childLbid is the new child block and need to register it in * the correct parent and assigned level * Private Function for getting the header * ***************************************************************/ const int IndexList::updateParentStatus(uint64_t& childLbid) { int rc; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; IdxRidListArrayPtr idxRidListArrayPtr; // Get the parent block read out or get the 4 children pointers out if ((m_parentBlock.state == BLK_INIT) || (m_parentBlock.lbid != m_parentLbid)) { rc = readSubBlockEntry(cb, &m_parentBlock, m_parentLbid, 0, BEGIN_LIST_BLK_LLP_POS, LIST_BLK_LLP_ENTRY_WIDTH, &idxRidListArrayPtr); m_parentBlock.dirty = true; m_parentBlock.state = BLK_READ; m_parentBlock.lbid = m_parentLbid; } else getSubBlockEntry(m_parentBlock.data, 0, BEGIN_LIST_BLK_LLP_POS, LIST_BLK_LLP_ENTRY_WIDTH, &idxRidListArrayPtr); // update current Child Block to full // The reason to update parent is becuse CURRENT child link is full // The CURRENT child lbid is m_lbid, m_curBlkPos is where it was registered if (m_lbid != m_parentLbid) // The fulled child is not the parent itself { // normal case found the child block is full and set it full if (idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].type == (int)LIST_BLOCK_TYPE) idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].llpStat = LLP_FULL; // else if ((m_curBlkPos==0) && (m_flag)) //Next level parent, a new parent, no child else if (m_curBlkPos == 0) // get here only when a brand new parent given, // it went up one level and the go back down to the same level, { if (!m_flag) // it is NOT the first block, this flag is useless, cannot be FALSE! return ERR_IDX_LIST_WRONG_TYPE; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].type = LIST_BLOCK_TYPE; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].llpStat = LLP_NOT_FULL; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].spare = 0; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].childLbid = childLbid; setSubBlockEntry(m_parentBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + m_curBlkPos, LIST_ENTRY_WIDTH, &idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos]); rc = writeDBFile(cb, m_parentBlock.data, m_parentLbid); m_parentBlock.state = BLK_READ; m_curLevelPos++; return rc; } else // m_flag cannot be false since it is not the first block return ERR_IDX_LIST_WRONG_TYPE; } else // This is the first block-> the current block's parent is itself { // only done once when first block was full m_curBlkPos = 0; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].type = (int)LIST_BLOCK_TYPE; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].llpStat = LLP_FULL; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].spare = 0; idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos].childLbid = childLbid; setSubBlockEntry(m_parentBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + m_curBlkPos, LIST_ENTRY_WIDTH, &idxRidListArrayPtr.childIdxRidListPtr[m_curBlkPos]); rc = writeDBFile(cb, m_parentBlock.data, m_parentLbid); m_parentBlock.state = BLK_READ; m_curLevel = 1; m_curLevelPos = 0; return rc; } int i; for (i = 0; i < TOTAL_NUM_ARRAY_PTR; i++) { if (idxRidListArrayPtr.childIdxRidListPtr[i].type != (int)LIST_BLOCK_TYPE) { idxRidListArrayPtr.childIdxRidListPtr[i].type = LIST_BLOCK_TYPE; idxRidListArrayPtr.childIdxRidListPtr[i].llpStat = LLP_NOT_FULL; idxRidListArrayPtr.childIdxRidListPtr[i].spare = 0; idxRidListArrayPtr.childIdxRidListPtr[i].childLbid = childLbid; setSubBlockEntry(m_parentBlock.data, 0, BEGIN_LIST_BLK_LLP_POS + i, LIST_ENTRY_WIDTH, &idxRidListArrayPtr.childIdxRidListPtr[i]); rc = writeDBFile(cb, m_parentBlock.data, m_parentLbid); m_parentBlock.state = BLK_READ; m_curBlkPos = i; // Need to figure out this where to put it m_curLevelPos++; return rc; } } // Parent is full and all children are full Not found any child pointer is available to add // then go to sibling in the same level or down // Need to look for the next block on parent block, on level down // The level will be increment by 1 HERE // Change parent lbid go to next link if (m_curLevelPos == (pow(4.0, m_curLevel) - 1)) // if the last node of this level { m_curLevel++; m_curLevelPos = -1; } m_flag = true; // this need to go // A new parent m_curBlkPos = 0; m_parentLbid = idxRidListArrayPtr.nextIdxListPtr.nextLbid; memset(m_parentBlock.data, 0, sizeof(m_parentBlock.data)); m_parentBlock.state = BLK_INIT; m_parentBlock.dirty = false; rc = updateParentStatus(childLbid); return rc; } } // namespace WriteEngine