1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-20 09:07:44 +03:00
2023-03-02 15:59:42 +00:00

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