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