1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
mariadb-columnstore-engine/writeengine/index/we_indexlist_multiple_narray.cpp
2017-10-26 17:18:17 +01:00

666 lines
20 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_multiple.cpp */
/* (c) 2001 Author */
/* */
/* Description */
/* */
/* ========================================================================== */
#include <stdio.h>
#include <string.h>
#ifndef _MSC_VER
#include <inttypes.h>
#endif
#include "we_indexlist.h"
using namespace std;
namespace WriteEngine
{
/****************************************************************
* DESCRIPTION:
* Public Function for adding a header and more than one row id
*
* PARAMETERS:
* input
* pFile - File Handler
* rid - Input row ID
* key - Input key value
* output
* listHdrPtr - Output a pointer to the index list header
* passed back to the caller
* it will containlbid,sbid,entry
* 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* ridList,
const int size, const uint64_t& key,
IdxEmptyListEntry* newEmptyListPtr)
{
int rc;
CommBlock cb;
m_pFile = pFile;
cb.file.oid = m_oid;
cb.file.pFile = m_pFile;
if (size < 1)
return ERR_IDX_LIST_INVALID_ADDHDR;
//cout << "key =" << key << endl;
//Initialize three blokcs
rc = init();
//The same as a single rowid
rc = addIndexListHdr( pFile, ridList[0], key, newEmptyListPtr);
if (size == 1)
{
return rc;
}
//More than one row id
//Set up the header structure
m_hdrLbid = newEmptyListPtr->fbo;
m_hdrSbid = newEmptyListPtr->sbid;
m_hdrEntry = newEmptyListPtr->entry;
rc = updateIndexList(pFile, ridList[1], key, newEmptyListPtr);
if (rc != NO_ERROR)
return rc;
if (size == 2)
return rc;
rc = updateIndexList(pFile, ridList[2], key, newEmptyListPtr);
if (rc != NO_ERROR)
return rc;
if (size == 3)
return rc;
//DONE with the header
//add more row id into the subblock and block
//first segment is a subblock
m_curType = LIST_SUBBLOCK_TYPE ;
m_type = LIST_SUBBLOCK_TYPE ;
int startPos = 3;
rc = getSubBlk();
if (size > 3)
rc = addRidList(ridList, size, startPos);
if (rc != NO_ERROR)
return rc;
rc = updateIndexListWrite();
//rc = getSubBlk();
//cout << "DEBUG INFO====================================="<< endl;
//cout<< " m_oid=" << m_oid << endl;
//cout<< " key= " << key << " header lbid=" << newEmptyListPtr->fbo
// << " header sbid= " << newEmptyListPtr->sbid
// << " header entry= " << newEmptyListPtr->entry <<endl;
return rc;
};
/************************************************************
* Description
* Private Function, Internal use
* For adding a whole subblock or block
* The segment is a clean slate and the lbid has been allocated
* Adding more rowid into the list, first time
* without any delete action preceeding this
* Fill up the subblock 31 entries first
* Then blocks if needed
* input -- ridList - rowid List
* input -- size - total array size
*
************************************************************/
const int IndexList::addRidList(const RID* ridList, const int size,
int& startPos)
{
int remainder = size - startPos ;
int insCnt, maxCount;
bool needNextBlk = false;
int rc = NO_ERROR;
//int count =2;
int count = 0;
CommBlock cb;
cb.file.oid = m_oid;
cb.file.pFile = m_pFile;
IdxEmptyListEntry newEmptyEntry;
rc = getSubBlk(m_lbid, m_sbid, m_entry);
if (rc != NO_ERROR)
return rc;
m_curType = ((IdxEmptyListEntry*)
& (m_curIdxRidListHdr.nextIdxRidListPtr))->type;
maxCount = MAX_SUB_RID_CNT;
m_curLevel = 0;
m_curLevelPos = 0;
m_curBlkPos = 0;
rc = readCurBlk();
//startPos means how many has been inserted
while (startPos < size)
{
rc = getNextInfoFromBlk();
count = m_lastIdxRidListPtr.count;
if (m_useNarray)
m_curLevel = ((IdxRidNextListPtr*)&m_lastIdxRidListPtr)->curLevel;
if (remainder > (maxCount - count))
{
insCnt = maxCount - count;
remainder = remainder - insCnt;
needNextBlk = true;
}
else
{
insCnt = remainder;
remainder = 0;
needNextBlk = false;
}
//Prepare to write the ridList
//write the current subblock or block
for (int i = count; i < (count + insCnt) ; i++)
{
//cout << "startPos->" << startPos << endl;
RID newRID = ridList[startPos];
rc = insertRid(newRID, i);
startPos++;
m_curIdxRidListHdr.idxRidListSize.size++;
m_hdrBlock.state = BLK_WRITE;
}//end for
setSubBlockEntry(m_hdrBlock.data, m_hdrSbid,
m_hdrEntry, LIST_HDR_SIZE,
&m_curIdxRidListHdr );
m_hdrBlock.state = BLK_WRITE;
//write out the last pointer and it depends on how much rid left
if (!needNextBlk)
{
//No more, the end. Just update the current block
//Not read from existing block, so initiate one
if ((m_useNarray) && (m_curType == LIST_BLOCK_TYPE))
rc = updateCurCountInArray(insCnt);
else
{
m_lastIdxRidListPtr.count = count + insCnt;
rc = setNextInfoFromBlk( m_lastIdxRidListPtr);
}
if (m_lastLbid != m_lbid)
rc = setLastLbid(m_lbid);
if (rc != NO_ERROR)
{
return ERR_IDX_LIST_INVALID_ADD_LIST;
}
return rc;//Done
}
else//new link
{
//take care the last entry with the new link
int lastCount = 0;
m_segType = LIST_BLOCK_TYPE;
memset(&newEmptyEntry, 0, sizeof(newEmptyEntry));
rc = getSegment(m_pFile, ENTRY_BLK, &newEmptyEntry);
//handle current block update before move to the new block
lastCount = count + insCnt;
if ((m_curType == LIST_SUBBLOCK_TYPE ) || (!m_useNarray))
{
m_lastIdxRidListPtr.llp = ((IdxRidListHdrPtr*)&newEmptyEntry)->llp;
m_lastIdxRidListPtr.type = LIST_BLOCK_TYPE;
m_lastIdxRidListPtr.spare = 0x0;
m_lastIdxRidListPtr.count = lastCount;
}
m_nextLbid = ((IdxEmptyListEntry*)&newEmptyEntry)->fbo;
m_nextSbid = 0 ;
m_nextEntry = 0 ;
m_nextType = m_segType;
if ((m_curType == LIST_SUBBLOCK_TYPE ) || (!m_useNarray))
{
//when current block is a subblock or single child link
rc = setNextInfoFromBlk( m_lastIdxRidListPtr);
}
else
{
rc = updateLastPtrAndParent(lastCount);
}
//Move on to the new block for insertions
m_lbid = newEmptyEntry.fbo;
m_sbid = 0;
m_entry = 0;
m_curType = m_nextType;
rc = readCurBlk();
//make sure no garbage
IdxRidListPtr idxRidListPtr;
memset(&idxRidListPtr, 0, sizeof(idxRidListPtr));
rc = setNextInfoFromBlk( idxRidListPtr);
if (m_useNarray)
{
maxCount = MAX_BLK_NARRAY_RID_CNT;
rc = initCurBlock();
}
else
maxCount = MAX_BLK_RID_CNT;
count = 0;
} //end else if needs next block
}//end while
return rc;
}
/****************************************************************
* DESCRIPTION:
* (0) THIS FUNCTION CAN ONLY BE CALLED WITH THE PUBLIC
*
* (1) Given a key value and a row ID, update the link list
* Converted
* PARAMETERS:
* Input rid
* --row ID
* Input key
* -- key value
*
* 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* ridList,
const int size, const uint64_t& key,
IdxEmptyListEntry* curIdxRidListHdrPtr)
{
int rc;
CommBlock cb;
m_pFile = pFile;
cb.file.oid = m_oid;
cb.file.pFile = m_pFile;
m_pFile = pFile;
//cout << "key=" << key << endl;
rc = init();
rc = updateIndexList(pFile, ridList[0], key, curIdxRidListHdrPtr);
if (size == 1)
return rc;
rc = updateIndexList(pFile, ridList[1], key, curIdxRidListHdrPtr);
if (size == 2)
return rc;
rc = getHdrInfo(curIdxRidListHdrPtr);
if (rc != NO_ERROR)
{
return rc;
}
if (key != m_curIdxRidListHdr.key)
{
//cout << "line 829->Error Key ->" << key << endl;
//cout << "m_curIdxRidListHdr.key->"<<m_curIdxRidListHdr.key<< endl;
//cout << "m_hdrLbid->" << m_hdrLbid << endl;
//cout << "m_hdrSbid->" << m_hdrSbid << endl;
//cout << "m_hdrEntry->" << m_hdrEntry << endl;
//cout << "m_oid->" << m_oid << endl;
return ERR_IDX_LIST_INVALID_KEY;
}
int startPos = 2;
rc = updateIndexList(ridList, size, startPos);
if (rc != NO_ERROR)
{
return rc;
}
rc = updateIndexListWrite();
if (rc != NO_ERROR)
{
return rc;
}
return rc;
}
/****************************************************************
* DESCRIPTION:
* (0) THIS FUNCTION CAN ONLY BE CALLED WITH THE PUBLIC
*
* (1) Given a key value and a row ID, update the link list
* Converted
* PARAMETERS:
* Input rid
* --row ID
* Input key
* -- key value
*
* RETURN:
* success - successfully created the index list header
* failure - it did not create the index list header
***********************************************************/
const int IndexList::updateIndexList( const RID* ridList, const int size,
int& startPos)
{
IdxEmptyListEntry newEmptyEntry;
int rc = NO_ERROR, width = 8;
int pos = 0, totalbytes = 0, maxCount = 0;
int remainder = size - startPos;
int count = 0;
bool needNextBlk = false;
IdxRidListEntry idxRidListEntry;
int oldType;
CommBlock cb;
cb.file.oid = m_oid;
cb.file.pFile = m_pFile;
if (m_pFile == NULL)
return ERR_IDX_LIST_INVALID_UPDATE;
//Header should be available by now
if (((long long)m_hdrLbid == -1LL) || (m_hdrSbid == -1) || (m_hdrEntry == -1))
return ERR_IDX_LIST_INVALID_UPDATE;
width = LIST_ENTRY_WIDTH;
memset(&m_lastIdxRidListPtr, 0, sizeof(m_lastIdxRidListPtr));
if (m_lastLbid == (uint64_t)INVALID_LBID)
{
rc = getSubBlk(m_lbid, m_sbid, m_entry);
m_curType = ((IdxEmptyListEntry*)
& (m_curIdxRidListHdr.nextIdxRidListPtr))->type;
//First link
pos = LIST_SUB_LLP_POS;
totalbytes = SUBBLOCK_TOTAL_BYTES;
maxCount = MAX_SUB_RID_CNT;
m_segType = LIST_SUBBLOCK_TYPE; //This is for next segment type
m_curType = LIST_SUBBLOCK_TYPE;
}
else
{
m_lbid = m_lastLbid;
m_sbid = 0;
m_entry = 0;
pos = LIST_BLOCK_LLP_POS;
totalbytes = BYTE_PER_BLOCK;
if (m_useNarray)
maxCount = MAX_BLK_NARRAY_RID_CNT;
else
maxCount = MAX_BLK_RID_CNT;
m_curType = LIST_BLOCK_TYPE;
m_segType = LIST_BLOCK_TYPE;
}
while (startPos < size)
{
rc = getNextInfoFromBlk();
count = m_lastIdxRidListPtr.count;
if (m_useNarray)
m_curLevel = ((IdxRidNextListPtr*)&m_lastIdxRidListPtr)->curLevel;
int availCount = maxCount - count;
int insCnt = 0;
m_nextType = m_lastIdxRidListPtr.type;
if (availCount > 0)
{
if (remainder > availCount)
{
insCnt = availCount;
needNextBlk = true;
}
else
{
insCnt = remainder;
needNextBlk = false;
}
for (int i = 0; i < insCnt; i++)
{
idxRidListEntry.type = LIST_RID_TYPE;
idxRidListEntry.spare = 0x0;
idxRidListEntry.rid = ridList[startPos];
startPos++;
remainder--;
m_lastIdxRidListPtr.count++;
availCount--;
if (m_lbid != m_hdrLbid)
{
if ((m_curBlock.state != BLK_INIT) &&
(m_curBlock.lbid == m_lbid))
setSubBlockEntry( m_curBlock.data, m_sbid,
i + count, width, &idxRidListEntry );
else
{
//return ERR_IDX_LIST_INVALID_UPDATE;
rc = readCurBlk();
if (rc != NO_ERROR)
return ERR_IDX_LIST_INVALID_BLK_READ;
setSubBlockEntry( m_curBlock.data, m_sbid,
i + count, width, &idxRidListEntry );
}
m_curBlock.dirty = true;
m_curBlock.state = BLK_WRITE;
}
else
{
setSubBlockEntry( m_hdrBlock.data, m_sbid,
i + count, width, &idxRidListEntry );
m_hdrBlock.dirty = true;
m_hdrBlock.state = BLK_WRITE;
}
m_curIdxRidListHdr.idxRidListSize.size++;
m_hdrBlock.state = BLK_WRITE;
}//end for
setSubBlockEntry(m_hdrBlock.data, m_hdrSbid,
m_hdrEntry, LIST_HDR_SIZE,
&m_curIdxRidListHdr );
m_hdrBlock.state = BLK_WRITE;
}//endif availCount>0
else if (remainder > 0)
{
needNextBlk = true;
}
else if (remainder == 0)
{
needNextBlk = false;
}
if (!needNextBlk)
{
//No more, the end. Just update the current block
if (insCnt > 0)
{
m_lastIdxRidListPtr.count = count + insCnt;
if (m_lbid != m_hdrLbid)
{
if ((m_curBlock.lbid == m_lbid) &&
(m_curBlock.state != BLK_INIT))
setSubBlockEntry(m_curBlock.data, m_sbid, pos, width,
&m_lastIdxRidListPtr );
else
return ERR_IDX_LIST_WRONG_LBID_WRITE;
m_curBlock.state = BLK_WRITE;
}
else
{
setSubBlockEntry( m_hdrBlock.data, m_sbid, pos, width,
&m_lastIdxRidListPtr );
m_hdrBlock.state = BLK_WRITE;
}
if (m_curType == LIST_SUBBLOCK_TYPE)
{
if (m_lastLbid != INVALID_LBID)
{
uint64_t zlbid = INVALID_LBID;
rc = setLastLbid(zlbid);
}
}
else
{
if (m_lastLbid != m_lbid)
rc = setLastLbid(m_lbid);
}
if (rc != NO_ERROR)
{
return ERR_IDX_LIST_INVALID_UPDATE;
}
return rc;//Done
}
else
return NO_ERROR;
}//no new link
else
{
//take care the last entry with the new link
int lastCount = 0;
lastCount = count + insCnt;
m_lastIdxRidListPtr.type = LIST_BLOCK_TYPE;
m_lastIdxRidListPtr.spare = 0x0;
m_lastIdxRidListPtr.count = lastCount;
if (m_nextType != LIST_BLOCK_TYPE)
{
m_segType = LIST_BLOCK_TYPE;
rc = getSegment(m_pFile, ENTRY_BLK, &newEmptyEntry);
if (rc != NO_ERROR)
{
cout << "Indexlist->Free mgr getSegment ERROR CODE rc=" << rc << endl;
return rc;
}
//handle current block update before move to the new
m_lastIdxRidListPtr.llp =
((IdxRidListHdrPtr*)&newEmptyEntry)->llp;
//For Narray
m_nextLbid = ((IdxEmptyListEntry*)&newEmptyEntry)->fbo;
m_nextSbid = 0 ;
m_nextEntry = 0 ;
oldType = m_nextType;
m_nextType = m_segType;
}
else
{
m_nextLbid = ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo;
m_nextSbid = 0 ;
m_nextEntry = 0 ;
oldType = m_nextType;
m_nextType = m_segType;
}
if (m_curType == LIST_SUBBLOCK_TYPE )
{
//when current block is a subblock
if (m_lbid == m_hdrLbid)
{
//header should be read already
setSubBlockEntry( m_hdrBlock.data, m_sbid,
pos, width,
&m_lastIdxRidListPtr );
m_hdrBlock.state = BLK_WRITE;
}
else
{
rc = readCurBlk();
setSubBlockEntry( m_curBlock.data, m_sbid,
pos, width,
&m_lastIdxRidListPtr );
m_curBlock.state = BLK_WRITE;
}
}
else
{
if (m_useNarray)
rc = updateLastPtrAndParent(lastCount);
else
rc = updateLastPtr(lastCount);
}
writeCurBlk();
m_lbid = m_nextLbid;
m_sbid = 0;
m_entry = 0;
//m_lastLbid = m_lbid;
m_curType = m_nextType;
pos = LIST_BLOCK_LLP_POS;
totalbytes = BYTE_PER_BLOCK;
rc = readCurBlk();
if (m_useNarray)
{
maxCount = MAX_BLK_NARRAY_RID_CNT;
if (oldType != LIST_BLOCK_TYPE)
rc = initCurBlock();
}
else
maxCount = MAX_BLK_RID_CNT;
} //end else if needs next block
}//end while
return rc;
}
}//end namespace