/* 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_indextree.h" #include "we_indexlist.h" using namespace std; namespace WriteEngine { /************************************************ * 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; icount--; 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; } /************************************************ * 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::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; icount--; 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_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: * Converted * Find an 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 * 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::deleteIndexList( FILE* pFile, const RID& rowId, const uint64_t& key, IdxEmptyListEntry* curIdxRidListHdrPtr, uint64_t& lbid, int&sbid, int& entry) { int rc =ERR_IDX_LIST_INVALID_DELETE; bool found = false; m_pFile = pFile; getHdrInfo(curIdxRidListHdrPtr); if (key!= m_curIdxRidListHdr.key) { return ERR_IDX_LIST_INVALID_KEY; } uint64_t dlbid =-1LL; int dsbid = -1; int dentry = -1; rc = deleteIndexList(rowId,key,dlbid,dsbid,dentry); if (rc!=NO_ERROR) { lbid=-1LL; sbid =-1; entry=-1; found = false; return rc; } else { lbid = dlbid; sbid = dsbid; entry = dentry; } return rc; } /************************************************ * Description: * No change * 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 * 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::deleteIndexList(const RID& rowId, const uint64_t& key, uint64_t& lbid, int&sbid, int& entry) { int rc =ERR_IDX_LIST_INVALID_DELETE; rc = deleteIndexList(rowId,key); lbid = m_dLbid; sbid = m_dSbid; entry = m_dEntry; return rc; } /************************************************ * Description: * Converted * Find all of the row Id or toke from list * input * pFile -- File Handler * curIdxRidListHdrPtr - point to the header * * return value * Success -- 0 * Fail -- ERR_IDX_LIST_INVALID_DELETE ************************************************/ const int IndexList::getRIDArrayFromListHdr(FILE* pFile, uint64_t& key, IdxEmptyListEntry* curIdxRidListHdrPtr, RID* ridArray, int& size) { int rc=NO_ERROR; int arrayCount = 0; IdxRidNextListPtr *nextIdxListPtr = NULL; m_pFile = pFile; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; rc = getHdrInfo(curIdxRidListHdrPtr); if (m_curIdxRidListHdr.idxRidListSize.size==0) {size =0; return NO_ERROR;} if (key!= m_curIdxRidListHdr.key) { return ERR_IDX_LIST_WRONG_KEY; } // cout << "IndexList::getRIDArrayFromListHdr->KEY ------>" << key << endl; //Check the first row location, 3rd enty if (m_curIdxRidListHdr.firstIdxRidListEntry.type==(int)LIST_RID_TYPE) { ridArray[arrayCount]= (RID)m_curIdxRidListHdr.firstIdxRidListEntry.rid; //cout<<" IndexList::getRIDArrayFromListHdr->header Lbid->" << m_hdrLbid <<" count->" << arrayCount <" << arrayCount << "rid->" << ridArray[arrayCount]<" << count << endl; //type should be LIST_BLOCK_TYPE from now on for (int i=0; i" << arrayCount << "rid->" << ridArray[arrayCount]<" << m_lbid ; //cout << " count->" << count << endl; m_lbid = ((IdxEmptyListEntry*)lastIdxRidListPtr)->fbo; while (type ==LIST_BLOCK_TYPE) { //cout << " Lbid->" << m_lbid ; pos = LIST_BLOCK_LLP_POS; totalbytes = BYTE_PER_BLOCK; rc = readSubBlockEntry(cb, &m_curBlock, m_lbid, 0 , 0, totalbytes, rowIdArray); m_curBlock.lbid = m_lbid; m_curBlock.state = BLK_READ; m_curBlock.dirty = true; if (!m_useNarray) { lastIdxRidListPtr =(IdxRidListPtr *) &rowIdArray[pos]; type = lastIdxRidListPtr->type; count = lastIdxRidListPtr->count; } else { nextIdxListPtr = (IdxRidNextListPtr *)&rowIdArray[pos]; type = nextIdxListPtr->type; count = nextIdxListPtr->count; } //cout << " count->" << count << endl; for (int i=0; i" << arrayCount << "rid->" << ridArray[arrayCount]<nextLbid; else m_lbid = ((IdxEmptyListEntry*)lastIdxRidListPtr)->fbo; } }//end while };//end of switch size = arrayCount; return rc; }//end getRIDArrayFromListHdr const int IndexList::getRIDArrayFromListHdrNarray(FILE* pFile, uint64_t& key, IdxEmptyListEntry* curIdxRidListHdrPtr, RID* ridArray, int& size, bool flag) { int rc=NO_ERROR; IdxRidNextListPtr *nextIdxListPtr; int pos =0, totalbytes=0; IdxRidListPtr *lastIdxRidListPtr; IdxRidListEntry rowIdArray[MAX_BLOCK_ENTRY*10]; int type=0, count=0; m_pFile = pFile; CommBlock cb; cb.file.oid = m_oid; cb.file.pFile = m_pFile; if (flag) { rc = getHdrInfo(curIdxRidListHdrPtr); if (m_curIdxRidListHdr.idxRidListSize.size==0) {size =0; return NO_ERROR;} if (key!= m_curIdxRidListHdr.key) { return ERR_IDX_LIST_WRONG_KEY; } // cout << "IndexList::getRIDArrayFromListHdr->KEY ------>" << key << endl; //Check the first row location, 3rd enty if (m_curIdxRidListHdr.firstIdxRidListEntry.type==(int)LIST_RID_TYPE) { ridArray[size]= (RID)m_curIdxRidListHdr.firstIdxRidListEntry.rid; //cout<<" IndexList::getRIDArrayFromListHdr->header Lbid->" << m_hdrLbid <<" count->" << arrayCount <" << arrayCount << "rid->" << ridArray[arrayCount]<" << count << endl; //type should be LIST_BLOCK_TYPE from now on for (int i=0; i" << arrayCount << "rid->" << ridArray[arrayCount]<" << m_lbid ; //cout << " count->" << count << endl; m_lbid = ((IdxEmptyListEntry*)lastIdxRidListPtr)->fbo; m_curType = type; }//end of switch }//end if flag if (m_curType ==LIST_BLOCK_TYPE) { pos = LIST_BLOCK_LLP_POS; totalbytes = BYTE_PER_BLOCK; rc = readSubBlockEntry(cb, &m_curBlock, m_lbid, 0 , 0, totalbytes, rowIdArray); m_curBlock.lbid = m_lbid; m_curBlock.state = BLK_READ; m_curBlock.dirty = true; nextIdxListPtr = (IdxRidNextListPtr *)&rowIdArray[pos]; type = nextIdxListPtr->type; count = nextIdxListPtr->count; for (int i=0; ifbo; m_sbid =((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->sbid; m_entry=((IdxEmptyListEntry*) &(m_curIdxRidListHdr.nextIdxRidListPtr))->entry; //Read the pointer entry at LIST_SUB_LLP_POS //reserve enough space for rowIdArray IdxRidListPtr *lastIdxRidListPtr; IdxRidListEntry rowIdArray[MAX_BLOCK_ENTRY]; memset(rowIdArray, 0, BYTE_PER_BLOCK); //first link pos = LIST_SUB_LLP_POS; totalbytes = SUBBLOCK_TOTAL_BYTES; //check if the sub block is on the header block if (m_lbid != m_hdrLbid) { rc = readSubBlockEntry( cb, &m_curBlock, m_lbid, m_sbid, 0, totalbytes, rowIdArray); m_curBlock.dirty = true; m_curBlock.state = BLK_READ; } else { getSubBlockEntry(m_hdrBlock.data, m_sbid, 0, totalbytes, rowIdArray ); } lastIdxRidListPtr =(IdxRidListPtr *) &rowIdArray[pos]; prevLbid = m_lbid; //sub block prevType = type; //sub block count = lastIdxRidListPtr->count; //current count type = lastIdxRidListPtr->type; //block found = false; //look inside the first sub block for (int i=0; ifbo; m_sbid = 0; m_entry = 0; pos = LIST_BLOCK_LLP_POS; totalbytes = BYTE_PER_BLOCK; if ((m_lbid !=m_hdrLbid) && (m_lbid != prevLbid)) { // the only case for block rc = readSubBlockEntry( cb, &m_curBlock, m_lbid, m_sbid, 0, totalbytes, rowIdArray); m_curBlock.dirty=true; } else { printf("error in findRowID\n"); return false; } prevType = type; lastIdxRidListPtr=(IdxRidListPtr *) &rowIdArray[pos]; type = lastIdxRidListPtr->type; count = lastIdxRidListPtr->count; found = false; for (int i=0; i