You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			1260 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1260 lines
		
	
	
		
			42 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. */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string>
 | 
						|
#include <stdexcept>
 | 
						|
using namespace std;
 | 
						|
 | 
						|
#include <boost/scoped_ptr.hpp>
 | 
						|
using namespace boost;
 | 
						|
 | 
						|
#include <cppunit/extensions/HelperMacros.h>
 | 
						|
 | 
						|
#include "we_indextree.h"
 | 
						|
#include "we_freemgr.h"
 | 
						|
#include "we_indexlist.h"
 | 
						|
 | 
						|
 | 
						|
using namespace WriteEngine;
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    IdxRidListHdr	hdrRec;
 | 
						|
    IdxRidListPtr	listPtr;
 | 
						|
    int				fbo;
 | 
						|
    int				sbid;
 | 
						|
    int				entry;
 | 
						|
    int				sbSeqNo;
 | 
						|
    int				recCnt;
 | 
						|
    int				sbCnt;
 | 
						|
    int				fullSbCnt;
 | 
						|
} IdxListStat;
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    int				mapSize;
 | 
						|
    int				entryCnt;
 | 
						|
} IdxFreeSpaceStat;
 | 
						|
 | 
						|
const int		QA_FILE_TYPE_TREE         = 1;
 | 
						|
const int		QA_FILE_TYPE_LIST         = 2;
 | 
						|
 | 
						|
const int		QA_FREEMAP_1ENTRY         = 1;
 | 
						|
const int		QA_FREEMAP_2ENTRY         = 2;
 | 
						|
const int		QA_FREEMAP_4ENTRY         = 3;
 | 
						|
const int		QA_FREEMAP_8ENTRY         = 4;
 | 
						|
const int		QA_FREEMAP_16ENTRY        = 5;
 | 
						|
const int		QA_FREEMAP_32ENTRY        = 6;
 | 
						|
 | 
						|
 | 
						|
class IndexTest : public CppUnit::TestFixture
 | 
						|
{
 | 
						|
 | 
						|
    CPPUNIT_TEST_SUITE( IndexTest );
 | 
						|
 | 
						|
    /* ====================================================
 | 
						|
       Index stress test
 | 
						|
       These tests will create the maxium number:
 | 
						|
       1) index key records, one row ID for each
 | 
						|
       2) row IDs for an index key
 | 
						|
    ======================================================= */
 | 
						|
 | 
						|
//CPPUNIT_TEST( testCreateIndex );
 | 
						|
 | 
						|
 | 
						|
    /* ====================================================
 | 
						|
       TTest Suites
 | 
						|
       ======================================================= */
 | 
						|
 | 
						|
    CPPUNIT_TEST(qaTSCStressTestMaxRowID);
 | 
						|
//CPPUNIT_TEST(qaTSCStressTestMaxKey);
 | 
						|
//CPPUNIT_TEST(qaTSCIndexTestUpdate);
 | 
						|
//CPPUNIT_TEST(qaTSCIndexTestDelete);
 | 
						|
//CPPUNIT_TEST(qaTSCFreeSpaceMapTest);
 | 
						|
 | 
						|
//CPPUNIT_TEST(qatestIndexList);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    CPPUNIT_TEST_SUITE_END();
 | 
						|
 | 
						|
private:
 | 
						|
    IndexTree                  m_index;
 | 
						|
    IndexList                  m_indexlist;
 | 
						|
    FILE* curFile;
 | 
						|
 | 
						|
public:
 | 
						|
    void setUp()
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    void tearDown()
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    Create maximum number of row ids for key and verify all
 | 
						|
    index list header records
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaTSCStressTestMaxRowID()
 | 
						|
    {
 | 
						|
 | 
						|
        IdxFreeSpaceStat mapInfo;
 | 
						|
 | 
						|
        uint64_t  	idxKey = 1;
 | 
						|
        int			testCaseNo;
 | 
						|
        int			numOfRowID;
 | 
						|
        int			expSbCnt;
 | 
						|
        int			expFullSbCnt;
 | 
						|
        char		testCaseDesc[256];
 | 
						|
 | 
						|
        int			tokenLen = 1;
 | 
						|
        int			rc;
 | 
						|
        int			execMode;
 | 
						|
 | 
						|
        m_index.setUseFreeMgr( true );
 | 
						|
        m_index.setUseListMgr( true );
 | 
						|
        execMode = 0;
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "8 bit key, max row stress test");
 | 
						|
 | 
						|
        tokenLen		= 8;
 | 
						|
        testCaseNo		= 10520;
 | 
						|
        numOfRowID		= 256;
 | 
						|
        expSbCnt		= 9;
 | 
						|
        expFullSbCnt	= 8;
 | 
						|
 | 
						|
        qaSupCreateMaxRowID(idxKey, tokenLen);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
        qaDspIndexListByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "16 bit key, max row stress test");
 | 
						|
 | 
						|
        testCaseNo		= 10521;
 | 
						|
        numOfRowID		= 65536;
 | 
						|
        expSbCnt		= 2115;
 | 
						|
        expFullSbCnt	= 2114;
 | 
						|
 | 
						|
        qaSupCreateMaxRowID(idxKey, tokenLen);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    Create maximum number key for a given key length and
 | 
						|
    verify each index list header record
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaTSCStressTestMaxKey()
 | 
						|
    {
 | 
						|
 | 
						|
        IdxFreeSpaceStat mapInfo;
 | 
						|
 | 
						|
        int			testCaseNo;
 | 
						|
        char		testCaseDesc[256];
 | 
						|
        int			tokenLen;
 | 
						|
        int			entryCnt;
 | 
						|
        int			execMode;
 | 
						|
 | 
						|
        execMode = 1;
 | 
						|
//		qaSupCreateMaxHdrRec(tokenLen);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "8 bit key, max key stress test");
 | 
						|
 | 
						|
        tokenLen		= 8;
 | 
						|
        testCaseNo		= 10522;
 | 
						|
 | 
						|
        qaSupCreateMaxHdrRec(tokenLen);
 | 
						|
        qaTstStressMaxKeyDriver(testCaseNo, testCaseDesc, tokenLen);
 | 
						|
 | 
						|
 | 
						|
//		qaSupCreateMaxHdrRec(tokenLen);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "16 bit key, max key stress test");
 | 
						|
 | 
						|
        tokenLen		= 16;
 | 
						|
        testCaseNo		= 10523;
 | 
						|
 | 
						|
        qaSupCreateMaxHdrRec(tokenLen);
 | 
						|
        qaTstStressMaxKeyDriver(testCaseNo, testCaseDesc, tokenLen);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    Test cases for for updating index
 | 
						|
    ============================================================= */
 | 
						|
    void qaTSCIndexTestUpdate()
 | 
						|
    {
 | 
						|
 | 
						|
        uint64_t idxKey		= 1;
 | 
						|
        int		 tokenLen	= 16;
 | 
						|
        int		 testCaseNo;
 | 
						|
        int		 startRowID	= 1;
 | 
						|
        int		 numOfRowID;
 | 
						|
        int		 expSbCnt;
 | 
						|
        int		 expFullSbCnt;
 | 
						|
        char	 testCaseDesc[256];
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 index key with one row ID, expecting no sub block and no full sub block.");
 | 
						|
 | 
						|
        testCaseNo		= 10524;
 | 
						|
        numOfRowID		= 1;
 | 
						|
        expSbCnt		= 0;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 2 index key with one row ID, expecting no sub block and no full sub block.");
 | 
						|
 | 
						|
        testCaseNo		= 10525;
 | 
						|
        numOfRowID		= 2;
 | 
						|
        expSbCnt		= 0;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 3 index key with one row ID, expecting 1 sub block and no full sub block.");
 | 
						|
 | 
						|
        testCaseNo		= 10526;
 | 
						|
        numOfRowID		= 3;
 | 
						|
        expSbCnt		= 1;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 index key with 32 row IDs, expecting 1 sub block and 1 full sub block.");
 | 
						|
 | 
						|
        testCaseNo		= 10527;
 | 
						|
        numOfRowID		= 32;
 | 
						|
        expSbCnt		= 1;
 | 
						|
        expFullSbCnt	= 1;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 index key with 33 row IDs, expecting 2 sub block and 1 full sub block.");
 | 
						|
 | 
						|
        testCaseNo		= 10528;
 | 
						|
        numOfRowID		= 33;
 | 
						|
        expSbCnt		= 2;
 | 
						|
        expFullSbCnt	= 1;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 index key with 63 row IDs, expecting 2 sub block and 2 full sub block.");
 | 
						|
        testCaseNo		= 10529;
 | 
						|
        numOfRowID		= 63;
 | 
						|
        expSbCnt		= 2;
 | 
						|
        expFullSbCnt	= 2;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    	Test cases deleting index
 | 
						|
    	============================================================= */
 | 
						|
    void qaTSCIndexTestDelete()
 | 
						|
    {
 | 
						|
 | 
						|
 | 
						|
        uint64_t idxKey = 1;
 | 
						|
        int		 tokenLen	= 16;
 | 
						|
        int		 testCaseNo;
 | 
						|
        int		 startRowID	= 1;
 | 
						|
        int		 numOfRowID;
 | 
						|
        int		 expSbCnt;
 | 
						|
        int		 expFullSbCnt;
 | 
						|
        char	 testCaseDesc[256];
 | 
						|
 | 
						|
        int		 i;
 | 
						|
        int		 rc;
 | 
						|
 | 
						|
        //Create 1 row IDs, then remove it.
 | 
						|
        //Expecting 0 row IDs, 0 sub blocks and 0 full sub blocks.
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 row ID, then remove it.  Expecting 0 row ID, 0 sub block and 0 full sub block.");
 | 
						|
        testCaseNo		= 10530;
 | 
						|
        numOfRowID		= 1;
 | 
						|
        expSbCnt		= 0;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        m_index.setUseFreeMgr( true );
 | 
						|
        m_index.setUseListMgr( true );
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        rc = m_index.deleteIndex(idxKey, tokenLen, startRowID );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
        numOfRowID		= 0;
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
//		qaDspIndexListStatsByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
        //Create 3 row IDs, then remove the first two.
 | 
						|
        //Expecting 1 row IDs, 1 sub blocks and 0 full sub blocks.
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 3 row IDs, then remove the first two.  Expecting 1 row ID, 1 sub block and 0 full sub block.");
 | 
						|
        testCaseNo		= 10531;
 | 
						|
        numOfRowID		= 3;
 | 
						|
        expSbCnt		= 1;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        for (i = startRowID; i < startRowID + numOfRowID - 1; i++)
 | 
						|
        {
 | 
						|
            rc = m_index.deleteIndex(idxKey, tokenLen, i );
 | 
						|
            CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        }
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
        numOfRowID		= 1;
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
//		qaDspIndexListStatsByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
 | 
						|
        //Create 100 row IDs, then remove them.
 | 
						|
        //Expecting 0 row IDs, 0 sub blocks and 0 full sub blocks.
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 100 row IDs, then remove them.  Expecting 0 row ID, 0 sub block and 0 full sub block.");
 | 
						|
        testCaseNo		= 10532;
 | 
						|
        numOfRowID		= 100;
 | 
						|
        expSbCnt		= 0;
 | 
						|
        expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        for (i = startRowID; i < startRowID + numOfRowID; i++)
 | 
						|
        {
 | 
						|
            rc = m_index.deleteIndex(idxKey, tokenLen, i );
 | 
						|
            CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        }
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
        numOfRowID		= 0;
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
//		qaDspIndexListStatsByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
        //create 63 row ids so that two full sub blocks will be allocated.
 | 
						|
        //delete all row ids, 2 to 32, in the first sub block
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 63 row ids, then remove all in the 2nd sub block.  Verify that row id sub block gets released when empty.");
 | 
						|
        testCaseNo		= 10533;
 | 
						|
        numOfRowID		= 63;
 | 
						|
        expSbCnt		= 1;
 | 
						|
        expFullSbCnt	= 1;
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        for (i = 2; i < 33; i++)
 | 
						|
        {
 | 
						|
            rc = m_index.deleteIndex(idxKey, tokenLen, i );
 | 
						|
            CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        }
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
        numOfRowID		= 32;
 | 
						|
        qaTstIndexListDriver(testCaseNo, testCaseDesc, idxKey, tokenLen, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    	Test cases for empty maps
 | 
						|
    	============================================================= */
 | 
						|
 | 
						|
    void qaTSCFreeSpaceMapTest()
 | 
						|
    {
 | 
						|
 | 
						|
        IdxFreeSpaceStat mapInfo;
 | 
						|
        uint64_t idxKey = 1;
 | 
						|
        int		 tokenLen = 16;
 | 
						|
        int		 execMode = 0;
 | 
						|
        int		 testCaseNo, startKey, numOfKey;
 | 
						|
        int		 startRowID, numOfRowID;
 | 
						|
        int		 i;
 | 
						|
        int		 expMapSize, expEntryCnt;
 | 
						|
        char	 testCaseDesc[256];
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "No keys created.  There should not be a empty list for header record.");
 | 
						|
        testCaseNo		= 10534;
 | 
						|
        startKey		= 1;
 | 
						|
        numOfKey		= 0;
 | 
						|
        expMapSize		= 0;
 | 
						|
        expEntryCnt		= 0;
 | 
						|
 | 
						|
        qaSupCreateRangeKey(idxKey, tokenLen, startKey, numOfKey);
 | 
						|
        qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_4ENTRY, execMode, mapInfo);
 | 
						|
        qaTstFreeMapDriver(testCaseNo, testCaseDesc, expMapSize, expEntryCnt, mapInfo);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 1 key.  There will be space left for 7 more header records.");
 | 
						|
        testCaseNo		= 10535;
 | 
						|
        startKey		= 1;
 | 
						|
        numOfKey		= 1;
 | 
						|
        expMapSize		= 1;
 | 
						|
        expEntryCnt		= 7;
 | 
						|
 | 
						|
        qaSupCreateRangeKey(idxKey, tokenLen, startKey, numOfKey);
 | 
						|
        qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_4ENTRY, execMode, mapInfo);
 | 
						|
        qaTstFreeMapDriver(testCaseNo, testCaseDesc, expMapSize, expEntryCnt, mapInfo);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 8 row ids.  There will be space left for 0 more header records.");
 | 
						|
        testCaseNo		= 10536;
 | 
						|
        startKey		= 1;
 | 
						|
        numOfKey		= 8;
 | 
						|
        expMapSize		= 1;
 | 
						|
        expEntryCnt		= 0;
 | 
						|
 | 
						|
 | 
						|
        qaSupCreateRangeKey(idxKey, tokenLen, startKey, numOfKey);
 | 
						|
        qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_4ENTRY, execMode, mapInfo);
 | 
						|
        qaTstFreeMapDriver(testCaseNo, testCaseDesc, expMapSize, expEntryCnt, mapInfo);
 | 
						|
 | 
						|
        strcpy(testCaseDesc, "Create 9 key.  There will be space left for 7 more header records.");
 | 
						|
        testCaseNo		= 10537;
 | 
						|
        startKey		= 1;
 | 
						|
        numOfKey		= 1;
 | 
						|
        expMapSize		= 1;
 | 
						|
        expEntryCnt		= 7;
 | 
						|
 | 
						|
        qaSupCreateRangeKey(idxKey, tokenLen, startKey, numOfKey);
 | 
						|
        qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_4ENTRY, execMode, mapInfo);
 | 
						|
        qaTstFreeMapDriver(testCaseNo, testCaseDesc, expMapSize, expEntryCnt, mapInfo);
 | 
						|
        /*
 | 
						|
        		strcpy(testCaseDesc, "Verify that a sub block holding empty list entries will be released when empty.");
 | 
						|
        	    testCaseNo		= 10538;
 | 
						|
        		startRowID		= 1;
 | 
						|
        		expMapSize		= 0;
 | 
						|
        		expEntryCnt		= 0;
 | 
						|
        		//Create files without key records, then get number of 32-entry free blocks.
 | 
						|
        		numOfRowID		= 0;
 | 
						|
        		qaSupCreateRangeKey(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        		qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_32ENTRY, execMode, mapInfo);
 | 
						|
        		int initialSize = mapInfo.mapSize;
 | 
						|
        		int initialEntry = mapInfo.entryCnt;
 | 
						|
        		execMode = 1;
 | 
						|
        		qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_32ENTRY, execMode, mapInfo);
 | 
						|
        	printf("      size:   %d\n", mapInfo.mapSize);
 | 
						|
        	printf("      entry:   %d\n", mapInfo.entryCnt);
 | 
						|
 | 
						|
        		numOfRowID		= 900;  //There are 31 entries in a 32-entry empty list sub block.
 | 
						|
        								//1 ptr allocated for 4-entry free map, 1 for hdr, 29 entries remaining.
 | 
						|
        								//29 entriess, pointing 29 sub blocks.  29 x 31 = 899, plus 1 in hdr = 900 entries
 | 
						|
        		qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, numOfRowID);
 | 
						|
        		qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_32ENTRY, execMode, mapInfo);
 | 
						|
        		expMapSize		= initialSize - 1 - 1 + 1;		// - 1 hdr block, -1 4-entry list, + 1 free 32-entry block.
 | 
						|
        		expEntryCnt		= initialEntry - 29 - 1 - 1 + 1;	// -29 data sub blocks, - 1 for 4-entry list ptr, 1 for hdr record ptr, +1 free 32-entry ptr
 | 
						|
        		expEntryCnt++					;	// add 1 for the free 32-entry sub block.
 | 
						|
 | 
						|
        		qaTstFreeMapDriver(testCaseNo, testCaseDesc, expMapSize, expEntryCnt, mapInfo);
 | 
						|
        		qaDspIndexListByKey(idxKey, tokenLen);
 | 
						|
        		qaDspIndexListStatsByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
        */
 | 
						|
 | 
						|
 | 
						|
        execMode = 1;
 | 
						|
//		qaDspFreeSpaceMap(QA_FILE_TYPE_LIST, QA_FREEMAP_32ENTRY, execMode, mapInfo);
 | 
						|
 | 
						|
//   		qaDspIndexListByKey(idxKey, tokenLen);
 | 
						|
//		qaDspIndexListStatsByKey(idxKey, tokenLen);
 | 
						|
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	verify each index list header record for a given key length
 | 
						|
    	============================================================= */
 | 
						|
 | 
						|
    void qaTstStressMaxKeyDriver(int testCaseNo, char* testCaseDesc, int tokenLen)
 | 
						|
    {
 | 
						|
        bool	rc, passed, ;
 | 
						|
        int		checkMode		= 2;
 | 
						|
        int		i, maxKey;
 | 
						|
        int		numOfRowID		= 1;
 | 
						|
        int		expSbCnt		= 0;
 | 
						|
        int		expFullSbCnt	= 0;
 | 
						|
 | 
						|
        qaDspTestStatusHeader(testCaseNo, testCaseDesc);
 | 
						|
 | 
						|
        maxKey = (1 << tokenLen);
 | 
						|
 | 
						|
        if (maxKey > 160) maxKey = 120;
 | 
						|
 | 
						|
        passed = true;
 | 
						|
 | 
						|
        for (i = 0; i < maxKey; i++)
 | 
						|
        {
 | 
						|
            rc = qaSupVerifyIndexByKey(i, tokenLen, checkMode, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
 | 
						|
            if (rc != NO_ERROR) passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        qaDspTestStatusFooter(testCaseNo, passed);
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    A driver function to execution test cases for the
 | 
						|
    index list.
 | 
						|
    ============================================================= */
 | 
						|
    void qaTstIndexListDriver(int testCaseNo, char* testCaseDesc, uint64_t idxKey, int tokenLen, int numOfRowID, int expSbCnt, int expFullSbCnt)
 | 
						|
    {
 | 
						|
 | 
						|
        bool	passed;
 | 
						|
        int		checkMode = 2;
 | 
						|
 | 
						|
        qaDspTestStatusHeader(testCaseNo, testCaseDesc);
 | 
						|
        passed = qaSupVerifyIndexByKey(idxKey, tokenLen, checkMode, numOfRowID, expSbCnt, expFullSbCnt);
 | 
						|
        qaDspTestStatusFooter(testCaseNo, passed);
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	A driver function to verify free map list
 | 
						|
    	============================================================= */
 | 
						|
    void qaTstFreeMapDriver(int testCaseNo, char* testCaseDesc, int expMapSize, int expEntryCnt, IdxFreeSpaceStat mapInfo)
 | 
						|
    {
 | 
						|
 | 
						|
        int		passed			= true;
 | 
						|
 | 
						|
        qaDspTestStatusHeader(testCaseNo, testCaseDesc);
 | 
						|
 | 
						|
        if (mapInfo.mapSize != expMapSize)
 | 
						|
        {
 | 
						|
            printf("      Free map size mismatch:     Expected: %d    Returned: %d\n", expMapSize, (int)mapInfo.mapSize );
 | 
						|
            passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        if (mapInfo.entryCnt != expEntryCnt)
 | 
						|
        {
 | 
						|
            printf("      Free map entry mismatch:    Expected: %d    Returned: %d\n", expEntryCnt, (int)mapInfo.entryCnt );
 | 
						|
            passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        qaDspTestStatusFooter(testCaseNo, passed);
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    	Verify index list record with it's integral components
 | 
						|
    	and expected values from the calling program.
 | 
						|
    ============================================================= */
 | 
						|
    bool qaSupVerifyIndexByKey(uint64_t idxKey, int tokenLen, int checkMode, int expRowIDCnt, int expSbCnt, int expFullSbCnt)
 | 
						|
    {
 | 
						|
 | 
						|
        IdxListStat	idxKeyInfo;
 | 
						|
 | 
						|
        int			execMode	= 0;
 | 
						|
        int			passed		= true;
 | 
						|
 | 
						|
        //checkMode != 1		Verify index header information only
 | 
						|
        //checkMode  = 2		verify header information, plus matching expected results.
 | 
						|
 | 
						|
 | 
						|
        qaSupWalkIndexList(idxKey, tokenLen, execMode, idxKeyInfo);
 | 
						|
 | 
						|
        // verify for matching record keys
 | 
						|
        if (idxKeyInfo.hdrRec.key != idxKey)
 | 
						|
        {
 | 
						|
            printf("      Index key mismatch:         Expected: %d    Returned: %d\n", (int)idxKey, (int)idxKeyInfo.hdrRec.key );
 | 
						|
            passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        //	verify row id count in the hdr record against row id count gathered from the index list record.
 | 
						|
        if (idxKeyInfo.hdrRec.idxRidListSize.size != idxKeyInfo.recCnt)
 | 
						|
        {
 | 
						|
            printf("      Index Hdr cnt mismatch:     In Hdr  : %d    In SB:    %d\n", idxKeyInfo.hdrRec.idxRidListSize.size, idxKeyInfo.recCnt );
 | 
						|
            passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        // verify that when there is not sub blocks for the row IDs, the header's link list pointer should not be used.
 | 
						|
        if ((idxKeyInfo.sbCnt == 0) && (idxKeyInfo.hdrRec.nextIdxRidListPtr.type == 4))
 | 
						|
        {
 | 
						|
            printf("      Incorrect list pointer:     Ptr type: %d     SB Cnt:  %d\n", idxKeyInfo.hdrRec.idxRidListSize.size, idxKeyInfo.recCnt );
 | 
						|
            passed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        if (checkMode = 2)
 | 
						|
        {
 | 
						|
 | 
						|
            // verify row id count in the hdr record against expected row id count
 | 
						|
            if (idxKeyInfo.hdrRec.idxRidListSize.size != expRowIDCnt)
 | 
						|
            {
 | 
						|
                printf("      Row ID cnt mismatch:        Expected: %d    Returned: %d\n", expRowIDCnt, idxKeyInfo.hdrRec.idxRidListSize.size);
 | 
						|
                passed = false;
 | 
						|
            }
 | 
						|
 | 
						|
            //	verify sub block count gathered from the index list record against the expected sub block count
 | 
						|
            if (idxKeyInfo.sbCnt != expSbCnt)
 | 
						|
            {
 | 
						|
                printf("      Subblock cnt mismatch:      Expected: %d    Returned: %d\n", expSbCnt, idxKeyInfo.sbCnt );
 | 
						|
                passed = false;
 | 
						|
            }
 | 
						|
 | 
						|
            //	verify full sub block count gathered from the index list record against the expected full sub block count
 | 
						|
            if (idxKeyInfo.fullSbCnt != expFullSbCnt)
 | 
						|
            {
 | 
						|
                printf("      Full subblock cnt mismatch: Expected: %d    Returned: %d\n", expFullSbCnt, idxKeyInfo.fullSbCnt );
 | 
						|
                passed = false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return passed;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	Display index record for a given key
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaGetListSubblockByKey(uint64_t idxKey, int tokenLen, int sbSeqNo, int& fbo, int& sbid, int& entry)
 | 
						|
    {
 | 
						|
 | 
						|
        int		p_fbo, p_sbid, p_entry;
 | 
						|
        int		execMode = 1;
 | 
						|
        bool		exist;
 | 
						|
 | 
						|
//	   qaSupWalkIndexList(idxKey, tokenLen, execMode, sbSeqNo, p_fbo, p_sbid, p_entry, hdrCntMatch, hdrRecCnt, hdrSbCnt, hdrFullSbCnt);
 | 
						|
        fbo = p_fbo;
 | 
						|
        sbid = p_sbid;
 | 
						|
        entry = p_entry;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	Display tree empty list map for a given block size
 | 
						|
    ============================================================= */
 | 
						|
    void qaDspFreeSpaceMap(int fileType, int mapType, int execMode, IdxFreeSpaceStat& mapInfo)
 | 
						|
    {
 | 
						|
 | 
						|
        DataBlock	curBlock;
 | 
						|
        FILE*       pFile = NULL;
 | 
						|
 | 
						|
        int         fileNum;
 | 
						|
        int			p_fbo, p_sbid, p_entry, p_type, p_group;
 | 
						|
        int			i, j;
 | 
						|
        int			p_mapType;
 | 
						|
        bool		done;
 | 
						|
 | 
						|
 | 
						|
        IdxEmptyListEntry emptyMap;
 | 
						|
 | 
						|
        if (fileType == QA_FILE_TYPE_TREE)
 | 
						|
            fileNum = 990;		//index tree
 | 
						|
        else
 | 
						|
            fileNum = 991;		//index list
 | 
						|
 | 
						|
        memset( curBlock.data, 0, sizeof(curBlock.data));
 | 
						|
        pFile = m_indexlist.openFile( fileNum );
 | 
						|
        CPPUNIT_ASSERT( pFile != NULL );
 | 
						|
 | 
						|
        //Free Manager
 | 
						|
        m_indexlist.setUseFreeMgr( true );
 | 
						|
 | 
						|
        p_fbo = 0;
 | 
						|
        p_sbid = 0;
 | 
						|
        p_entry = mapType; //Entry location in Fb 0 and SB 0;
 | 
						|
 | 
						|
        if (execMode == 1)
 | 
						|
        {
 | 
						|
            printf("\n------------------------------------\n");
 | 
						|
 | 
						|
            if (fileType == 1)
 | 
						|
                printf("Index Tree %d-ENTRY free space map\n", 1 << (mapType - 1));
 | 
						|
            else
 | 
						|
                printf("Index list %d-ENTRY free space map\n", 1 << (mapType - 1));
 | 
						|
 | 
						|
            printf("------------------------------------\n");
 | 
						|
        }
 | 
						|
 | 
						|
        m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, p_entry, 8, &emptyMap);
 | 
						|
 | 
						|
        if (execMode == 1)
 | 
						|
        {
 | 
						|
//			printf("\nList Ptr:  Type = %d  Group = %d  fbo = %d  sbid = %d Entry = %d\n", p_type, p_group, p_fbo, p_sbid, p_entry);
 | 
						|
            printf("\nList:       Type = %d  Group = %d Addr(%d, %d, %d) ----> Addr(%d, %d, %d)\n", int(emptyMap.type), int(emptyMap.group), p_fbo, p_sbid, p_entry, (int)emptyMap.fbo, (int)emptyMap.sbid, (int)emptyMap.entry);
 | 
						|
            printf("-------------------------------------------------------------------------\n");
 | 
						|
        }
 | 
						|
 | 
						|
        p_type = emptyMap.type;
 | 
						|
        p_group = emptyMap.group;
 | 
						|
        p_fbo = emptyMap.fbo;
 | 
						|
        p_sbid = emptyMap.sbid;
 | 
						|
        p_entry = emptyMap.entry;
 | 
						|
 | 
						|
        p_mapType = emptyMap.type;
 | 
						|
        mapInfo.mapSize = 0;
 | 
						|
        mapInfo.entryCnt = 0;
 | 
						|
 | 
						|
        done = ((p_mapType == 1) && (p_fbo == 0) && (p_sbid == 0) && (p_entry == 0));
 | 
						|
 | 
						|
        while (not done )
 | 
						|
        {
 | 
						|
 | 
						|
            j = p_entry;
 | 
						|
            mapInfo.mapSize++;
 | 
						|
 | 
						|
            for (i = j; i >= 0; i--)
 | 
						|
            {
 | 
						|
                m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, i, 8, &emptyMap);
 | 
						|
 | 
						|
                if (execMode == 1)
 | 
						|
//					printf("EntryPtr: %d Type = %d  Group = %d  fbo = %d  sbid = %d Entry = %d\n", i, int(emptyMap.type), int(emptyMap.group), (int)emptyMap.fbo, (int)emptyMap.sbid, (int)emptyMap.entry);
 | 
						|
                    printf("Entry: %d   Type = %d  Group = %d Addr(%d, %d, %d) ----> Addr(%d, %d, %d)\n", i,  int(emptyMap.type), int(emptyMap.group), p_fbo, p_sbid, i, (int)emptyMap.fbo, (int)emptyMap.sbid, (int)emptyMap.entry);
 | 
						|
 | 
						|
                if (i != 0) mapInfo.entryCnt++;
 | 
						|
            }
 | 
						|
 | 
						|
            p_fbo = emptyMap.fbo;
 | 
						|
            p_sbid = emptyMap.sbid;
 | 
						|
            p_entry = emptyMap.entry;
 | 
						|
            p_mapType = emptyMap.type;
 | 
						|
 | 
						|
            done = ( (p_fbo == 0) && (p_sbid == 0) && (p_entry == 0));
 | 
						|
 | 
						|
            if (not done && (execMode == 1))
 | 
						|
            {
 | 
						|
//				printf("\nList Ptr:  Type: %d  Group: %d  FBO: %d  SBID: %d ENTRY: %d\n", p_type, p_group, p_fbo, p_sbid, p_entry);
 | 
						|
                printf("\nList:       Type = %d  Group = %d Addr(%d, %d, %d) ----> Addr(%d, %d, %d)\n", int(emptyMap.type), int(emptyMap.group), p_fbo, p_sbid, p_entry, (int)emptyMap.fbo, (int)emptyMap.sbid, (int)emptyMap.entry);
 | 
						|
                printf("-------------------------------------------------------------------------\n");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        m_indexlist.closeFile(pFile);
 | 
						|
 | 
						|
    } // qaDspFreeSpaceMap
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	Show branch list for all keys for a given key length
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaDspTreePathAll(uint64_t idxKey, int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        uint64_t	i;
 | 
						|
        int			maxKey;
 | 
						|
 | 
						|
        maxKey = (1 << tokenLen);
 | 
						|
 | 
						|
        for (i = 0; i < maxKey; i++)
 | 
						|
            qaDspTreePathByKey(idxKey, tokenLen);
 | 
						|
    }
 | 
						|
 | 
						|
    /*******************************************************
 | 
						|
    .   Display branch list for a key
 | 
						|
    *******************************************************/
 | 
						|
    void qaDspTreePathByKey(uint64_t idxKey, int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        int		p_fbo, p_sbid, p_entry;
 | 
						|
        bool	exist;
 | 
						|
        int		execMode = 1;
 | 
						|
 | 
						|
        qaSupWalkIndexTree(idxKey, tokenLen, execMode, p_fbo, p_sbid, p_entry, exist);
 | 
						|
 | 
						|
    } // qaDspTreePathByKey
 | 
						|
    /* ==========================================================
 | 
						|
    	Verfiy hdr records all keys for a given key length
 | 
						|
    ============================================================= */
 | 
						|
    void qaDspIndexListStatsByKey(uint64_t idxKey, int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        IdxListStat	idxKeyInfo;
 | 
						|
 | 
						|
        int			execMode = 0;
 | 
						|
        int			sbSeqNo = 0;
 | 
						|
 | 
						|
        qaSupWalkIndexList (idxKey, tokenLen, execMode, idxKeyInfo);
 | 
						|
 | 
						|
        printf("\nINDEX STATS for key: %d\n", (int)idxKey);
 | 
						|
        printf("--------------------------------------\n");
 | 
						|
        printf("Key:                %d\n", (int)idxKeyInfo.hdrRec.key );
 | 
						|
        printf("Hdr Record Count:   %d\n", idxKeyInfo.hdrRec.idxRidListSize.size );
 | 
						|
 | 
						|
        if (idxKeyInfo.hdrRec.firstIdxRidListEntry.type == 3)
 | 
						|
            printf("RowID 0   :         %d\n", idxKeyInfo.hdrRec.firstIdxRidListEntry.rid);
 | 
						|
 | 
						|
        if (idxKeyInfo.hdrRec.nextIdxRidListPtr.type == 3)
 | 
						|
            printf("RowID 1   :         %d\n", (int)idxKeyInfo.hdrRec.nextIdxRidListPtr.llp);
 | 
						|
 | 
						|
        printf("File Block:         %d\n", idxKeyInfo.fbo);
 | 
						|
        printf("Sub Block:          %d\n", idxKeyInfo.sbid);
 | 
						|
        printf("Entry:              %d\n", idxKeyInfo.entry);
 | 
						|
        printf("Actual Row ID Cnt:  %d\n", idxKeyInfo.recCnt);
 | 
						|
        printf("Sub Block Cnt:      %d\n", idxKeyInfo.sbCnt);
 | 
						|
        printf("Full Sub Block Cnt: %d\n", idxKeyInfo.fullSbCnt);
 | 
						|
        printf("Row ID Cnt Match?:  ");
 | 
						|
 | 
						|
        if (idxKeyInfo.hdrRec.idxRidListSize.size == idxKeyInfo.recCnt)
 | 
						|
            printf("Yes\n");
 | 
						|
        else
 | 
						|
            printf("No\n");
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    	Display index record all keys for a given key length
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaDspIndexListAll(uint64_t, int tokenLen)
 | 
						|
    {
 | 
						|
        uint64_t	i;
 | 
						|
        int			maxKey;
 | 
						|
 | 
						|
        maxKey = (1 << tokenLen);
 | 
						|
 | 
						|
        for (i = 0; i < maxKey; i++)
 | 
						|
            qaDspIndexListByKey(i, tokenLen);
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	Display index record for a given key
 | 
						|
    ============================================================= */
 | 
						|
    void qaDspIndexListByKey(uint64_t idxKey, int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        IdxListStat	idxKeyInfo;
 | 
						|
 | 
						|
        int		p_fbo, p_sbid, p_entry;
 | 
						|
        int		execMode = 1;
 | 
						|
        bool		exist;
 | 
						|
        int		sbSeqNo = 0;
 | 
						|
 | 
						|
        qaSupWalkIndexList (idxKey, tokenLen, execMode, idxKeyInfo);
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
    	Display test case status header
 | 
						|
    	============================================================= */
 | 
						|
    void qaDspTestStatusHeader(int testCaseNo, char* testCaseDesc)
 | 
						|
    {
 | 
						|
 | 
						|
        printf("\nBEGIN IdxHdrTestCase %d\n", testCaseNo);
 | 
						|
        printf("      Desc:   %s\n", testCaseDesc);
 | 
						|
    }
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    	Display test case status header
 | 
						|
    	============================================================= */
 | 
						|
    void qaDspTestStatusFooter(int testCaseNo, bool passed)
 | 
						|
    {
 | 
						|
 | 
						|
        if (passed)
 | 
						|
            printf("      Status: Passed\n");
 | 
						|
        else
 | 
						|
        {
 | 
						|
            printf("      Status: Failed  -- [**ERROR**]\n");
 | 
						|
        }
 | 
						|
 | 
						|
        printf("END   IdxHdrTestCase %d\n", testCaseNo);
 | 
						|
    }
 | 
						|
    /* ==========================================================
 | 
						|
       Populate tree with max key for a given bit length
 | 
						|
       Populate tree row ID for a given bitlength
 | 
						|
    ============================================================= */
 | 
						|
    void qaSupCreateMaxRowID(uint64_t idxKey, int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        int			maxKey;
 | 
						|
        int			startRowID = 0;
 | 
						|
 | 
						|
        maxKey = (1 << tokenLen);
 | 
						|
 | 
						|
        qaSupCreateRangeRowID(idxKey, tokenLen, startRowID, maxKey);
 | 
						|
 | 
						|
    } //qaSupCreateMaxRowID
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
       Populate tree with a range of row IDs for a key.
 | 
						|
    ============================================================= */
 | 
						|
    void qaSupCreateRangeRowID(uint64_t idxKey, int tokenLen, int startRowID, int numOfRowID)
 | 
						|
    {
 | 
						|
 | 
						|
        int			rc;
 | 
						|
        int			i;
 | 
						|
        int			maxKey;
 | 
						|
 | 
						|
        rc = m_index.dropIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        rc = m_index.createIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        m_index.setUseFreeMgr( true );
 | 
						|
        m_index.setUseListMgr( true );
 | 
						|
 | 
						|
        // here is the correct check
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        for (i = 0; i < numOfRowID; i++)
 | 
						|
        {
 | 
						|
            rc = m_index.updateIndex( idxKey, tokenLen, startRowID + i );  //1 key, multiple rows, multiple row ids
 | 
						|
            CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
        }
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
    } //qaSupCreateMaxRowID
 | 
						|
 | 
						|
    /* ==========================================================
 | 
						|
    Populate tree with max key for a given bit length
 | 
						|
    Populate tree row ID for a given bitlength
 | 
						|
    ============================================================= */
 | 
						|
    void qaSupCreateMaxHdrRec(int tokenLen)
 | 
						|
    {
 | 
						|
 | 
						|
        int			rc;
 | 
						|
        uint64_t		i;
 | 
						|
        int			maxKey;
 | 
						|
 | 
						|
        rc = m_index.dropIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        rc = m_index.createIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        m_index.setUseFreeMgr( true );
 | 
						|
        m_index.setUseListMgr( true );
 | 
						|
 | 
						|
        // here is the correct check
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        maxKey = (1 << tokenLen);
 | 
						|
 | 
						|
        if (maxKey > 160) maxKey = 160;
 | 
						|
 | 
						|
        for (i = 0; i < maxKey; i++)
 | 
						|
            rc = m_index.updateIndex( i, tokenLen, i );  //1 row id per key.
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
    } //qaSupCreateMaxHdrRec
 | 
						|
    /* ==========================================================
 | 
						|
    Populate tree with range of keys
 | 
						|
    ============================================================= */
 | 
						|
 | 
						|
    void qaSupCreateRangeKey(uint64_t idxKey, int tokenLen, int startKey, int numOfKey)
 | 
						|
    {
 | 
						|
        int			rc;
 | 
						|
        uint64_t   	i;
 | 
						|
        int			maxKey;
 | 
						|
 | 
						|
        rc = m_index.dropIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        rc = m_index.createIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        m_index.setUseFreeMgr( true );
 | 
						|
        m_index.setUseListMgr( true );
 | 
						|
 | 
						|
        // here is the correct check
 | 
						|
        rc = m_index.openIndex( 990, 991 );
 | 
						|
        CPPUNIT_ASSERT( rc == NO_ERROR );
 | 
						|
 | 
						|
        for (i = startKey; i < startKey + numOfKey; i++)
 | 
						|
            rc = m_index.updateIndex( i, tokenLen, i );  //1 row id per key.
 | 
						|
 | 
						|
        m_index.closeIndex();
 | 
						|
 | 
						|
    } //qaSupCreateRangeKey
 | 
						|
 | 
						|
    /*******************************************************
 | 
						|
    .  This function navigate through the index list record.
 | 
						|
    few global variables are set relating to index list.
 | 
						|
    *******************************************************/
 | 
						|
    void qaSupWalkIndexList (uint64_t idxKey, int tokenLen, int execMode, IdxListStat& idxKeyInfo)
 | 
						|
    {
 | 
						|
 | 
						|
        DataBlock  indexBlock;
 | 
						|
        FILE*			pFileIndexList = NULL;
 | 
						|
        int			file_indexList = 991;
 | 
						|
 | 
						|
        int p_fbo, p_sbid, p_entry;
 | 
						|
        int i,;
 | 
						|
        int SBRecCnt;
 | 
						|
        bool endOfList;
 | 
						|
        bool exist;
 | 
						|
        int tempExecMode;
 | 
						|
 | 
						|
 | 
						|
        IdxRidListEntry listEntry;
 | 
						|
        IdxRidListPtr listPtr;
 | 
						|
        IdxRidListHdr indexListHdrRec;
 | 
						|
 | 
						|
 | 
						|
        //Free Manager
 | 
						|
        m_indexlist.setUseFreeMgr( true );
 | 
						|
        tempExecMode = execMode;
 | 
						|
        execMode = 0;
 | 
						|
        qaSupWalkIndexTree(idxKey, tokenLen, execMode, p_fbo, p_sbid, p_entry, exist);
 | 
						|
        execMode = tempExecMode;
 | 
						|
 | 
						|
        idxKeyInfo.fbo = p_fbo;		//Save the address for the header
 | 
						|
        idxKeyInfo.sbid = p_sbid;
 | 
						|
        idxKeyInfo.entry = p_entry;
 | 
						|
 | 
						|
        if (not exist)
 | 
						|
            printf("Tree node not found: Key = %d\n", (int)idxKey);
 | 
						|
        else
 | 
						|
        {
 | 
						|
            //read index list header record
 | 
						|
 | 
						|
            i = 0;
 | 
						|
 | 
						|
            idxKeyInfo.sbCnt = 0;
 | 
						|
            idxKeyInfo.fullSbCnt = 0;
 | 
						|
            idxKeyInfo.recCnt = 0; //first entry in the hdr
 | 
						|
            endOfList = false;
 | 
						|
 | 
						|
            memset( indexBlock.data, 0, sizeof(indexBlock.data));
 | 
						|
            pFileIndexList = m_indexlist.openFile( file_indexList );
 | 
						|
            CPPUNIT_ASSERT( pFileIndexList != NULL );
 | 
						|
 | 
						|
            m_indexlist.readSubBlockEntry( pFileIndexList, &indexBlock, p_fbo, p_sbid, p_entry, 32, &indexListHdrRec);
 | 
						|
 | 
						|
            idxKeyInfo.hdrRec = indexListHdrRec;
 | 
						|
 | 
						|
 | 
						|
            if (execMode == 1)
 | 
						|
            {
 | 
						|
                printf("\n---------------------------------\n");
 | 
						|
                printf("Index record for key: %d\n", (int)idxKey);
 | 
						|
                printf("---------------------------------\n");
 | 
						|
                printf("Size:    %d\n", (int)indexListHdrRec.idxRidListSize.size);
 | 
						|
                printf("Key:     %d\n", (int)indexListHdrRec.key);
 | 
						|
                printf("RowID 1: %d    Type:  %d\n", (int)indexListHdrRec.firstIdxRidListEntry.rid, (int)indexListHdrRec.firstIdxRidListEntry.type);
 | 
						|
 | 
						|
                if (indexListHdrRec.nextIdxRidListPtr.type == 3 )
 | 
						|
                    printf("RowID 2: %d    Type: %d\\nn", (int)indexListHdrRec.nextIdxRidListPtr.llp, (int)indexListHdrRec.nextIdxRidListPtr.type);
 | 
						|
                else if (indexListHdrRec.nextIdxRidListPtr.type == 4 )
 | 
						|
                    printf("Ptr:     Addr(%d, %d, %d) Type = %d\n\n", (int)((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->fbo, (int)((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->sbid, (int)((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->entry, (int)indexListHdrRec.nextIdxRidListPtr.type);
 | 
						|
            }
 | 
						|
 | 
						|
            if (int(indexListHdrRec.firstIdxRidListEntry.type) == 3)
 | 
						|
                idxKeyInfo.recCnt++;
 | 
						|
 | 
						|
            if (indexListHdrRec.nextIdxRidListPtr.type == 3 )
 | 
						|
            {
 | 
						|
                idxKeyInfo.recCnt++;
 | 
						|
            }
 | 
						|
            else if (indexListHdrRec.nextIdxRidListPtr.type == 4 )
 | 
						|
            {
 | 
						|
                p_fbo = ((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->fbo;
 | 
						|
                p_sbid = ((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->sbid;
 | 
						|
                p_entry = ((IdxEmptyListEntry*) & (indexListHdrRec.nextIdxRidListPtr))->entry;
 | 
						|
 | 
						|
                while ( not endOfList )
 | 
						|
                {
 | 
						|
                    idxKeyInfo.sbCnt++;
 | 
						|
                    SBRecCnt = 0;
 | 
						|
                    m_indexlist.readSubBlockEntry( pFileIndexList, &indexBlock, p_fbo, p_sbid, 31, 8, &listPtr);
 | 
						|
                    printf("Index list subblock: #%d\n", idxKeyInfo.sbCnt);
 | 
						|
 | 
						|
                    for (i = 0; i <= 30; i++)
 | 
						|
                    {
 | 
						|
                        m_indexlist.readSubBlockEntry( pFileIndexList, &indexBlock, p_fbo, p_sbid, i, 8, &listEntry);
 | 
						|
 | 
						|
                        if (listEntry.type == 3)
 | 
						|
                        {
 | 
						|
                            SBRecCnt++;
 | 
						|
 | 
						|
                            if (execMode == 1)
 | 
						|
                                printf("Entry %d: Addr(%d, %d, %d)  RowId: %d \n", i, p_fbo, p_sbid, i, listEntry.rid);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    p_fbo = ((IdxEmptyListEntry*) & (listPtr))->fbo;
 | 
						|
                    p_sbid = ((IdxEmptyListEntry*) & (listPtr))->sbid;
 | 
						|
 | 
						|
                    if ((idxKeyInfo.sbSeqNo != 0 ) && (idxKeyInfo.sbSeqNo == (idxKeyInfo.sbCnt - 1)))
 | 
						|
                    {
 | 
						|
                        idxKeyInfo.fbo = p_fbo;		//Save the address for the request block
 | 
						|
                        idxKeyInfo.sbid = p_sbid;
 | 
						|
                        idxKeyInfo.entry = p_entry;
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (execMode == 1 )
 | 
						|
                        printf("Entry 31: Addr(%d, %d, %d)   RecCnt = %d\n\n", p_fbo, p_sbid, p_entry, (int)listPtr.count);
 | 
						|
 | 
						|
                    idxKeyInfo.recCnt += SBRecCnt;
 | 
						|
 | 
						|
                    if (SBRecCnt == 31) idxKeyInfo.fullSbCnt++;
 | 
						|
 | 
						|
                    if (SBRecCnt != listPtr.count)
 | 
						|
                        printf("[**ERROR**] Sub Block entry count Error: In Ptr Rec: %d  In sub block: %d\n", listPtr.count, SBRecCnt);
 | 
						|
 | 
						|
                    endOfList = (listPtr.type == 0);
 | 
						|
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        m_indexlist.closeFile(pFileIndexList);
 | 
						|
    }
 | 
						|
 | 
						|
    /*******************************************************
 | 
						|
    .  This function navigate through the tree, from the
 | 
						|
    bitmap entry to the leaf.  It can be used for many
 | 
						|
    functions that require access to the hdr record also.
 | 
						|
    *******************************************************/
 | 
						|
    void qaSupWalkIndexTree(uint64_t idxKey, int tokenLen, int execMode, int& fbo, int& sbid, int& entry, bool& exist)
 | 
						|
    {
 | 
						|
 | 
						|
        DataBlock               curBlock;
 | 
						|
        FILE*                   pFile = NULL;
 | 
						|
        int                     file_number = 990;
 | 
						|
 | 
						|
        IdxBitmapPointerEntry   bitmapRec;
 | 
						|
        IdxBitTestEntry		  treeNodeRec;
 | 
						|
        int p_fbo, p_sbid, p_entry, p_type, p_group, p_bitTest;
 | 
						|
        int i;
 | 
						|
        int maskValue = 31;  //mask for 11111.
 | 
						|
        int bitMapLoc, key1, shiftBits;
 | 
						|
        int bitCnt;
 | 
						|
        bool found;
 | 
						|
        int mask[5] = {1, 3, 7, 15, 31};
 | 
						|
        int group[7] = {1, 2, 4, 8, 16, 32, 64};
 | 
						|
 | 
						|
        memset( curBlock.data, 0, sizeof(curBlock.data));
 | 
						|
        pFile = m_indexlist.openFile( file_number );
 | 
						|
        CPPUNIT_ASSERT( pFile != NULL );
 | 
						|
 | 
						|
        //Free Manager
 | 
						|
        m_indexlist.setUseFreeMgr( true );
 | 
						|
 | 
						|
        if (tokenLen > 5)
 | 
						|
            bitMapLoc = ((idxKey >> tokenLen - 5) & maskValue);
 | 
						|
        else
 | 
						|
            bitMapLoc = idxKey;
 | 
						|
 | 
						|
        p_fbo = 0;
 | 
						|
        p_sbid = 1;
 | 
						|
        p_entry = bitMapLoc;
 | 
						|
 | 
						|
        if (execMode == 1)
 | 
						|
        {
 | 
						|
            printf("\n---------------------------------\n");
 | 
						|
            printf("Tree branch path for key: %d\n", (int)idxKey);
 | 
						|
            printf("---------------------------------\n");
 | 
						|
        }
 | 
						|
 | 
						|
        m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, p_entry, 8, &bitmapRec);
 | 
						|
 | 
						|
        shiftBits = 1;
 | 
						|
        p_type = bitmapRec.type;
 | 
						|
        p_fbo = bitmapRec.fbo;
 | 
						|
        p_sbid = bitmapRec.sbid;
 | 
						|
        p_entry = bitmapRec.entry;
 | 
						|
 | 
						|
        if (execMode == 1) // branch list
 | 
						|
            printf("Bitmap:   Type= %d            BitTest= %d  FBO= %d  SBID= %d Entry= %d\n", int(p_type), int(p_bitTest), (int)p_fbo, (int)p_sbid, (int)p_entry);
 | 
						|
 | 
						|
        bitCnt = tokenLen - 5;
 | 
						|
 | 
						|
        while (bitCnt > 0)
 | 
						|
        {
 | 
						|
            if (bitCnt > 5)
 | 
						|
                key1 = ((idxKey >> (bitCnt - 5)) & maskValue);
 | 
						|
            else
 | 
						|
                key1 = ((idxKey) & mask[bitCnt - 1]);
 | 
						|
 | 
						|
            m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, p_entry, 8, &treeNodeRec);
 | 
						|
 | 
						|
            int groupIdx = treeNodeRec.group;
 | 
						|
//		printf("group: %d  count: %d\n", groupIdx, group[groupIdx]);
 | 
						|
 | 
						|
            found = false;
 | 
						|
 | 
						|
            for (i = 0; i < group[groupIdx]; i++)
 | 
						|
            {
 | 
						|
                m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, p_entry + i, 8, &treeNodeRec);
 | 
						|
                found = ( treeNodeRec.bitTest == key1);
 | 
						|
                p_type = treeNodeRec.type;
 | 
						|
 | 
						|
//			printf("key1: %d  bitTest: %d\n", key1, treeNodeRec.bitTest);
 | 
						|
                if (found) i = group[groupIdx];
 | 
						|
 | 
						|
            };
 | 
						|
 | 
						|
//			m_indexlist.readSubBlockEntry( pFile, &curBlock, p_fbo, p_sbid, p_entry, 8, &treeNodeRec);
 | 
						|
 | 
						|
            p_type = treeNodeRec.type;
 | 
						|
 | 
						|
            p_group = treeNodeRec.group;
 | 
						|
 | 
						|
            p_bitTest = treeNodeRec.bitTest;
 | 
						|
 | 
						|
            p_fbo = treeNodeRec.fbo;
 | 
						|
 | 
						|
            p_sbid = treeNodeRec.sbid;
 | 
						|
 | 
						|
            p_entry = treeNodeRec.entry;
 | 
						|
 | 
						|
            bitCnt = bitCnt - 5;
 | 
						|
 | 
						|
            if (execMode == 1) // branch list
 | 
						|
                printf("Level:    Type= %d  Group= %d  BitTest= %d  FBO= %d  SBID= %d Entry= %d\n", int(p_type), int(p_group), int(p_bitTest), (int)p_fbo, (int)p_sbid, (int)p_entry);
 | 
						|
        }
 | 
						|
 | 
						|
//set global variables so that calling functions can access to the address of the index header record
 | 
						|
 | 
						|
        exist = found;
 | 
						|
        fbo = p_fbo;
 | 
						|
        sbid = p_sbid;
 | 
						|
        entry = p_entry;
 | 
						|
 | 
						|
        m_indexlist.closeFile(pFile);
 | 
						|
    } // qaSupWalkIndexTree
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
CPPUNIT_TEST_SUITE_REGISTRATION( IndexTest );
 | 
						|
 | 
						|
#include <cppunit/extensions/TestFactoryRegistry.h>
 | 
						|
#include <cppunit/ui/text/TestRunner.h>
 | 
						|
 | 
						|
int main( int argc, char** argv)
 | 
						|
{
 | 
						|
    CppUnit::TextUi::TestRunner runner;
 | 
						|
    CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
 | 
						|
    runner.addTest( registry.makeTest() );
 | 
						|
    bool wasSuccessful = runner.run( "", false );
 | 
						|
    return (wasSuccessful ? 0 : 1);
 | 
						|
}
 | 
						|
 | 
						|
 |