You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* 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.cpp                                                               */
 | |
| /*   (c) 2001 Author                                                          */
 | |
| /*                                                                            */
 | |
| /*   Description                                                              */
 | |
| /*                                                                            */
 | |
| /* ========================================================================== */
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <inttypes.h>
 | |
| #include "we_indexlist.h"
 | |
| using namespace std;
 | |
| 
 | |
| namespace WriteEngine
 | |
| {
 | |
| /**
 | |
|  * Constructor
 | |
|  */
 | |
| IndexList::IndexList()
 | |
|  : m_oid((OID)INVALID_NUM)
 | |
|  , m_useNarray(true)
 | |
|  , m_curLevel(INVALID_NUM)
 | |
|  , m_curBlkPos(0)
 | |
|  , m_curLevelPos(INVALID_NUM)
 | |
| 
 | |
| {
 | |
|   m_freemgr.setDebugLevel(DEBUG_0);
 | |
|   init();
 | |
| };
 | |
| /****************************************************************
 | |
|  * DESCRIPTION:
 | |
|  * Public Function for adding a header
 | |
|  * (1) Given a key value and a row ID,
 | |
|  * (2) Return a pointer for insertion into the correct position
 | |
|  *     in the Index Tree List Pointer group
 | |
|  * (3) A return code should indicate success or failur
 | |
|  * PARAMETERS:
 | |
|  *    input
 | |
|  *        pFile      - File Handler
 | |
|  *        rid        - Input row ID
 | |
|  *        key        - Input key value
 | |
|  *    output
 | |
|  *        listHdrPtr - Output a pointer to the index list header
 | |
|  * RETURN:
 | |
|  *    success    - successfully created the index list header
 | |
|  *    failure    - it did not create the index list header
 | |
|  *
 | |
|  *******************************************************************/
 | |
| const int IndexList::addIndexListHdr(FILE* pFile, const RID& rowId, const uint64_t& key,
 | |
|                                      IdxEmptyListEntry* newEmptyListPtr)
 | |
| {
 | |
|   int rc;
 | |
|   CommBlock cb;
 | |
|   m_pFile = pFile;
 | |
|   cb.file.oid = m_oid;
 | |
|   cb.file.pFile = m_pFile;
 | |
|   // Set up the header structure
 | |
|   // Initialize header blokcs
 | |
|   rc = resetBlk(&m_hdrBlock);
 | |
|   m_hdrLbid = INVALID_LBID;
 | |
|   m_hdrSbid = INVALID_NUM;
 | |
|   m_hdrEntry = INVALID_NUM;
 | |
| 
 | |
|   // Initialize the new Index List header to null
 | |
|   memset(&m_curIdxRidListHdr, 0, LIST_HDR_SIZE);
 | |
|   // Assign the bit fields for the first entry in the Index List Header
 | |
|   m_curIdxRidListHdr.idxRidListSize.type = LIST_SIZE_TYPE;
 | |
|   m_curIdxRidListHdr.idxRidListSize.spare = 0x0;
 | |
|   m_curIdxRidListHdr.idxRidListSize.size = 1;
 | |
|   // Assign the bit fields for the second entry of the Index List Header
 | |
|   m_curIdxRidListHdr.key = key;
 | |
|   // Assign bit fields for the third entry of the Index List Header
 | |
|   m_curIdxRidListHdr.firstIdxRidListEntry.type = LIST_RID_TYPE;
 | |
|   m_curIdxRidListHdr.firstIdxRidListEntry.spare = 0x0;
 | |
|   m_curIdxRidListHdr.firstIdxRidListEntry.rid = rowId;
 | |
|   // Assign bit fields for the fourth entry of the Index List Header
 | |
|   m_curIdxRidListHdr.nextIdxRidListPtr.type = LIST_NOT_USED_TYPE;
 | |
|   m_curIdxRidListHdr.nextIdxRidListPtr.spare = 0x0;
 | |
|   m_curIdxRidListHdr.nextIdxRidListPtr.llp = 0x0;
 | |
|   /* Get assigned space for the header from free manager
 | |
|    * Get the new block for the new idx list header
 | |
|    * The header needs LIST_HDR_SIZE bytes
 | |
|    */
 | |
|   rc = getSegment(pFile, ENTRY_4, newEmptyListPtr);
 | |
| 
 | |
|   if (rc != NO_ERROR)
 | |
|     return rc;
 | |
| 
 | |
|   m_hdrLbid = newEmptyListPtr->fbo;
 | |
|   m_hdrSbid = newEmptyListPtr->sbid;
 | |
|   m_hdrEntry = newEmptyListPtr->entry;
 | |
| 
 | |
|   // Write Index List Header to the file block
 | |
|   // Write LIST_HDR_SIZE bytes in one time.
 | |
| 
 | |
|   rc = readDBFile(cb, m_hdrBlock.data, m_hdrLbid);
 | |
|   rc = writeSubBlockEntry(cb, &m_hdrBlock, m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE,
 | |
|                           &m_curIdxRidListHdr);
 | |
| 
 | |
|   if (rc != NO_ERROR)
 | |
|   {
 | |
|     return rc;
 | |
|   }
 | |
| 
 | |
|   // Wrote Header Block Out already, Start Over next time
 | |
|   // Update the flags to indicate there is data on the header block
 | |
|   m_hdrBlock.dirty = true;
 | |
|   m_hdrBlock.lbid = m_hdrLbid;
 | |
|   m_hdrBlock.state = BLK_READ;
 | |
|   m_lastLbid = INVALID_LBID;
 | |
|   // DONE
 | |
|   return rc;
 | |
| };
 | |
| /****************************************************************
 | |
|  * DESCRIPTION:
 | |
|  *
 | |
|  *
 | |
|  * RETURN:
 | |
|  *    success    - successfully created the index list header
 | |
|  *    failure    - it did not create the index list header
 | |
|  ***********************************************************/
 | |
| const int IndexList::updateIndexList(FILE* pFile, const RID& newRid, const uint64_t& key,
 | |
|                                      IdxEmptyListEntry* curIdxRidListHdrPtr)
 | |
| {
 | |
|   int rc;
 | |
|   m_pFile = pFile;
 | |
| 
 | |
|   // Initialization
 | |
|   if ((key != m_curIdxRidListHdr.key) || (m_hdrBlock.state == BLK_INIT))
 | |
|   {
 | |
|     rc = initGetHdr(key, curIdxRidListHdrPtr);
 | |
| 
 | |
|     if (key != m_curIdxRidListHdr.key)
 | |
|       return ERR_IDX_LIST_INVALID_KEY;
 | |
|   }
 | |
| 
 | |
|   rc = updateIndexList(newRid, key);
 | |
| 
 | |
|   if (rc != NO_ERROR)
 | |
|   {
 | |
|     return rc;
 | |
|   }
 | |
| 
 | |
|   // Write everything out
 | |
|   rc = updateIndexListWrite();
 | |
|   return rc;
 | |
| };
 | |
| /****************************************************************
 | |
|  * DESCRIPTION:
 | |
|  * (0) THIS FUNCIION CAN ONLY BE CALLED WITH THE PUBLIC
 | |
|  *
 | |
|  * RETURN:
 | |
|  *    success    - successfully created the index list header
 | |
|  *    failure    - it did not create the index list header
 | |
|  ***********************************************************/
 | |
| const int IndexList::updateIndexList(const RID& newRid, const uint64_t& key)
 | |
| {
 | |
|   int rc = NO_ERROR;
 | |
| 
 | |
|   // m_lastLbid==0 or not determines if we can skip from the header,the first
 | |
|   // subblock or go to the last inserted block
 | |
|   if (m_lastLbid == (uint64_t)INVALID_LBID)
 | |
|   {
 | |
|     rc = updateHdrSub(newRid, key);
 | |
|   }
 | |
|   else  // get the lastLbid info from header
 | |
|   {
 | |
|     // m_lastLbid > 0, space is in some block now
 | |
|     m_lbid = m_lastLbid;
 | |
|     m_sbid = 0;
 | |
|     m_entry = 0;
 | |
|     m_segType = LIST_BLOCK_TYPE;
 | |
|     m_curType = LIST_BLOCK_TYPE;
 | |
|     rc = addRidInBlk(newRid);
 | |
|   }
 | |
| 
 | |
|   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::deleteIndexList(FILE* pFile, const RID& rowId, const uint64_t& key,
 | |
|                                      IdxEmptyListEntry* curIdxRidListHdrPtr)
 | |
| {
 | |
|   int rc = ERR_IDX_LIST_INVALID_DELETE;
 | |
|   m_pFile = pFile;
 | |
| 
 | |
|   getHdrInfo(curIdxRidListHdrPtr);
 | |
| 
 | |
|   if (key != m_curIdxRidListHdr.key)
 | |
|   {
 | |
|     memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
 | |
|     m_hdrBlock.dirty = false;
 | |
|     m_hdrBlock.state = BLK_INIT;
 | |
|     return ERR_IDX_LIST_INVALID_KEY;
 | |
|   }
 | |
| 
 | |
|   rc = deleteIndexList(rowId, key);
 | |
|   return rc;
 | |
| }
 | |
| 
 | |
| /************************************************
 | |
|  * Description:
 | |
|  * Converted - keep the first sub block
 | |
|  * 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)
 | |
| {
 | |
|   int rc = ERR_IDX_LIST_INVALID_DELETE;
 | |
|   RID savedRid;
 | |
|   DataBlock prevDataBlock;
 | |
| 
 | |
|   CommBlock cb;
 | |
|   cb.file.oid = m_oid;
 | |
|   cb.file.pFile = m_pFile;
 | |
| 
 | |
|   // Check the first row location, 3rd entry
 | |
|   // Because it may be deleted from the delete action
 | |
|   // The header size cannot tell us the rowid size on header
 | |
|   if (m_curIdxRidListHdr.firstIdxRidListEntry.type == (int)LIST_RID_TYPE)
 | |
|   {
 | |
|     if (m_curIdxRidListHdr.firstIdxRidListEntry.rid == rowId)
 | |
|     {
 | |
|       m_curIdxRidListHdr.firstIdxRidListEntry.type = LIST_NOT_USED_TYPE;  // not used type
 | |
|       m_curIdxRidListHdr.firstIdxRidListEntry.rid = 0;
 | |
|       m_curIdxRidListHdr.idxRidListSize.size--;
 | |
|       rc = writeSubBlockEntry(cb, &m_hdrBlock, m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE,
 | |
|                               &m_curIdxRidListHdr);
 | |
|       memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
 | |
|       m_hdrBlock.dirty = false;
 | |
|       m_dLbid = m_hdrLbid;
 | |
|       m_dSbid = m_hdrSbid;
 | |
|       m_dEntry = m_hdrEntry + 2;
 | |
| 
 | |
|       return rc;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   // Check Header last entry's type
 | |
|   int type = m_curIdxRidListHdr.nextIdxRidListPtr.type;
 | |
| 
 | |
|   switch (type)
 | |
|   {
 | |
|     case LIST_NOT_USED_TYPE:  // Header is not full, no sub-block linked
 | |
|       // No RowId here
 | |
|       memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
 | |
|       m_hdrBlock.dirty = false;
 | |
|       m_dLbid = -1LL;
 | |
|       m_dSbid = -1;
 | |
|       m_dEntry = -1;
 | |
|       return ERR_IDX_LIST_INVALID_DELETE;  // not found, failed
 | |
| 
 | |
|     case LIST_RID_TYPE:  // There is a row id here, Check!
 | |
|       savedRid = m_curIdxRidListHdr.nextIdxRidListPtr.llp;
 | |
| 
 | |
|       if (savedRid == rowId)
 | |
|       {
 | |
|         m_curIdxRidListHdr.nextIdxRidListPtr.type = LIST_NOT_USED_TYPE;
 | |
|         m_curIdxRidListHdr.nextIdxRidListPtr.llp = 0;
 | |
|         m_curIdxRidListHdr.idxRidListSize.size--;
 | |
|         rc = writeSubBlockEntry(cb, &m_hdrBlock, m_hdrLbid, m_hdrSbid, m_hdrEntry, LIST_HDR_SIZE,
 | |
|                                 &m_curIdxRidListHdr);
 | |
|         m_hdrBlock.dirty = false;
 | |
|         memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
 | |
|         m_dLbid = m_hdrLbid;
 | |
|         m_dSbid = m_hdrSbid;
 | |
|         m_dEntry = 3;
 | |
| 
 | |
|         return rc;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         m_hdrBlock.dirty = false;
 | |
|         memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
 | |
|         m_dLbid = -1LL;
 | |
|         m_dSbid = -1;
 | |
|         m_dEntry = -1;
 | |
|         return ERR_IDX_LIST_INVALID_DELETE;
 | |
|       }
 | |
| 
 | |
|     case LIST_SUBBLOCK_TYPE:  // Not found in header,
 | |
|       rc = deleteInSub(rowId);
 | |
| 
 | |
|       if (rc == NO_ERROR)
 | |
|         return rc;
 | |
| 
 | |
|       rc = deleteInBlock(rowId);
 | |
|       return rc;
 | |
|       break;
 | |
| 
 | |
|     default: break;
 | |
|   };  // end of switch
 | |
| 
 | |
|   return ERR_IDX_LIST_INVALID_DELETE;
 | |
| }
 | |
| }  // namespace WriteEngine
 |