1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 /******************************************************************************************
19 * $Id: we_indextree.cpp 4450 2013-01-21 14:13:24Z rdempsey $
20 *
21 ******************************************************************************************/
22 /** @file */
23 
24 #include <stdio.h>
25 #include <string.h>
26 
27 #define WRITEENGINEINDEXTREE_DLLEXPORT
28 #include "we_indextree.h"
29 #undef WRITEENGINEINDEXTREE_DLLEXPORT
30 
31 namespace WriteEngine
32 {
33 
34 /**
35  * Constructor
36  */
IndexTree()37 IndexTree::IndexTree()
38     : m_useFreeMgr( true ), m_useListMgr( true ), m_useMultiCol( false), m_useMultiRid( false ), m_assignFbo( 0 )
39 {
40     clearBlock( &m_rootBlock );
41 }
42 
43 /**
44  * Default Destructor
45  */
~IndexTree()46 IndexTree::~IndexTree()
47 {}
48 
49 /*
50    const int IndexTree::getIndexTreeBitTestEntry( uint64_t entry, short* entryType, int* bitTest, int* group, int32_t* treePointer )
51    {
52       *treePointer = entry & IDX_PTR_MASK;
53       entry = entry >> IDX_PTR_SIZE + 2; // skip one spare bit and bit-compare bit
54 
55       *group = entry & THREE_BIT_MASK;
56       entry = entry >> IDX_GROUP_SIZE;
57 
58       *bitTest = entry & TEN_BIT_MASK;
59       *entryType = entry >> IDX_BITTEST_SIZE;
60 
61       *entryType = entry & THREE_BIT_MASK;
62 
63       return NO_ERROR;
64    }
65 
66    const void IndexTree::setIndexTreeBitTestEntry( uint64_t* entry, short entryType, int bitTest, int group, int32_t treePointer )
67    {
68       memset( entry, 0, ROW_PER_BYTE );
69 
70       *entry = treePointer | group << ( IDX_PTR_SIZE + 2 );
71       *entry = *entry | bitTest << ( IDX_PTR_SIZE + 2 + IDX_GROUP_SIZE );
72       *entry = *entry | entryType << ( IDX_PTR_SIZE + 2 + IDX_GROUP_SIZE + IDX_TYPE_SIZE );
73 
74       return NO_ERROR;
75    }
76 */
77 /***********************************************************
78  * DESCRIPTION:
79  *    Clear the tree
80  * PARAMETERS:
81  *    myTree - tree pointer
82  * RETURN:
83  *    none
84  ***********************************************************/
clearTree(IdxTree * myTree)85 void IndexTree::clearTree( IdxTree* myTree )
86 {
87     myTree->width = myTree->key = myTree->rid = myTree->maxLevel = 0;
88 
89     for ( int i = 0; i < IDX_MAX_TREE_LEVEL; i++ )
90         clearTreeNode( &myTree->node[i] );
91 }
92 
93 /***********************************************************
94  * DESCRIPTION:
95  *    Clear the tree node
96  * PARAMETERS:
97  *    myNode - node pointer
98  * RETURN:
99  *    none
100  ***********************************************************/
clearTreeNode(IdxTreeNode * myNode)101 void IndexTree::clearTreeNode( IdxTreeNode* myNode )
102 {
103     myNode->level = 0;
104     myNode->allocCount = 0;
105     myNode->useCount = 0;
106 //      myNode->group = 0;
107     myNode->used = false;
108     setBlankEntry( &myNode->next );
109     setBlankEntry( &myNode->current );
110 }
111 
112 
113 /***********************************************************
114  * DESCRIPTION:
115  *    Assign segment from free manager
116  * PARAMETERS:
117  *    segmentType - group type
118  *    assignPtr - the assigned ptr
119  *    no - internal debug use flag
120  * RETURN:
121  *    NO_ERROR if success
122  *    error no if fail
123  ***********************************************************/
assignSegment(int segmentType,IdxEmptyListEntry * assignPtr,int no)124 const int IndexTree::assignSegment( int segmentType, IdxEmptyListEntry* assignPtr, int no )
125 {
126     int rc = NO_ERROR;
127 
128     m_rootBlock.dirty = true;
129 
130     if ( m_useFreeMgr )
131     {
132         if ( isDebug( DEBUG_3 ))
133         {
134             printf( "\n++++++ Before Assign");
135             printMemSubBlock( &m_rootBlock, 0, true );
136         }
137 
138         rc = m_freeMgr.assignSegment( /*m_pTreeFile*/m_cbTree, &m_rootBlock, TREE, (IdxTreeGroupType) segmentType, assignPtr /*, TREE */);
139 
140         if ( isDebug( DEBUG_3 ))
141         {
142             printf( "\nAssign the pointer, entry segment=%d fbo=%2d sbid=%2d entry=%2d", segmentType, (int)assignPtr->fbo, (int)assignPtr->sbid, (int)assignPtr->entry );
143             printMemSubBlock( &m_rootBlock, 0, true );
144         }
145     }
146     else
147     {
148         assignPtr->fbo = 1 + m_assignFbo;
149         assignPtr->sbid = 3 + no;
150         assignPtr->entry = 4 ;
151     }
152 
153     return rc;
154 }
155 
156 
157 /***********************************************************
158  * DESCRIPTION:
159  *    Build a complete empty tree branch
160  * PARAMETERS:
161  *    key - key value
162  *    width - key width
163  *    rid - row id
164  *    rootTestbitVal - test bit test value at root level
165  * RETURN:
166  *    NO_ERROR if success
167  *    error no if fail
168  ***********************************************************/
buildEmptyIndexTreeBranch(const uint64_t key,const int width,const RID rid,const int rootTestbitVal)169 const int IndexTree::buildEmptyIndexTreeBranch( const uint64_t key, const int width, const RID rid, const int rootTestbitVal )
170 {
171     int                     rc;
172     IdxBitmapPointerEntry   bitmapEntry = {0};
173 
174     rc = buildEmptyTreePart( key, width, rid, 1 );
175 
176     // set the root level bitmapPointerMap
177     bitmapEntry.type = BITMAP_PTR; //BIT_TEST;
178     bitmapEntry.fbo = m_tree.node[0].next.fbo;
179     bitmapEntry.sbid = m_tree.node[0].next.sbid;
180     bitmapEntry.entry = m_tree.node[0].next.entry;
181 
182     setSubBlockEntry( m_rootBlock.data, IDX_BITMAP_SUBBLOCK_NO, rootTestbitVal, MAX_COLUMN_BOUNDARY, &bitmapEntry );
183     m_rootBlock.dirty = true;
184 
185     return rc;
186 }
187 
188 /***********************************************************
189  * DESCRIPTION:
190  *    Build exist index tree branch
191  * PARAMETERS:
192  *    key - key value
193  *    width - key width
194  *    rid - row id
195  *    rootTestbitVal - test bit at root level
196  *    bitmapEntry - current bitmap entry
197  * RETURN:
198  *    NO_ERROR if success
199  *    error no if fail
200  ***********************************************************/
buildExistIndexTreeBranch(const uint64_t key,const int width,const RID rid,const int rootTestbitVal,IdxBitmapPointerEntry bitmapEntry)201 const int IndexTree::buildExistIndexTreeBranch( const uint64_t key, const int width, const RID rid, const int rootTestbitVal, IdxBitmapPointerEntry bitmapEntry )
202 {
203     int                     rc = NO_ERROR, loopCount, testbitVal, i, j, allocCount, realCount, matchPos, moveCount, parentLevel = 0, curLevel, curOffset = 0;
204     bool                    bSuccess;
205     IdxEmptyListEntry       assignPtrEntry, releasePtrEntry;
206     IdxBitTestEntry         bittestEntry, matchBitTestEntry, parentBitTestEntry, curEntry;
207     DataBlock               curBlock, parentBlock;
208     bool                    bAddFlag = false, bDone = false, bFound, bExitOuterLoop, bExitInnerLoop, entryMap[ENTRY_PER_SUBBLOCK];
209 
210     bExitOuterLoop = false;
211     loopCount = m_tree.maxLevel;
212 
213     for ( i = 1; !bExitOuterLoop && i < loopCount; i++ )
214     {
215         // load the block
216         rc = readSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
217                                 m_tree.node[parentLevel].next.entry, MAX_COLUMN_BOUNDARY, &bittestEntry );
218 
219         if ( rc != NO_ERROR )
220             return rc;
221 
222         if ( i == 1 && isAddrPtrEmpty( &bittestEntry, BIT_TEST ))
223             return ERR_STRUCT_EMPTY;
224 
225         rc = getTreeNodeInfo( &curBlock, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry, width,
226                               (IdxTreeGroupType)bittestEntry.group, &allocCount, &realCount, entryMap );
227 
228         if ( rc != NO_ERROR )
229             return rc;
230 
231 
232         matchBitTestEntry = bittestEntry;   // assign to the value of the first entry
233         bSuccess = getTestbitValue( key, width, i, &testbitVal );
234 
235         setBittestEntry( &curEntry, testbitVal, bittestEntry.group, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry );
236         setTreeNode( &m_tree.node[i], i, allocCount, realCount, 0, bittestEntry, curEntry );
237 
238         matchBitTestEntry.bitTest = testbitVal;
239         bFound = getTreeMatchEntry( &curBlock, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry,
240                                     width, allocCount, entryMap, &matchPos, &matchBitTestEntry );
241 
242         if ( !bFound )   // this testbit not exist at the current level
243         {
244             bExitOuterLoop = true;    // tell to exit the outer loop
245             bAddFlag = true;
246 
247             if ( allocCount < realCount + 1 ) // we have enough space to take care of the extra one
248             {
249                 // we don't have space to take care of the extra one, have to reassign to a big block
250                 if ( bittestEntry.group >= ENTRY_32 )            // it's impossible this condition holds true
251                     return ERR_IDX_TREE_INVALID_GRP;
252 
253                 m_tree.node[i].current.group++;
254                 rc = assignSegment( m_tree.node[i].current.group, &assignPtrEntry, i );
255 
256                 if ( rc != NO_ERROR )
257                     return rc;
258 
259                 m_tree.node[i].allocCount = 0x1 << m_tree.node[i].current.group;
260 
261                 if ( isDebug( DEBUG_3 ))
262                 {
263                     printf( "\nEntry starting from %d:%d:%d (type %d ) will move to %d:%d:%d (type %d)", (int)m_tree.node[parentLevel].next.fbo, (int)m_tree.node[parentLevel].next.sbid, (int)m_tree.node[parentLevel].next.entry, (int)(m_tree.node[i].current.group - 1),
264                             (int)assignPtrEntry.fbo, (int)assignPtrEntry.sbid, (int)assignPtrEntry.entry, (int)m_tree.node[i].current.group );
265                     printf( "\nNew space capacity is %d", (int)m_tree.node[i].allocCount );
266                     printf( "\nBefore the move" );
267                     printSubBlock( m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid );
268                     printSubBlock( assignPtrEntry.fbo, assignPtrEntry.sbid );
269                 }
270 
271                 rc = moveEntry( m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry, width,
272                                 assignPtrEntry.fbo, assignPtrEntry.sbid, assignPtrEntry.entry, m_tree.node[i].current.group,
273                                 allocCount, entryMap, &moveCount, m_tree.node[i].allocCount );
274 
275                 if ( rc != NO_ERROR )
276                     return rc;
277 
278                 if (  isDebug( DEBUG_3 ))
279                 {
280                     printf( "\nAfter the move" );
281                     printSubBlock( m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid );
282                     printSubBlock( assignPtrEntry.fbo, assignPtrEntry.sbid );
283                 }
284 
285                 if ( moveCount != realCount )
286                     return ERR_IDX_TREE_MOVE_ENTRY;
287 
288                 // set release entry
289                 setEmptyListEntry( &releasePtrEntry, bittestEntry.group, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry );
290 
291                 if ( i == 1 )   // handle bitmap parent
292                 {
293                     bitmapEntry.fbo = m_tree.node[0].next.fbo = m_tree.node[i].current.fbo = assignPtrEntry.fbo;
294                     bitmapEntry.sbid = m_tree.node[0].next.sbid = m_tree.node[i].current.sbid = assignPtrEntry.sbid;
295                     bitmapEntry.entry = m_tree.node[0].next.entry = m_tree.node[i].current.entry = assignPtrEntry.entry;
296                     setSubBlockEntry( m_rootBlock.data, IDX_BITMAP_SUBBLOCK_NO, rootTestbitVal, MAX_COLUMN_BOUNDARY, &bitmapEntry );
297                 }
298                 else   // handle parent for the rest of levels in the tree
299                 {
300                     rc = readSubBlockEntry( m_cbTree, &parentBlock, m_tree.node[parentLevel].current.fbo, m_tree.node[parentLevel].current.sbid,
301                                             m_tree.node[parentLevel].current.entry, MAX_COLUMN_BOUNDARY, &parentBitTestEntry );
302 
303                     if ( rc != NO_ERROR )
304                         return rc;
305 
306                     parentBitTestEntry.fbo = m_tree.node[parentLevel].next.fbo = m_tree.node[i].current.fbo = assignPtrEntry.fbo;
307                     parentBitTestEntry.sbid = m_tree.node[parentLevel].next.sbid = m_tree.node[i].current.sbid = assignPtrEntry.sbid;
308                     parentBitTestEntry.entry = m_tree.node[parentLevel].next.entry = m_tree.node[i].current.entry = assignPtrEntry.entry;
309 
310                     rc = writeSubBlockEntry( m_cbTree, &parentBlock, m_tree.node[parentLevel].current.fbo, m_tree.node[parentLevel].current.sbid,
311                                              m_tree.node[parentLevel].current.entry, MAX_COLUMN_BOUNDARY, &parentBitTestEntry );
312 
313                     if ( rc != NO_ERROR )
314                         return rc;
315                 }
316 
317                 // here's the work to release the ptr
318                 rc = releaseSegment( bittestEntry.group, &releasePtrEntry );
319 
320                 if ( rc != NO_ERROR )
321                     return rc;
322 
323             } // end of if( allocCount >=
324 
325             // take care of rest of empty part
326             rc = readSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
327                                     m_tree.node[parentLevel].next.entry, MAX_COLUMN_BOUNDARY, &bittestEntry );
328 
329             if ( rc != NO_ERROR )
330                 return rc;
331 
332             m_tree.node[i].current.bitTest = testbitVal;
333             matchBitTestEntry.group = m_tree.node[i].current.group;
334             m_tree.node[i].allocCount = 0x1 << m_tree.node[i].current.group;
335 
336             bExitInnerLoop = false;
337 
338             for ( j = 0; !bExitInnerLoop && j < m_tree.node[i].allocCount; j++ )
339                 if ( !entryMap[j] )          // here's the empty spot
340                 {
341 
342                     if ( m_tree.maxLevel > 2 && i != loopCount - 1 )
343                     {
344                         rc = buildEmptyTreePart( key, width, rid, i + 1, 0 );
345 
346                         if ( rc != NO_ERROR )
347                             return rc;
348 
349                         bDone = true;
350                     }
351 
352                     // check out of bound
353                     rc = readSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
354                                             m_tree.node[parentLevel].next.entry + j, MAX_COLUMN_BOUNDARY, &bittestEntry );
355 
356                     if ( rc != NO_ERROR )
357                         return rc;
358 
359                     matchBitTestEntry.fbo = m_tree.node[i + 1].current.fbo;
360                     matchBitTestEntry.sbid = m_tree.node[i + 1].current.sbid;
361                     matchBitTestEntry.entry = m_tree.node[i + 1].current.entry;
362 
363                     rc = writeSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
364                                              m_tree.node[parentLevel].next.entry + j, MAX_COLUMN_BOUNDARY, &matchBitTestEntry );
365 
366                     if ( rc != NO_ERROR )
367                         return rc;
368 
369                     m_tree.node[i].useCount++;
370 
371                     m_tree.node[i].current.entry += j;
372                     entryMap[j] = true;
373                     curOffset = j;
374 
375                     bExitInnerLoop = true;
376                 } // end of if( !entryMap[j] )
377 
378         } // end of if( !bFound
379         else
380         {
381             m_tree.node[i].current.entry += matchPos;
382             m_tree.node[parentLevel].next.entry += matchPos;
383         }
384 
385         m_tree.node[i].next = matchBitTestEntry;
386         parentLevel++;
387     } // end of for( i = 1;
388 
389     curLevel = m_tree.maxLevel - 1;
390 
391     if ( !bDone )
392     {
393         rc = updateListFile( key, width, rid, curLevel, m_tree.node[curLevel].current.group, m_tree.node[curLevel].allocCount, m_tree.node[curLevel].useCount, curOffset, bAddFlag );
394     }
395 
396     return rc;
397 }
398 
399 /***********************************************************
400  * DESCRIPTION:
401  *    Build a a part of empty tree branch
402  * PARAMETERS:
403  *    key - key value
404  *    width - key width
405  *    rid - row id
406  *    startLevel - tree level
407  * RETURN:
408  *    NO_ERROR if success
409  *    error no if fail
410  *    retBitTestEntry - return address pointer
411  ***********************************************************/
buildEmptyTreePart(const uint64_t key,const int width,const RID rid,const int startLevel,const int offset)412 const int IndexTree::buildEmptyTreePart( const uint64_t key, const int width, const RID rid, const int startLevel, const int offset )
413 {
414     int                     rc, loopCount, testbitVal, i, parentLevel;
415     bool                    bSuccess;
416     IdxEmptyListEntry       assignPtrEntry, childPtrEntry;//, listEntry;
417     IdxBitTestEntry         bittestEntry, curEntry;
418     DataBlock               curBlock;
419 
420     if ( startLevel <= 0 || m_tree.maxLevel < 2 )              // the start level must >= 1 and maxLevel >= 2
421         return ERR_IDX_TREE_INVALID_LEVEL;
422 
423     loopCount = (m_tree.maxLevel - 1) > 1 ? m_tree.maxLevel - 1 : 0; //( width/5 ) - 1;
424 
425     rc = assignSegment( ENTRY_1, &assignPtrEntry, 0 );
426 
427     if ( rc != NO_ERROR )
428         return rc;
429 
430     if ( isAddrPtrEmpty( &assignPtrEntry, EMPTY_LIST ) )
431         return ERR_STRUCT_EMPTY;
432 
433     parentLevel = startLevel - 1;
434 
435     // assuming the parent take care of group, bit test value, and type
436     m_tree.node[parentLevel].next.fbo = assignPtrEntry.fbo;
437     m_tree.node[parentLevel].next.sbid = assignPtrEntry.sbid;
438     m_tree.node[parentLevel].next.entry = assignPtrEntry.entry;
439 
440     // assign bit test for rest of levels
441     for ( i = startLevel; i < loopCount; i++ )
442     {
443         // assign another one for child
444         rc = assignSegment( ENTRY_1, &childPtrEntry, i );
445 
446         if ( rc != NO_ERROR )
447             return rc;
448 
449         rc = readSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
450                                 m_tree.node[parentLevel].next.entry, /*width*/MAX_COLUMN_BOUNDARY, &bittestEntry );
451 
452         if ( rc != NO_ERROR )
453             return rc;
454 
455         bSuccess = getTestbitValue( key, width, i, &testbitVal );
456 
457         if ( !bSuccess )
458             return ERR_IDX_TREE_INVALID_LEVEL;
459 
460         setBittestEntry( &bittestEntry, testbitVal, ENTRY_1, childPtrEntry.fbo, childPtrEntry.sbid, childPtrEntry.entry );
461         setSubBlockEntry( &curBlock, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry, MAX_COLUMN_BOUNDARY, &bittestEntry );
462 
463         writeDBFile( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo );
464 
465         setBittestEntry( &curEntry, testbitVal, ENTRY_1, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry );
466         setTreeNode( &m_tree.node[i], i, 1, 1, 0, bittestEntry, curEntry );
467         parentLevel++;
468     }
469 
470     // assign the bit test for the last level
471     // load the last piece
472     rc = updateListFile( key, width, rid, i, ENTRY_1, 1, 1, offset, true );
473 
474     return rc;
475 }
476 
477 
478 /***********************************************************
479  * DESCRIPTION:
480  *    Close index files
481  * PARAMETERS:
482  *    none
483  * RETURN:
484  *    none
485  ***********************************************************/
closeIndex()486 void IndexTree::closeIndex()
487 {
488 
489     if ( m_rootBlock.dirty )
490     {
491         uint64_t lbid0 = 0;
492 #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
493         BRMWrapper::getInstance()->getBrmInfo( m_cbTree.file.oid, 0, lbid0 );
494 #endif
495         writeDBFile( m_cbTree, m_rootBlock.data, lbid0);
496     }
497 
498     if ( Cache::getUseCache() )
499         flushCache();
500 
501     m_fileopTree.closeFile( m_cbTree.file.pFile );
502     m_fileopList.closeFile( m_cbList.file.pFile );
503     m_cbTree.file.pFile = NULL;
504     m_cbList.file.pFile = NULL;
505     clear();
506 }
507 
508 /***********************************************************
509  * DESCRIPTION:
510  *    Create index related files
511  * PARAMETERS:
512  *    treeFid - the index tree file id
513  *    listFid - the index list file id
514  *    useFreeMgrFlag - internal use flag
515  * RETURN:
516  *    NO_ERROR if success
517  *    error no if fail
518  ***********************************************************/
createIndex(const FID treeFid,const FID listFid,const bool useFreeMgrFlag)519 const int IndexTree::createIndex( const FID treeFid, const FID listFid, const bool useFreeMgrFlag )
520 {
521 #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
522     int allocSize;
523 
524     // init
525 //     clear();
526 
527     RETURN_ON_ERROR( createFile( treeFid, DEFAULT_TOTAL_BLOCK/* * 10*/, allocSize ) );
528     RETURN_ON_ERROR( createFile( listFid, DEFAULT_TOTAL_BLOCK/* * 10*/, allocSize ) );
529 #endif
530 
531     // load index files
532 //      RETURN_ON_ERROR( openIndex( treeFid, listFid ) );
533 //      rc = initIndex( treeFid, listFid );
534 //      closeIndex();
535 
536     return initIndex( treeFid, listFid );
537 }
538 
539 /***********************************************************
540  * DESCRIPTION:
541  *    Delete a value from the tree
542  * PARAMETERS:
543  *    key - key value
544  *    width - key width
545  *    rid - row id
546  * RETURN:
547  *    NO_ERROR if success
548  *    error no if fail
549  ***********************************************************/
deleteIndex(const uint64_t key,const int width,const RID rid)550 const int IndexTree::deleteIndex( const uint64_t key, const int width, const RID rid  )
551 {
552     IdxEmptyListEntry listHdrAddr;
553 
554     return processIndex( key, width, rid, listHdrAddr );
555 }
556 
557 
558 /***********************************************************
559  * DESCRIPTION:
560  *    Get test bit values
561  * PARAMETERS:
562  *    key - index key
563  *    width - key width
564  *    curTestNo - test bit iteration no
565  * RETURN:
566  *    True if success, otherwise if out of bound
567  *    bittestVal - test bit value
568  ***********************************************************/
getTestbitValue(const uint64_t key,const int width,const int curTestNo,int * bittestVal)569 const bool IndexTree::getTestbitValue( const uint64_t key, const int width, const int curTestNo, int* bittestVal )
570 {
571     int   shiftPos, maskPos = 0;
572     bool  bSuccess = true;
573 
574     if ( !m_useMultiCol )
575     {
576         *bittestVal = 0;
577         shiftPos = width - ( curTestNo + 1 ) * 5;
578 
579         if ( shiftPos > 0 )
580             *bittestVal = getBitValue( key, shiftPos, BIT_MASK_ARRAY[5] );
581         else
582         {
583             if ( shiftPos >= -4 )
584             {
585                 maskPos = width - curTestNo  * 5 ;
586                 *bittestVal = key & BIT_MASK_ARRAY[maskPos];
587             }
588             else
589                 bSuccess = false;
590         }
591     }
592     else
593         *bittestVal = m_multiColKey.testbitArray[curTestNo];
594 
595     return bSuccess;
596 }
597 
598 
599 /***********************************************************
600  * DESCRIPTION:
601  *    Get the matching entry within the current tree node
602  * PARAMETERS:
603  *    block - block data
604  *    fbo, sbid, entry - pointer address
605  *    width - key width
606  *    allocCount - the total number of allocated entries
607  *    entryMap - the entry availablibility map
608  *    checkEntry - bittest value
609  * RETURN:
610  *    True if found, False otherwise
611  *    checkEntry - if found the ptr got reset
612  ***********************************************************/
getTreeMatchEntry(DataBlock * block,const uint64_t sbid,const uint64_t entry,const int width,const int allocCount,const bool * entryMap,int * matchEntry,IdxBitTestEntry * checkEntry)613 const bool IndexTree::getTreeMatchEntry( DataBlock* block, const uint64_t sbid, const uint64_t entry, const int width,
614         const int allocCount, const bool* entryMap, int* matchEntry, IdxBitTestEntry* checkEntry )
615 {
616     IdxBitTestEntry   curEntry;
617     bool              bFoundFlag = false;
618 
619     for ( int i = 0; i < allocCount; i++ )
620     {
621         getSubBlockEntry( block->data, sbid, entry + i, MAX_COLUMN_BOUNDARY, &curEntry );
622 
623         if ( entryMap[i] && ( curEntry.type == checkEntry->type && curEntry.bitTest == checkEntry->bitTest ) )
624         {
625             *checkEntry = curEntry;
626             *matchEntry = i;
627             bFoundFlag = true;
628             break;
629         }
630     }
631 
632     return bFoundFlag;
633 }
634 
635 /***********************************************************
636  * DESCRIPTION:
637  *    Get tree node summary information
638  * PARAMETERS:
639  *    block - block data
640  *    fbo, sbid, entry - pointer address
641  *    width - key width
642  *    group - entry group
643  *    testbitVal - current bit test value
644  * RETURN:
645  *    NO_ERROR if success
646  *    error no if fail
647  *    allocCount - the total number of allocated entries
648  *    realCount - the total number of real entries
649  *    entryMap - the entry availablibility map
650  ***********************************************************/
getTreeNodeInfo(DataBlock * block,const uint64_t sbid,const uint64_t entry,const int width,const IdxTreeGroupType group,int * allocCount,int * realCount,bool * entryMap)651 const int IndexTree::getTreeNodeInfo( DataBlock* block, const uint64_t sbid, const uint64_t entry, const int width,
652                                       const IdxTreeGroupType group, int* allocCount, int* realCount, bool* entryMap )
653 {
654     IdxBitTestEntry   curEntry;
655     int               rc = NO_ERROR;
656 
657     memset( entryMap, false, ENTRY_PER_SUBBLOCK );
658     *realCount = 0;
659     *allocCount = 0x1 << group;
660 
661     for ( int i = 0; i < *allocCount; i++ )
662     {
663         getSubBlockEntry( block->data, sbid, entry + i, MAX_COLUMN_BOUNDARY, &curEntry );
664 
665         if ( curEntry.type == BIT_TEST || curEntry.type == LEAF_LIST )            // every guy here must have the same type
666         {
667             entryMap[i] = true;
668             *realCount = *realCount + 1;
669         }
670         else if ( curEntry.type == EMPTY_ENTRY )
671             entryMap[i] = false;
672         else
673             rc = ERR_IDX_TREE_INVALID_TYPE;
674 
675         if ( rc != NO_ERROR )
676             break;
677     }
678 
679     return rc;
680 }
681 
682 /***********************************************************
683  * DESCRIPTION:
684  *    Check index entry address pointer is empty or not
685  * PARAMETERS:
686  *    pStruct - index entry pointer
687  *    entryType - the entry type
688  * RETURN:
689  *    True if empty, False otherwise
690  ***********************************************************/
isAddrPtrEmpty(void * pStruct,const IdxTreeEntryType entryType) const691 const bool IndexTree::isAddrPtrEmpty( void* pStruct, const IdxTreeEntryType entryType ) const
692 {
693     bool                    bStatus;
694     IdxBitmapPointerEntry*  pBitmap;
695     IdxBitTestEntry*        pBittest;
696     IdxEmptyListEntry*      pEmptyList;
697 
698 
699     switch ( entryType )
700     {
701         case BITMAP_PTR/*EMPTY_PTR*/ :  // this is the case for bitmap pointer address
702             pBitmap = (IdxBitmapPointerEntry*) pStruct;
703             bStatus = /*!pBitmap->oid &&*/ !pBitmap->fbo && !pBitmap->sbid && !pBitmap->entry;
704             break;
705 
706         case BIT_TEST :   // this is the case for bittest pointer address
707             pBittest = (IdxBitTestEntry*) pStruct;
708             bStatus = /*!pBittest->oid &&*/ !pBittest->fbo && !pBittest->sbid && !pBittest->entry;
709             break;
710 
711         case EMPTY_LIST :   // this is the case for bittest pointer address
712             pEmptyList = (IdxEmptyListEntry*) pStruct;
713             bStatus = !pEmptyList->fbo && !pEmptyList->sbid && !pEmptyList->entry;
714             break;
715 
716         default  :
717             bStatus = true;
718     }
719 
720     return bStatus;
721 }
722 
initIndex(const FID treeFid,const FID listFid)723 const int IndexTree::initIndex( const FID treeFid, const FID listFid )
724 {
725     int            rc = NO_ERROR;
726     long           numOfBlock;
727     unsigned char  writeBuf[BYTE_PER_BLOCK];
728 
729     bool oldUseVb = BRMWrapper::getUseVb();
730     BRMWrapper::setUseVb( false );
731 
732     clear();
733     RETURN_ON_ERROR( openIndex( treeFid, listFid ) );
734 
735     memset( writeBuf, 0, BYTE_PER_BLOCK );
736     numOfBlock = getFileSize( m_cbTree.file.pFile ) / BYTE_PER_BLOCK;
737 
738     for ( int i = 0; i < numOfBlock; i++ )
739         fwrite( writeBuf, sizeof( writeBuf ), 1, m_cbTree.file.pFile );
740 
741     numOfBlock = getFileSize( m_cbList.file.pFile ) / BYTE_PER_BLOCK;
742 
743     for ( int i = 0; i < numOfBlock; i++ )
744         fwrite( writeBuf, sizeof( writeBuf ), 1, m_cbList.file.pFile );
745 
746     // very weird, have to close before we can call free mgr init
747     closeIndex();
748     RETURN_ON_ERROR( openIndex( treeFid, listFid ) );
749 
750     rc = m_freeMgr.init( m_cbTree, TREE );
751 
752     if ( rc == NO_ERROR )
753         rc = m_freeMgr.init( m_cbList, LIST );
754 
755     closeIndex();
756 
757     BRMWrapper::setUseVb( oldUseVb );
758 
759     if ( isDebug( DEBUG_1 ) )
760         printf( "\nEnd of the init for oid %d\n", m_cbTree.file.oid );
761 
762     return rc;
763 }
764 
765 /***********************************************************
766  * DESCRIPTION:
767  *    Move tree entries
768  * PARAMETERS:
769  *    fbo, sbid, entry - pointer address
770  *    width - key width
771  *    allocCount - the total number of allocated entries
772  *    entryMap - the entry availablibility map
773  * RETURN:
774  *    NO_ERROR if success
775  *    error no if fail
776  ***********************************************************/
moveEntry(const uint64_t oldFbo,const uint64_t oldSbid,const uint64_t oldEntry,const int width,const uint64_t newFbo,const uint64_t newSbid,const uint64_t newEntry,const int newGroup,const int allocCount,bool * entryMap,int * moveCount,const int newAllocCount)777 const int IndexTree::moveEntry( const uint64_t oldFbo, const uint64_t oldSbid, const uint64_t oldEntry, const int width, const uint64_t newFbo,
778                                 const uint64_t newSbid, const uint64_t newEntry, const int newGroup, const int allocCount, bool* entryMap, int* moveCount, const int newAllocCount )
779 {
780     int               rc, i;
781     DataBlock         oldBlock, newBlock;
782     IdxBitTestEntry   curEntry, blankEntry;
783 
784     rc = readSubBlockEntry( m_cbTree, &oldBlock, oldFbo, oldSbid, oldEntry, /*width*/MAX_COLUMN_BOUNDARY, &curEntry );
785 
786     if ( rc != NO_ERROR )
787         return rc;
788 
789     rc = readSubBlockEntry( m_cbTree, &newBlock, newFbo, newSbid, newEntry, /*width*/MAX_COLUMN_BOUNDARY, &curEntry );
790 
791     if ( rc != NO_ERROR )
792         return rc;
793 
794     setBlankEntry( &blankEntry );
795 
796     for ( i = 0; i < newAllocCount; i++ )
797         setSubBlockEntry( newBlock.data, newSbid, newEntry + i, MAX_COLUMN_BOUNDARY, &blankEntry );
798 
799     *moveCount = 0;
800 
801     for ( i = 0; i < allocCount; i++ )
802     {
803         getSubBlockEntry( oldBlock.data, oldSbid, oldEntry + i, MAX_COLUMN_BOUNDARY, &curEntry );
804 
805         if ( entryMap[i] )
806         {
807             curEntry.group = newGroup;
808             setSubBlockEntry( newBlock.data, newSbid, newEntry + *moveCount, MAX_COLUMN_BOUNDARY, &curEntry );
809             *moveCount = *moveCount + 1;
810 
811         }
812 
813         setBlankEntry( &curEntry );
814 
815         if ( newFbo != oldFbo )
816             setSubBlockEntry( oldBlock.data, oldSbid, oldEntry + i, MAX_COLUMN_BOUNDARY, &curEntry );
817         else
818             setSubBlockEntry( newBlock.data, oldSbid, oldEntry + i, MAX_COLUMN_BOUNDARY, &curEntry );
819     }
820 
821     rc = writeDBFile( m_cbTree, &newBlock, newFbo );
822 
823     if ( rc != NO_ERROR )
824         return rc;
825 
826     if ( newFbo != oldFbo )
827         rc = writeDBFile( m_cbTree, &oldBlock, oldFbo );
828 
829     // reset map
830     memset( entryMap, false, ENTRY_PER_SUBBLOCK );
831 
832     for ( i = 0; i < *moveCount; i++ )
833         entryMap[i] = true;
834 
835     return rc;
836 }
837 
838 /***********************************************************
839  * DESCRIPTION:
840  *    Open index related files
841  * PARAMETERS:
842  *    treeFid - the index tree file id
843  *    listFid - the index list file id
844  * RETURN:
845  *    NO_ERROR if success
846  *    error no if fail
847  ***********************************************************/
openIndex(const FID treeFid,const FID listFid)848 const int IndexTree::openIndex( const FID treeFid, const FID listFid  )
849 {
850     int rc = NO_ERROR;
851     clear();
852 
853     // load index files
854 #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
855     m_cbTree.file.pFile = m_fileopTree.openFile( treeFid );
856 #endif
857 
858     if ( m_cbTree.file.pFile == NULL )
859         return ERR_FILE_OPEN;
860 
861 #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
862     m_cbList.file.pFile = m_fileopList.openFile( listFid );
863 #endif
864 
865     if ( m_cbList.file.pFile == NULL )
866     {
867         m_fileopTree.closeFile( m_cbTree.file.pFile );       // close the one just open
868         return ERR_FILE_OPEN;
869     }
870 
871     m_cbTree.file.oid = treeFid;
872     m_cbList.file.oid = listFid;
873 
874     uint64_t lbid0 = 0;
875 #ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
876     rc = BRMWrapper::getInstance()->getBrmInfo( m_cbTree.file.oid, 0, lbid0 );
877 #endif
878 
879     if ( rc != NO_ERROR )
880     {
881         if ( isDebug( DEBUG_1 ) )
882         {
883             printf( "\nFor oid : %d block zero is %ld", m_cbTree.file.oid, (long)lbid0 );
884             printf( "\nIn open index, have problem in get brmInfo, rc=%d", rc );
885         }
886 
887         return rc;
888     }
889 
890     rc = readDBFile( m_cbTree, m_rootBlock.data, lbid0 );
891 
892     return rc;
893 }
894 
895 /***********************************************************
896  * DESCRIPTION:
897  *    Process index, including search or delete
898  * PARAMETERS:
899  *    key - key value
900  *    width - key width
901  *    rid - row id
902  *    listHdrAddr - list header address
903  *    bDelete - delete operation flag
904  * RETURN:
905  *    NO_ERROR if success
906  *    error no if fail
907  ***********************************************************/
processIndex(const uint64_t key,const int width,const RID rid,IdxEmptyListEntry & listHdrAddr,const bool bDelete)908 const int IndexTree::processIndex( const uint64_t key, const int width, const RID rid, IdxEmptyListEntry& listHdrAddr, const bool bDelete  )
909 {
910     int                     loopCount, testbitVal, i, allocCount, realCount, matchPos, curFbo, curSbid, curEntry;
911     bool                    bSuccess;
912     IdxEmptyListEntry       listEntry;
913     IdxBitTestEntry         bittestEntry, matchBitTestEntry;
914     DataBlock               curBlock;
915     bool                    bFound, entryMap[ENTRY_PER_SUBBLOCK];
916 
917     int                     rootTestbitVal, rc = NO_ERROR;
918     IdxBitmapPointerEntry   bitmapEntry;
919 
920     getTestbitValue( key, width, 0, &rootTestbitVal );
921     getSubBlockEntry( m_rootBlock.data, 1, rootTestbitVal, MAX_COLUMN_BOUNDARY, &bitmapEntry );
922 
923     if ( isAddrPtrEmpty( &bitmapEntry, /*EMPTY_PTR*/BITMAP_PTR ) )
924         return bDelete ? ERR_IDX_LIST_INVALID_DELETE : NOT_FOUND ;
925 
926     // get the rootbittestEntry level bitmapPointerMap
927     curFbo = bitmapEntry.fbo;
928     curSbid = bitmapEntry.sbid;
929     curEntry = bitmapEntry.entry;
930 
931     loopCount = width / 5 + 1;
932 
933     for ( i = 1; i < loopCount; i++ )
934     {
935         // load the block
936         rc = readSubBlockEntry( m_cbTree, &curBlock, curFbo, curSbid, curEntry, /*width*/MAX_COLUMN_BOUNDARY, &bittestEntry );
937 
938         if ( rc != NO_ERROR )
939             return rc;
940 
941         if ( isDebug( DEBUG_3 ) )
942         {
943             printf( "\nIn processIndex, level %d", i );
944             printSubBlock( curFbo, curSbid );
945         }
946 
947         rc = getTreeNodeInfo( &curBlock, curSbid, curEntry, width, (IdxTreeGroupType)bittestEntry.group, &allocCount, &realCount, entryMap );
948 
949         if ( rc != NO_ERROR )
950             return rc;
951 
952         matchBitTestEntry = bittestEntry;   // assign to the value of the first entry
953         bSuccess = getTestbitValue( key, width, i, &testbitVal );
954 
955         matchBitTestEntry.bitTest = testbitVal;
956         bFound = getTreeMatchEntry( &curBlock, curSbid, curEntry, width, allocCount, entryMap, &matchPos, &matchBitTestEntry );
957 
958         if ( bFound )   // this test bit exists at the current level
959         {
960             if ( i == loopCount - 1 )
961             {
962 //               if( loopCount == 2 )   // because of bitmap, it requires a special treatment
963                 curEntry += matchPos;
964                 break;
965             }
966         }
967         else
968             return NOT_FOUND;
969 
970         getSubBlockEntry( &curBlock, curSbid, curEntry + matchPos, MAX_COLUMN_BOUNDARY, &matchBitTestEntry );
971 
972         curFbo = matchBitTestEntry.fbo;
973         curSbid = matchBitTestEntry.sbid;
974         curEntry = matchBitTestEntry.entry;
975 
976     } // end of for( i = 0;
977 
978     // here's the last level
979     // load the last piece
980     rc = readSubBlockEntry( m_cbTree, &curBlock, curFbo, curSbid, curEntry /*+ matchPos*/, MAX_COLUMN_BOUNDARY, &bittestEntry );
981 
982     if ( rc != NO_ERROR )
983         return rc;
984 
985     listEntry.fbo = bittestEntry.fbo;
986     listEntry.sbid = bittestEntry.sbid;
987     listEntry.entry = bittestEntry.entry;
988 
989     if ( bDelete )
990     {
991         rc = m_listMgr.deleteIndexList( m_cbList, rid, key, &listEntry );
992 
993         if ( rc != NO_ERROR )
994             return rc;
995 
996         bSuccess = getTestbitValue( key, width, loopCount - 1, &testbitVal );
997         setBittestEntry( &bittestEntry, testbitVal, bittestEntry.group, listEntry.fbo, listEntry.sbid, listEntry.entry, LEAF_LIST );
998         setSubBlockEntry( &curBlock, curSbid, curEntry, MAX_COLUMN_BOUNDARY, &bittestEntry );
999 
1000         rc = writeDBFile( m_cbTree, &curBlock, curFbo );
1001 
1002     }
1003     else
1004         listHdrAddr = listEntry;
1005 
1006     return rc;
1007 }
1008 
1009 
1010 /***********************************************************
1011  * DESCRIPTION:
1012  *    Print a sub block
1013  * PARAMETERS:
1014  *    fbo - file block offset
1015  *    sbid - sub block id
1016  * RETURN:
1017  *    none
1018  ***********************************************************/
printSubBlock(const int fbo,const int sbid,const bool bNoZero)1019 void IndexTree::printSubBlock( const int fbo, const int sbid, const bool bNoZero )
1020 {
1021     DataBlock         curBlock;
1022 
1023     readDBFile( m_cbTree, &curBlock, fbo );
1024     printf( "\n lbid=%2d sbid=%2d", fbo, sbid );
1025     printMemSubBlock( &curBlock, sbid );
1026 }
1027 
printMemSubBlock(DataBlock * curBlock,const int sbid,const bool bNoZero)1028 void IndexTree::printMemSubBlock( DataBlock* curBlock, const int sbid, const bool bNoZero )
1029 {
1030     int off;
1031     unsigned char*    curPos;
1032     IdxBitTestEntry   curEntry, testZero;
1033 
1034     setBlankEntry( &testZero );
1035     curPos = curBlock->data + BYTE_PER_SUBBLOCK * sbid;
1036     printf( "\n========================" );
1037 
1038     for ( int i = 0; i < ENTRY_PER_SUBBLOCK; i++ )
1039     {
1040         memcpy( &curEntry, curPos, MAX_COLUMN_BOUNDARY );
1041         off = memcmp( &testZero, &curEntry, MAX_COLUMN_BOUNDARY );
1042         printf( "\n Entry %2d : ", i );
1043 
1044         for ( int j = 0; j < MAX_COLUMN_BOUNDARY; j++ )
1045             printf( " %2X", *(curPos + j) );
1046 
1047         printf( " fbo=%2d sbid=%2d entry=%2d group=%d bit=%2d type=%2d", (int)curEntry.fbo, (int)curEntry.sbid, (int)curEntry.entry, (int)curEntry.group, (int)curEntry.bitTest, (int)curEntry.type );
1048 
1049         curPos += MAX_COLUMN_BOUNDARY;
1050     }
1051 
1052     printf( "\n" );
1053 }
1054 
1055 /***********************************************************
1056  * DESCRIPTION:
1057  *    Assign segment from free manager
1058  * PARAMETERS:
1059  *    segmentType - group type
1060  *    assignPtr - the assigned ptr
1061  *    no - internal debug use flag
1062  * RETURN:
1063  *    NO_ERROR if success
1064  *    error no if fail
1065  ***********************************************************/
releaseSegment(int segmentType,IdxEmptyListEntry * myPtr)1066 const int IndexTree::releaseSegment( int segmentType, IdxEmptyListEntry* myPtr )
1067 {
1068     int rc = NO_ERROR;
1069 
1070     m_rootBlock.dirty = true;
1071 
1072     if ( m_useFreeMgr )
1073     {
1074         if ( isDebug( DEBUG_3 ) )
1075             printf( "\n----------Release the pointer, entry segment=%d fbo=%d sbid=%d entry=%d", segmentType, (int)myPtr->fbo, (int)myPtr->sbid, (int)myPtr->entry );
1076 
1077         rc = m_freeMgr.releaseSegment( m_cbTree, &m_rootBlock, TREE, (IdxTreeGroupType) segmentType, myPtr/*, TREE */);
1078 
1079         if ( isDebug( DEBUG_3 ) )
1080             printf("\nReleased" );
1081     }
1082 
1083     return rc;
1084 }
1085 
resetIndexFile(const FID treeFid,const FID listFid)1086 const int IndexTree::resetIndexFile( const FID treeFid, const FID listFid )
1087 {
1088     /*      long numOfBlock;
1089           unsigned char  writeBuf[BYTE_PER_BLOCK];
1090 
1091           memset( writeBuf, 0, BYTE_PER_BLOCK );
1092           numOfBlock = getFileSize( m_cbTree.file.pFile )/BYTE_PER_BLOCK;
1093           for( int i = 0; i < numOfBlock; i++ )
1094              fwrite( writeBuf, sizeof( writeBuf ), 1, m_cbTree.file.pFile );
1095 
1096           numOfBlock = getFileSize( m_cbList.file.pFile )/BYTE_PER_BLOCK;
1097           for( int i = 0; i < numOfBlock; i++ )
1098              fwrite( writeBuf, sizeof( writeBuf ), 1, m_cbList.file.pFile );
1099     */
1100     return initIndex( treeFid, listFid );
1101 }
1102 
1103 /***********************************************************
1104  * DESCRIPTION:
1105  *    Calculate bit test array for multi column index
1106  * PARAMETERS:
1107  *    none
1108  * RETURN:
1109  *    NO_ERROR if success
1110  *    error no if fail
1111  ***********************************************************/
calculateBittestArray()1112 const int IndexTree::calculateBittestArray()
1113 {
1114     if ( m_multiColKey.totalBit <= 0 )
1115         return ERR_INVALID_PARAM;
1116 
1117     m_multiColKey.maxLevel = m_multiColKey.totalBit / 5 + 1;
1118 
1119     if ( m_multiColKey.maxLevel > IDX_MAX_MULTI_COL_IDX_LEVEL )
1120         return ERR_VALUE_OUTOFRANGE;
1121 
1122     for ( int i = 0; i < m_multiColKey.maxLevel - 1; i++ )
1123     {
1124         m_multiColKey.curBitset = ( m_multiColKey.bitSet & m_multiColKey.curMask ) >> ( IDX_MAX_MULTI_COL_BIT - ( i + 1 ) * 5 );
1125         m_multiColKey.testbitArray[i] = m_multiColKey.curBitset.to_ulong();
1126         m_multiColKey.curMask = m_multiColKey.curMask >> 5;
1127     }
1128 
1129     m_multiColKey.curBitset = ( m_multiColKey.bitSet & m_multiColKey.curMask ) >> ( IDX_MAX_MULTI_COL_BIT - m_multiColKey.totalBit );
1130     m_multiColKey.testbitArray[m_multiColKey.maxLevel - 1] = m_multiColKey.curBitset.to_ulong();
1131     return NO_ERROR;
1132 }
1133 
1134 /***********************************************************
1135  * DESCRIPTION:
1136  *    Setup bit test array for multi column index
1137  * PARAMETERS:
1138  *    keyArray - index key array
1139  *    totalByte - total byte in the key
1140  * RETURN:
1141  *    NO_ERROR if success
1142  *    error no if fail
1143  ***********************************************************/
setBitsetColumn(void * val,const int pos,const int width,const ColType colType)1144 const int IndexTree::setBitsetColumn( void* val, const int pos, const int width, const ColType colType )
1145 {
1146     int copyLen = width / 8;
1147 
1148     switch ( colType )
1149     {
1150         // No body is using float or double for indexing
1151         /*         case WriteEngine::WR_FLOAT :  m_multiColKey.curBitset = *((float*) val);
1152                                                break;
1153                  case WriteEngine::WR_DOUBLE : m_multiColKey.curBitset = *((double*) val);
1154                                                break;
1155         */
1156         case WriteEngine::WR_CHAR :
1157             m_multiColKey.curBitset.reset();
1158 
1159             for ( int i = 0; i < width / 8; i++ )
1160             {
1161                 uint64_t curChar = ((char*)val)[i];
1162                 m_multiColKey.curBitset = m_multiColKey.curBitset << 8;
1163                 m_multiColKey.curBitset |= curChar;
1164             }
1165 
1166             memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (char*) val, copyLen );
1167             break;
1168 
1169         case WriteEngine::WR_SHORT :
1170             m_multiColKey.curBitset = *((short*) val);
1171             memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (short*) val, copyLen );
1172             break;
1173 
1174         case WriteEngine::WR_BYTE :
1175             m_multiColKey.curBitset = *((char*) val);
1176             memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (char*) val, copyLen );
1177             break;
1178 
1179         case WriteEngine::WR_LONGLONG:
1180             m_multiColKey.curBitset = *((long long*) val);
1181             memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (long long*) val, copyLen );
1182             break;
1183 
1184         case WriteEngine::WR_INT :
1185         case WriteEngine::WR_MEDINT :
1186         default  :
1187             memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (int*) val, copyLen );
1188             m_multiColKey.curBitset = *((int*) val);
1189             break;
1190     }
1191 
1192     m_multiColKey.totalBit += width;
1193     m_multiColKey.curBitset = m_multiColKey.curBitset << ( IDX_MAX_MULTI_COL_BIT - m_multiColKey.totalBit );
1194     m_multiColKey.bitSet |= m_multiColKey.curBitset;
1195     return NO_ERROR;
1196 }
1197 
1198 /***********************************************************
1199  * DESCRIPTION:
1200  *    Set bit test entry
1201  * PARAMETERS:
1202  *    bittestEntry - the bit test entry
1203  *    testbitVal - current bit test value
1204  *    group - entry group
1205  *    fbo, sbid, entry - pointer address
1206  * RETURN:
1207  *    none
1208  ***********************************************************/
setBittestEntry(IdxBitTestEntry * bittestEntry,const uint64_t testbitVal,const uint64_t group,const uint64_t fbo,const uint64_t sbid,const uint64_t entry,const uint64_t entryType) const1209 void IndexTree::setBittestEntry( IdxBitTestEntry* bittestEntry, const uint64_t testbitVal, const uint64_t group, const uint64_t fbo, const uint64_t sbid, const uint64_t entry, const uint64_t entryType ) const
1210 {
1211     bittestEntry->type = entryType;
1212     bittestEntry->bitTest = testbitVal;
1213     bittestEntry->group = group;
1214     bittestEntry->bitCompare = BIT_5;
1215     bittestEntry->spare = 0;
1216 
1217     bittestEntry->fbo = fbo;
1218     bittestEntry->sbid = sbid;
1219     bittestEntry->entry = entry;
1220 }
1221 
1222 /***********************************************************
1223  * DESCRIPTION:
1224  *    Set empty list entry for free manager
1225  * PARAMETERS:
1226  *    bittestEntry - the bit test entry
1227  *    testbitVal - current bit test value
1228  *    group - entry group
1229  *    fbo, sbid, entry - pointer address
1230  * RETURN:
1231  *    none
1232  ***********************************************************/
1233 // todo: need test case
setEmptyListEntry(IdxEmptyListEntry * myEntry,const uint64_t group,const uint64_t fbo,const uint64_t sbid,const uint64_t entry) const1234 void IndexTree::setEmptyListEntry( IdxEmptyListEntry* myEntry, const uint64_t group, const uint64_t fbo, const uint64_t sbid, const uint64_t entry ) const
1235 {
1236     myEntry->type = EMPTY_PTR;
1237     myEntry->group = group;
1238     myEntry->spare = 0;
1239     myEntry->spare2 = 0;
1240     myEntry->fbo = fbo;
1241     myEntry->sbid = sbid;
1242     myEntry->entry = entry;
1243 }
1244 
1245 /***********************************************************
1246  * DESCRIPTION:
1247  *    Set the tree header node
1248  * PARAMETERS:
1249  *    myTree - tree pointer
1250  *    key - index key
1251  *    width - key width
1252  *    rid - ROW ID
1253  *    testbitVal - bit test value at root level
1254  *    bitmapEntry - bitmap entry
1255  * RETURN:
1256  *    none
1257  ***********************************************************/
setTreeHeader(IdxTree * myTree,const uint64_t key,const RID rid,const int width,const int testbitVal,const IdxBitmapPointerEntry bitmapEntry)1258 void IndexTree::setTreeHeader( IdxTree* myTree, const uint64_t key, const RID rid, const int width,
1259                                const int testbitVal, const IdxBitmapPointerEntry bitmapEntry )
1260 {
1261     IdxBitTestEntry nextEntry, curEntry;
1262 
1263     myTree->width = width;
1264     myTree->key = key;
1265     myTree->rid = rid;
1266     myTree->maxLevel = (width / 5) + 1;
1267 
1268     setBlankEntry( &nextEntry );
1269     setBlankEntry( &curEntry );
1270 
1271 //      myEntry.bitTest = testbitVal;
1272     nextEntry.fbo = bitmapEntry.fbo;
1273     nextEntry.sbid = bitmapEntry.sbid;
1274     nextEntry.entry = bitmapEntry.entry;
1275     nextEntry.type = BIT_TEST;
1276 
1277 //      nextEntry.group = ENTRY_32;
1278 
1279     curEntry.fbo = 0;
1280     curEntry.sbid = IDX_BITMAP_SUBBLOCK_NO;
1281     curEntry.entry = testbitVal;
1282     curEntry.type = BITMAP_PTR;
1283     curEntry.group = ENTRY_32;
1284     curEntry.bitTest = testbitVal;
1285 
1286 
1287     // at this point useCount not known
1288     setTreeNode( &myTree->node[0], 0, ENTRY_PER_SUBBLOCK, 0, testbitVal, nextEntry, curEntry );
1289 }
1290 
1291 /***********************************************************
1292  * DESCRIPTION:
1293  *    Set the tree node
1294  * PARAMETERS:
1295  *    myNode - node pointer
1296  *    level - current tree level
1297  *    allocCount - allocated count
1298  *    useCount - used count
1299  *    offset - entry offset
1300  *    nextEntry - next entry
1301  *    curEntry - current entry
1302  * RETURN:
1303  *    none
1304  ***********************************************************/
setTreeNode(IdxTreeNode * myNode,const int level,const int allocCount,const int useCount,const int offset,const IdxBitTestEntry nextEntry,const IdxBitTestEntry curEntry)1305 void IndexTree::setTreeNode( IdxTreeNode* myNode, const int level, const int allocCount, const int useCount,
1306                              const int offset, const IdxBitTestEntry nextEntry, const IdxBitTestEntry curEntry )
1307 {
1308     myNode->level = level;
1309     myNode->allocCount = allocCount;
1310     myNode->useCount = useCount;
1311     myNode->offset = offset;
1312     myNode->next = nextEntry;
1313     myNode->current = curEntry;
1314     myNode->used = true;
1315 }
1316 
1317 
isTreeEmpty()1318 const bool IndexTree::isTreeEmpty()
1319 {
1320     bool                    bEmpty = true;
1321     IdxBitmapPointerEntry   curBitmapPointer, emptyPointer;
1322 
1323     memset( &emptyPointer, 0, MAX_COLUMN_BOUNDARY );
1324 
1325     for ( int i = 0; i < 32; i++ )
1326     {
1327         getSubBlockEntry( m_rootBlock.data, IDX_BITMAP_SUBBLOCK_NO, i, MAX_COLUMN_BOUNDARY, &curBitmapPointer );
1328 
1329         if ( memcmp( &curBitmapPointer, &emptyPointer, MAX_COLUMN_BOUNDARY ) )
1330         {
1331             bEmpty = false;
1332             break;
1333         }
1334     }
1335 
1336 //      printMemSubBlock( &m_rootBlock, IDX_BITMAP_SUBBLOCK_NO );
1337     return bEmpty;
1338 }
1339 
1340 /***********************************************************
1341  * DESCRIPTION:
1342  *    Allocate Row ID
1343  * PARAMETERS:
1344  *    tableFid - the file id for table bitmap file
1345  *    totalRow - the total number of rows need to be allocated
1346  * RETURN:
1347  *    NO_ERROR if success
1348  *    rowIdArray - allocation of the row id left here
1349  ***********************************************************/
updateIndex(const uint64_t key,const int width,const RID rid)1350 const int IndexTree::updateIndex( const uint64_t key, const int width, const RID rid )
1351 {
1352     int                     rootTestbitVal, rc = NO_ERROR;
1353     IdxBitmapPointerEntry   curBitmapPointer;
1354 
1355     clearTree( &m_tree );
1356 
1357     getTestbitValue( key, width, 0, &rootTestbitVal );
1358     getSubBlockEntry( m_rootBlock.data, IDX_BITMAP_SUBBLOCK_NO, rootTestbitVal, MAX_COLUMN_BOUNDARY, &curBitmapPointer );
1359 
1360     setTreeHeader( &m_tree, key, rid, width, rootTestbitVal, curBitmapPointer );
1361 
1362     if ( m_tree.maxLevel > IDX_MAX_TREE_LEVEL )
1363         return ERR_VALUE_OUTOFRANGE;
1364 
1365     if ( isAddrPtrEmpty( &curBitmapPointer, (IdxTreeEntryType) curBitmapPointer.type ) )
1366         rc = buildEmptyIndexTreeBranch( key, width, rid, rootTestbitVal );
1367     else          // at least we have the root level pointer
1368         rc = buildExistIndexTreeBranch( key, width, rid, rootTestbitVal, curBitmapPointer );
1369 
1370     return rc;
1371 }
1372 
1373 /***********************************************************
1374  * DESCRIPTION:
1375  *    Dummy list addr generator
1376  * PARAMETERS:
1377  *    key - index key
1378  *    width - key width
1379  *    rid - ROW ID
1380  *    myEntry - return entry with addr
1381  *    no - sequence no
1382  * RETURN:
1383  *    NO_ERROR if success
1384  *    error no if fail
1385  ***********************************************************/
updateIndexList(const uint64_t key,const int width,const RID rid,IdxEmptyListEntry * myEntry,const int no,const bool addFlag)1386 const int IndexTree::updateIndexList( const uint64_t key, const int width, const RID rid, IdxEmptyListEntry* myEntry, const int no, const bool addFlag )
1387 {
1388     int rc = NO_ERROR;
1389 
1390     if ( m_useListMgr )
1391     {
1392         // doing something here
1393         if ( !addFlag )  // update list
1394         {
1395             if ( m_useMultiRid )
1396                 rc = m_listMgr.updateIndexList( m_cbList, m_multiRid, key, myEntry );
1397             else
1398                 rc = m_listMgr.updateIndexList( m_cbList, rid, key, myEntry );
1399         }
1400         else   // add list
1401         {
1402             if ( m_useMultiRid )
1403                 rc = m_listMgr.addIndexListHdr( m_cbList, m_multiRid, key, myEntry );
1404             else
1405                 rc = m_listMgr.addIndexListHdr( m_cbList, rid, key, myEntry );
1406         }
1407 
1408     }
1409     else
1410     {
1411         myEntry->fbo = 3;
1412         myEntry->sbid = 3;
1413         myEntry->entry = 3 + no;
1414     }
1415 
1416     return rc;
1417 }
1418 
1419 /***********************************************************
1420  * DESCRIPTION:
1421  *    Update the entry in index list file
1422  * PARAMETERS:
1423  *    key - index key
1424  *    width - key width
1425  *    rid - ROW ID
1426  *    curLevel - current tree level
1427  *    group - current group
1428  *    allocCount - allocated count
1429  *    useCount - used count
1430  *    offset - entry offset
1431  * RETURN:
1432  *    NO_ERROR if success
1433  *    error no if fail
1434  ***********************************************************/
updateListFile(const uint64_t key,const int width,const RID rid,const int curLevel,const uint64_t group,const int allocCount,const int useCount,const int offset,const bool addFlag)1435 const int IndexTree::updateListFile( const uint64_t key, const int width, const RID rid, const int curLevel, const uint64_t group, const int allocCount, const int useCount, const int offset, const bool addFlag )
1436 {
1437     int                  rc, testbitVal, parentLevel = curLevel - 1;
1438     IdxEmptyListEntry    listEntry;
1439     IdxBitTestEntry      bittestEntry, curEntry;
1440     bool                 bSuccess;
1441     DataBlock            curBlock;
1442 
1443     rc = readSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid,
1444                             m_tree.node[parentLevel].next.entry + offset, MAX_COLUMN_BOUNDARY, &bittestEntry );
1445 
1446     if ( rc != NO_ERROR )
1447         return rc;
1448 
1449     if ( !addFlag )
1450     {
1451         listEntry.fbo = bittestEntry.fbo;
1452         listEntry.sbid = bittestEntry.sbid;
1453         listEntry.entry = bittestEntry.entry;
1454     }
1455 
1456     rc = updateIndexList( key, width, rid, &listEntry, curLevel, addFlag );
1457 
1458     if ( rc != NO_ERROR )
1459         return rc;
1460 
1461     bSuccess = getTestbitValue( key, width, curLevel, &testbitVal );
1462     setBittestEntry( &bittestEntry, testbitVal, group, listEntry.fbo, listEntry.sbid, listEntry.entry, LEAF_LIST );
1463 
1464     rc = writeSubBlockEntry( m_cbTree, &curBlock, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry + offset, MAX_COLUMN_BOUNDARY, &bittestEntry );
1465 
1466     setBittestEntry( &curEntry, testbitVal, group, m_tree.node[parentLevel].next.fbo, m_tree.node[parentLevel].next.sbid, m_tree.node[parentLevel].next.entry, LEAF_LIST );
1467     setTreeNode( &m_tree.node[curLevel], curLevel, allocCount, useCount, offset, bittestEntry, curEntry );
1468 
1469     return rc;
1470 }
1471 
1472 } //end of namespace
1473 
1474