![]() |
|
|
Bdb packages | Design docs | Source docs | Guidelines | Recent releases |
|
Main Page Modules Namespace List Class Hierarchy Alphabetical List Compound List File List Compound Members File Members /BdbBitMap/BdbBMIndexQueryAPI.cc
Go to the documentation of this file.00001 // ------------------------------------------------------------------------------ 00002 // File: 00003 // BdbBMIndexQueryAPI.cc 00004 // 00005 // Description: 00006 // Transient abstract class implmeenting an API to the BitMap index structure. 00007 // The API is used to access events using index structure. The access 00008 // is read-only via (subset of) SQL query. 00009 // 00010 // Environment: 00011 // Software developed for the BaBar Detector at the SLAC B-Factory 00012 // 00013 // Author List: 00014 // Jacek Becla, Igor Gaponenko Original Authors 00015 // 00016 // Copyright Information: 00017 // Copyright (C) 1997-98 Stanford Linear Accelerator Center 00018 // 00019 // ------------------------------------------------------------------------------ 00020 00021 // ------------------------- 00022 // -- This Class's Header -- 00023 // ------------------------- 00024 00025 #ifndef BDBBMINDEXQUERYAPI_HH 00026 #include "BdbBitMap/BdbBMIndexQueryAPI.hh" 00027 #endif 00028 00029 // --------------------------------- 00030 // -- Collaborating Class Headers -- 00031 // --------------------------------- 00032 00033 #include "BdbApplication/BdbApplication.hh" 00034 00035 #include "BdbAccess/BdbDbTreeSingleton.hh" 00036 00037 #include "BdbClustering/BdbEvsHdrClusteringHint.hh" 00038 #include "BdbClustering/BdbSimpleClusteringHint.hh" 00039 00040 #include "BdbTrees/BdbDbRegistrator.hh" 00041 00042 #include "AbsEvent/AbsEvent.hh" 00043 00044 #include "BdbEvent/BdbEvent.hh" 00045 00046 #include "BdbEventStore/BdbCollection.hh" 00047 #include "BdbEventStore/BdbEventStore.hh" 00048 #include "BdbEventStore/BdbTreeNodeCollectionIterator.hh" 00049 #include "BdbEventStore/BdbEventStoreIterator.hh" 00050 #include "BdbEventStore/BdbTreeCollection.hh" 00051 #include "BdbEventStore/BdbVectorCollection.hh" 00052 00053 #include "BdbIndexing/BdbIndexingErrors.hh" 00054 #include "BdbIndexing/BdbAbsIndexAPI.hh" 00055 #include "BdbIndexing/BdbQuery.hh" 00056 #include "BdbIndexing/BdbQueryDescr.hh" 00057 #include "BdbIndexing/BdbQueryEstimation.hh" 00058 00059 #include "BdbBitMap/BdbBMDimension.hh" 00060 #include "BdbBitMap/BdbBMBin.hh" 00061 00062 // ----------------------- 00063 // -- Local definitions -- 00064 // ----------------------- 00065 00066 static const d_ULong BITS_31_30 = 0x80000000 | 0x40000000 ; 00067 static const d_ULong BITS_31 = 0x80000000 ; 00068 static const d_ULong BITS_30 = 0x40000000 ; 00069 static const d_ULong BITS_29_00 = 0x3FFFFFFF ; 00070 00071 // ---------------------- 00072 // -- Static functions -- 00073 // ---------------------- 00074 00075 inline d_Boolean IS_COMPRESSED(d_ULong value) 00076 { 00077 return BITS_31 == ( BITS_31 & value ) ; 00078 } 00079 00080 inline d_Boolean IS_EMPTY(d_ULong value) 00081 { 00082 return ! ( BITS_29_00 & value ) ; 00083 } 00084 00085 /** 00086 ** Constructor. Used for accessing existing index structure. 00087 ** Requires a read transaction. 00088 **/ 00089 00090 BdbBMIndexQueryAPI::BdbBMIndexQueryAPI() : 00091 BdbAbsIndexQueryAPI("IndexRegistry", 00092 "BitMapIndexStructure") 00093 {} 00094 00095 /** 00096 ** Destructor 00097 **/ 00098 00099 BdbBMIndexQueryAPI::~BdbBMIndexQueryAPI() 00100 {} 00101 00102 /** 00103 ** Report error condition 00104 **/ 00105 00106 void 00107 BdbBMIndexQueryAPI::error(const char* message) const 00108 { 00109 cout << "BdbBitMap[Events]::error " << message << "." << endl ; 00110 } 00111 00112 /** 00113 ** Get a persistent reference to the implementation-specific 00114 ** index structure. 00115 **/ 00116 00117 BdbStatus 00118 BdbBMIndexQueryAPI::lookupIndexStructure(BdbHandle(BdbContObj)& contH, 00119 BdbRef(BdbAbsIndexStructure)& indexRef) 00120 { 00121 BdbStatus status ; 00122 BdbRef(BdbBMIndexStructure) bmRef ; 00123 00124 // Look up an object by its name in the namespace 00125 // container. 00126 00127 status = bmRef.lookupObj(contH, getIndexStructureName(), BdbcRead) ; 00128 if( BdbcSuccess != status ) { 00129 error(" locate index structure") ; 00130 return status ; 00131 } 00132 00133 // Load some essential information on the database: 00134 // 00135 // - the compression flag (used by vector operations) 00136 // - the number of events (used by vector operation NOT for 00137 // the correct vector allignment). 00138 00139 _compressed = bmRef->isCompressed() ; 00140 _events = bmRef->getNumEvents() ; 00141 00142 // Initialize the number of events 00143 00144 // Return a reference to the structure. 00145 00146 indexRef = bmRef ; 00147 00148 return BdbcSuccess ; 00149 } 00150 00151 00152 // ---------------------------------------------------------------------- 00153 // -- Execute "trial" query request. Return result of query estimation -- 00154 // -- into supplied object. -- 00155 // ---------------------------------------------------------------------- 00156 00157 00158 BdbStatus 00159 BdbBMIndexQueryAPI::estimate(BdbQueryDescr& descr, 00160 BdbQueryEstimation& estimation) 00161 { 00162 BdbStatus status ; 00163 00164 // Build the mask (vector) of selected events based on 00165 // given query description. 00166 00167 ooVArray(d_ULong) result ; 00168 00169 status = select(result, descr) ; 00170 if ( BdbcSuccess != status ) { 00171 return status ; 00172 } 00173 00174 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00175 // Make some estimations on the query results. 00176 // 00177 // <IMPLEMENTED> (1) In case of the totatl number of the selected events this 00178 // require to count "1" in both compressed and non-compressed 00179 // vectors. 00180 // <NOT APPLIED> (2) In case of number of "physical" DBs we have to use the 00181 // <NOT APPLIED> (3) There are no ideas what to do with the number of tapes, since we 00182 // don't know for the moment how the files are located on HPSS. 00183 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00184 00185 BdbRef(BdbBMIndexStructure) indexRef = getBMIndexRef() ; 00186 00187 estimation.setTotalNumEvents(indexRef->getNumEvents()) ; 00188 estimation.setNumEvents(estimateNumEvents(result)) ; 00189 00190 return BdbcSuccess ; 00191 } 00192 00193 00194 // ----------------------------------------------------------------------- 00195 // -- FRONT-END: Place results into specified by name events collection -- 00196 // ----------------------------------------------------------------------- 00197 00198 00199 BdbStatus 00200 BdbBMIndexQueryAPI::execute(BdbQueryDescr& descr, 00201 BdbQueryEstimation& estimation, 00202 const char* collection) 00203 { 00204 BdbStatus status ; 00205 00206 // - - - - - - - - - - - - - - - - - - - - - 00207 // Initialize context: clustering hints, etc 00208 // - - - - - - - - - - - - - - - - - - - - - 00209 00210 BdbEventStore* theStore = BdbEventStore::instance( ) ; 00211 00212 BdbDbRegistrator registrator ; 00213 BdbDbTreeSingleton::instance()->setRegistrator(®istrator) ; 00214 00215 BdbAbstractClusteringHint* theTreHint ; 00216 BdbAbstractClusteringHint* theVecHint ; 00217 00218 theStore->configureClustering() ; 00219 00220 if ( theStore->useFullClustering()) { 00221 theTreHint = new BdbEvsClusteringHint(*theStore) ; 00222 theVecHint = new BdbEvsClusteringHint(*theStore) ; 00223 } else { 00224 theTreHint = new BdbSimpleClusteringHint(*theStore) ; 00225 theVecHint = new BdbSimpleClusteringHint(*theStore) ; 00226 } 00227 theTreHint->setComponent("col") ; 00228 theVecHint->setComponent("col") ; 00229 00230 theStore->configureClustering(theTreHint, theVecHint) ; 00231 00232 // - - - - - - - - - - - - - - - - - - - - - - - - 00233 // Try to locate collection. It should not exists 00234 // - - - - - - - - - - - - - - - - - - - - - - - - 00235 00236 BdbCollection<BdbEvent> aCollection; 00237 00238 status = theStore->collection( aCollection, collection ); 00239 if ( BdbcSuccess == status ) { 00240 error("Can not execute the query. Specified output collection already exists.") ; 00241 return BdbcError ; 00242 } 00243 00244 // - - - - - - - - - - - 00245 // Create new collection 00246 // - - - - - - - - - - - 00247 00248 status = theStore->treeCollection(aCollection, collection); 00249 if ( BdbcSuccess != status ) { 00250 error("Can not execute the query. Failed to create specified output collection.") ; 00251 return status ; 00252 } 00253 aCollection.createDescription(aCollection.name()) ; 00254 00255 // - - - - - - - - - - - - - - - - - - - - - - - - - - - 00256 // Go ahead and perform a real query. Place results into 00257 // specified collection. 00258 // - - - - - - - - - - - - - - - - - - - - - - - - - - - 00259 00260 return ( status = execute(descr, estimation, aCollection)) ; 00261 } 00262 00263 00264 // ---------------------------------------------------------------------------- 00265 // -- FRONT-END: Place results into specified by reference events collection -- 00266 // ---------------------------------------------------------------------------- 00267 00268 00269 BdbStatus 00270 BdbBMIndexQueryAPI::execute(BdbQueryDescr& descr, 00271 BdbQueryEstimation& estimation, 00272 BdbCollection<BdbEvent>& outputCollection) 00273 { 00274 BdbStatus status ; 00275 00276 // - - - - - - - - - - - - - - - - - - - - - - - - - - 00277 // Build the mask (vector) of selected events based on 00278 // given query description. 00279 // - - - - - - - - - - - - - - - - - - - - - - - - - - 00280 00281 ooVArray(d_ULong) result ; 00282 00283 status = select(result, descr) ; 00284 if ( BdbcSuccess != status ) { 00285 return status ; 00286 } 00287 00288 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00289 // Make some estimations on the query results. 00290 // 00291 // <IMPLEMENTED> (1) In case of the totatl number of the selected events this 00292 // require to count "1" in both compressed and non-compressed 00293 // vectors. 00294 // <NOT APPLIED> (2) In case of number of "physical" DBs we have to use the 00295 // <NOT APPLIED> (3) There are no ideas what to do with the number of tapes, since 00296 // we don't know for the moment how the files are located on HPSS 00297 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00298 00299 BdbRef(BdbBMIndexStructure) indexRef = getBMIndexRef() ; 00300 00301 estimation.setTotalNumEvents(indexRef->getNumEvents()) ; 00302 estimation.setNumEvents(estimateNumEvents(result)) ; 00303 00304 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00305 // Locate the name of the original events collection 00306 // 00307 // NOTE: The current implementation allows to execute queries 00308 // if the index was built from a real events collection 00309 // rather then from just a plain text file. 00310 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00311 00312 const char* target = indexRef->getTarget() ; 00313 00314 if ( strncmp(target, "COLLECTION:", strlen("COLLECTION:"))) { 00315 error("Can not execute query. The index was not built from an event collection.") ; 00316 return BdbcError ; 00317 } 00318 00319 int inputCollectionNameLength = strlen(target) - strlen("COLLECTION:") ; 00320 char* inputCollectionName = new char[inputCollectionNameLength + 1] ; 00321 00322 strcpy(inputCollectionName, &target[strlen(target) - inputCollectionNameLength]) ; 00323 00324 // - - - - - - - - - - - - - - - - - - - - - - - - - 00325 // Open input collection and set up events iterator 00326 // - - - - - - - - - - - - - - - - - - - - - - - - - 00327 00328 BdbEventStore* theStore = BdbEventStore::instance( ) ; 00329 00330 BdbCollection<BdbEvent> inputCollection; 00331 00332 status = theStore->collection( inputCollection, inputCollectionName ); 00333 if ( BdbcSuccess != status ) { 00334 error("Can not execute the query. Original events collection does not exists.") ; 00335 return status ; 00336 } 00337 BdbCollectionIterator<BdbEvent> inputCollectionItr(inputCollection) ; 00338 00339 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00340 // Now we will translate the selected events (defined by their relative 00341 // position in the bit string) into real references. 00342 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00343 00344 BdbHandle(BdbEvent) theEvent ; 00345 00346 d_ULong nElems = result.size() ; 00347 d_ULong eventNumber = 0 ; 00348 00349 d_ULong i ; 00350 d_ULong j ; 00351 00352 for ( i = 0 ; i < nElems ; i++ ) { 00353 00354 d_ULong value = result[i] ; 00355 00356 if ( IS_COMPRESSED(value)) { 00357 if ( value & BITS_30 ) { 00358 00359 // Take into account all "1"-s. 00360 00361 d_ULong elements = BITS_29_00 & value ; 00362 00363 for ( j = 0 ; j < elements ; j++ ) { 00364 00365 status = inputCollectionItr.next(theEvent) ; 00366 if ( BdbcSuccess != status ) { 00367 00368 error("1: Unable to proceed with query execution.") ; 00369 error("2: Failed to fetch next event reference from original collection.") ; 00370 error("3: This might be because the index does not match the original collection.") ; 00371 00372 return status ; 00373 } 00374 00375 status = outputCollection.add(theEvent) ; 00376 if ( BdbcSuccess != status ) { 00377 error("1: Unable to proceed with query execution.") ; 00378 error("2: Failed to add next event reference to the output collection.") ; 00379 00380 return status ; 00381 } 00382 eventNumber++ ; 00383 } 00384 } else { 00385 00386 // Skip "0"-es. 00387 00388 d_ULong eventsToSkeep = BITS_29_00 & value ; 00389 00390 for ( j = 0 ; j < eventsToSkeep ; j++ ) { 00391 00392 status = inputCollectionItr.next(theEvent) ; 00393 if ( BdbcSuccess != status ) { 00394 00395 error("1: Unable to proceed with query execution.") ; 00396 error("2: Failed to fetch next event reference from original collection.") ; 00397 error("3: This might be because the index does not match the original collection.") ; 00398 00399 return status ; 00400 } 00401 } 00402 00403 eventNumber += eventsToSkeep ; 00404 } 00405 } else { 00406 00407 // Go along the bits and find all "1"-s. 00408 00409 for ( j = 0 ; j < 30 ; j++ ) { 00410 if (( 1 << j ) & ( BITS_29_00 & value )) { 00411 00412 status = inputCollectionItr.next(theEvent) ; 00413 if ( BdbcSuccess != status ) { 00414 00415 error("1: Unable to proceed with query execution.") ; 00416 error("2: Failed to fetch next event reference from original collection.") ; 00417 error("3: This might be because the index does not match the original collection.") ; 00418 00419 return status ; 00420 } 00421 00422 status = outputCollection.add(theEvent) ; 00423 if ( BdbcSuccess != status ) { 00424 error("1: Unable to proceed with query execution.") ; 00425 error("2: Failed to add next event reference to the output collection.") ; 00426 00427 return status ; 00428 } 00429 } 00430 eventNumber++ ; 00431 } 00432 } 00433 } 00434 00435 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00436 // Copy collection description (TAGs profile) from the original 00437 // colection to the output one. 00438 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 00439 00440 BdbHandle(HepExplorableDescr) expDescr ; 00441 00442 status = inputCollection.description(expDescr) ; 00443 if ( BdbcSuccess != status ) { 00444 error("Unable to get a description for input collection") ; 00445 return status ; 00446 } 00447 00448 status = outputCollection.setDescription(expDescr) ; 00449 if ( BdbcSuccess != status ) { 00450 error("Unable to set a description for output collection") ; 00451 return status ; 00452 } 00453 00454 return BdbcSuccess ; 00455 } 00456 00457 00458 // ------------------------------------------------------------ 00459 // -- Test method. It brakes through the regular interface -- 00460 // -- allowing to obtain the bit-map implementation specific -- 00461 // -- results of the query execution. -- 00462 // ------------------------------------------------------------ 00463 00464 00465 BdbStatus 00466 BdbBMIndexQueryAPI::execute(const BdbQueryDescr& descr, 00467 BdbQueryEstimation& estimation, 00468 ooVArray(d_ULong)& result) 00469 { 00470 BdbStatus status ; 00471 00472 // Build the mask (vector) of selected events based on 00473 // given query description. 00474 00475 status = select(result, descr) ; 00476 if ( BdbcSuccess != status ) { 00477 return status ; 00478 } 00479 00480 // Make some estimations on the query results. 00481 // 00482 // <IMPLEMENTED> (1) In case of the totatl number of the selected events this 00483 // require to count "1" in both compressed and non-compressed 00484 // vectors. 00485 // <NOT APPLIED> (2) In case of number of "physical" DBs we have to use the 00486 // <NOT APPLIED> (3) There are no ideas what to do with the number of tapes, since we 00487 // don't know for the moment how the files are located on HPSS. 00488 00489 estimation.setNumEvents(estimateNumEvents(result)) ; 00490 00491 return BdbcSuccess ; 00492 } 00493 00494 /**----------------------------------------------------------- 00495 ** This helper functions perform an actual processing of the 00496 ** given request. On return it fills up a bit vector 00497 ** with the compression information on the selected events. 00498 **----------------------------------------------------------- 00499 **/ 00500 00501 BdbStatus 00502 BdbBMIndexQueryAPI::select(ooVArray(d_ULong)& result, const BdbQueryDescr& descr) 00503 { 00504 00505 // Check if the given structure is initialized. 00506 00507 if ( ! descr.isInitialized()) { 00508 error("- the wrong structure has been passed for selection.") ; 00509 return BdbcError ; 00510 } 00511 00512 // Start from the root node in the tree. 00513 00514 return nextNode(result, descr.getHead()) ; 00515 } 00516 00517 BdbStatus 00518 BdbBMIndexQueryAPI::nextNode(ooVArray(d_ULong)& result, const BdbQueryNode* node) 00519 { 00520 BdbStatus status ; 00521 ooVArray(d_ULong) left ; 00522 ooVArray(d_ULong) right ; 00523 00524 // Check zero reference to the node was passed. 00525 // This should be treated as a error. 00526 00527 if ( node == (BdbQueryNode*) 0 ) { 00528 error("- inconsistent query description. Unexpected NULL pointer.") ; 00529 return BdbcError ; 00530 } 00531 00532 // Process this node. 00533 00534 if ( node->isLogical()) { 00535 00536 switch ( node->getLogicalOperation()) { 00537 00538 case BdbQueryNode::LOP_NOT : 00539 00540 status = nextNode(left, node->getLeft()) ; 00541 if ( BdbcSuccess != status ) { 00542 return status ; 00543 } 00544 00545 status = NOT(result, left) ; 00546 if ( BdbcSuccess != status ) { 00547 return status ; 00548 } 00549 00550 break ; 00551 00552 case BdbQueryNode::LOP_AND : 00553 00554 status = nextNode(left, node->getLeft()) ; 00555 if ( BdbcSuccess != status ) { 00556 return status ; 00557 } 00558 status = nextNode(right, node->getRight()) ; 00559 if ( BdbcSuccess != status ) { 00560 return status ; 00561 } 00562 00563 status = AND(result, left, right) ; 00564 if ( BdbcSuccess != status ) { 00565 return status ; 00566 } 00567 00568 break ; 00569 00570 case BdbQueryNode::LOP_OR : 00571 00572 status = nextNode(left, node->getLeft()) ; 00573 if ( BdbcSuccess != status ) { 00574 return status ; 00575 } 00576 status = nextNode(right, node->getRight()) ; 00577 if ( BdbcSuccess != status ) { 00578 return status ; 00579 } 00580 00581 status = OR(result, left, right) ; 00582 if ( BdbcSuccess != status ) { 00583 return status ; 00584 } 00585 00586 break ; 00587 } 00588 } else { 00589 00590 status = endNode(result, node) ; 00591 if ( BdbcSuccess != status ) { 00592 return status ; 00593 } 00594 } 00595 00596 return BdbcSuccess ; 00597 } 00598 00599 BdbStatus 00600 BdbBMIndexQueryAPI::endNode(ooVArray(d_ULong)& result, const BdbQueryNode* node) 00601 { 00602 BdbStatus status ; 00603 d_ULong i ; 00604 00605 // Take the specified range and calculate the bins 00606 // that must be OR-ed. 00607 00608 const char* dimName = node->getName() ; 00609 00610 // STEP I: Pre-load the following information: 00611 // 00612 // - the reference to the persistent index structure 00613 // - reference to the persistent dimension 00614 // - the number of events in the database 00615 // - the number of bins 00616 // - an array of references to the persistent bins 00617 00618 d_ULong nEvents ; 00619 d_ULong nBins ; 00620 00621 BdbRef(BdbBMIndexStructure) indexRef ; 00622 BdbRef(BdbBMDimension) dimRef ; 00623 ooVArray(BdbRef(BdbBMBin)) binRef ; 00624 00625 indexRef = getBMIndexRef() ; 00626 00627 status = indexRef->getDimension(dimName, dimRef) ; 00628 if ( BdbcSuccess != status ) { 00629 cout << "BdbBMIndexQuery::endNode() - unknown attribute name: " 00630 << dimName << endl ; 00631 return status ; 00632 } 00633 00634 nEvents = indexRef->getNumEvents() ; 00635 nBins = dimRef->getNumBins() ; 00636 00637 status = binRef.resize(nBins) ; 00638 if ( BdbcSuccess != status ) { 00639 cout << "BdbBMIndexQuery::endNode() - failed to resize ooVArray." << endl ; 00640 return status ; 00641 } 00642 00643 for ( i = 0 ; i < nBins ; i++ ) { 00644 00645 status = dimRef->getBin(i, binRef[i]) ; 00646 if ( BdbcSuccess != status ) { 00647 cout << "BdbBMIndexQuery::endNode() - failed to load persistent BdbBMBin object." << endl ; 00648 return status ; 00649 } 00650 } 00651 00652 // STEP II: Find out a range of bins to be OR-ed together 00653 // in order to meet the selection criteria. 00654 00655 d_ULong from ; // The bin number to start WITH. 00656 d_ULong to ; // The bin number to finish BEFORE. 00657 00658 d_Float minVal ; // Minumum range of the query. 00659 d_Float maxVal ; // Maxumum range of the query. 00660 00661 minVal = node->getMinVal() ; 00662 maxVal = node->getMaxVal() ; 00663 00664 if ( ! node->isMinDefined()) { 00665 from = 0 ; 00666 } else { 00667 00668 while ( true ) { 00669 00670 if ( minVal < dimRef->getMinValue()) { 00671 from = 0 ; 00672 break ; // Less then dimension's minimum. 00673 } 00674 00675 if ( minVal >= dimRef->getMaxValue()) { 00676 from = nBins -1 ; 00677 break ; // More or equal then dimension's maximum. 00678 } 00679 00680 d_Boolean from_is_found = false ; 00681 00682 for ( i = 0 ; i < nBins ; i++ ) { 00683 00684 if (( minVal >= binRef[i]->getMinValue()) && 00685 ( minVal < binRef[i]->getMaxValue())) { 00686 00687 from = i ; 00688 00689 from_is_found = true ; 00690 00691 break ; 00692 } 00693 } 00694 00695 if ( ! from_is_found ) { 00696 cout << "BdbBMIndexQuery::endNode() - internal bug #1." << endl ; 00697 return BdbcError ; 00698 } 00699 00700 break ; // Within dimension. 00701 } 00702 } 00703 00704 if ( ! node->isMaxDefined()) { 00705 to = nBins ; 00706 } else { 00707 00708 while ( true ) { 00709 00710 if ( maxVal < dimRef->getMinValue()) { 00711 to = 1 ; 00712 break ; // Less then dimension's minimum. 00713 } 00714 00715 if ( maxVal >= dimRef->getMaxValue()) { 00716 to = nBins ; 00717 break ; // More or equal then dimension's maximum. 00718 } 00719 00720 d_Boolean to_is_found = false ; 00721 00722 for ( i = 0 ; i < nBins ; i++ ) { 00723 00724 if (( maxVal >= binRef[i]->getMinValue()) && 00725 ( maxVal < binRef[i]->getMaxValue())) { 00726 00727 to = i + 1 ; 00728 00729 to_is_found = true ; 00730 00731 break ; 00732 } 00733 } 00734 00735 if ( ! to_is_found ) { 00736 cout << "BdbBMIndexQuery::endNode() - internal bug #2." << endl ; 00737 return BdbcError ; 00738 } 00739 00740 break ; // Within dimension. 00741 } 00742 } 00743 00744 if ( from >= to ) { 00745 cout << "BdbBMIndexQuery::endNode() - wrong range for attribute: " 00746 << dimName << endl ; 00747 return BdbcError ; 00748 } 00749 00750 // STEP III: The final action is to go through the selected 00751 // bit strings and to "OR" them together. 00752 00753 ooVArray(d_ULong) tmp ; 00754 00755 status = ZERO(tmp, nEvents) ; 00756 if ( BdbcSuccess != status ) { 00757 cout << "BdbBMIndexQuery::endNode() - error to create temporary bit vector." << endl ; 00758 return status ; 00759 } 00760 00761 for ( i = from ; i < to ; i++ ) { 00762 00763 result.resize(0) ; // If we don't do it, the vector length 00764 // will increase after each OR. 00765 00766 status = OR(result, tmp, binRef[i]->getBits()) ; 00767 if ( BdbcSuccess != status ) { 00768 cout << "BdbBMIndexQuery::endNode() - operation OR failed for bit vectors." << endl ; 00769 return status ; 00770 } 00771 tmp = result ; // Save the result for the next operation. 00772 } 00773 00774 return BdbcSuccess ; 00775 } 00776 00777 /**------------------------------------------------------------------- 00778 ** Bit strings operations. Are used by the query estimator 00779 ** and executor. 00780 ** All the operations are based on existing arrays. 00781 ** The output of the vectors is compressed or not depending 00782 ** on the state of the persistent index structure. 00783 ** 00784 ** NOTE: (1) The max number of elements (either compressed or not) 00785 ** is limited by 30 bits, or 10^30. 00786 ** This is general limitation of all the vector algorithms. 00787 ** 00788 ** (2) The implementation of the OR, AND operations for the 00789 ** compressed vetors is not so efficient as it could be. 00790 ** The situation will be improved in further versions. 00791 **------------------------------------------------------------------- 00792 **/ 00793 00794 BdbStatus 00795 BdbBMIndexQueryAPI::NOT(ooVArray(d_ULong)& out, 00796 const ooVArray(d_ULong)& in) 00797 { 00798 BdbStatus status ; 00799 d_ULong i ; 00800 d_ULong nBits ; 00801 00802 // (Re-)allocate output vector of the same 00803 // size as the input one. 00804 00805 nBits = in.size() ; 00806 00807 status = out.resize(nBits) ; 00808 if ( BdbcSuccess != status ) { 00809 error("- vector resize.") ; 00810 return status ; 00811 } 00812 00813 // Perform NOT for each element depending 00814 // on the compressing method. 00815 00816 // DEBUG: cout << endl ; 00817 // DEBUG: cout << "BdbBMIndexQueryAPI::NOT num30 " << nBits << endl ; 00818 00819 if ( isCompressed()) { 00820 00821 for ( i = 0 ; i < nBits ; i++ ) { 00822 00823 d_ULong value = in[i] ; 00824 00825 if ( IS_COMPRESSED(value)) { 00826 00827 out[i] = BITS_31 | ( BITS_30 & ( ~value )) | ( BITS_29_00 & value ) ; 00828 00829 } else { 00830 00831 out[i] = BITS_29_00 & ( ~value ) ; 00832 00833 } 00834 00835 d_ULong value1 = value ; 00836 d_ULong value2 = out[i] ; 00837 00838 // DEBUG: cout << endl ; 00839 // DEBUG: cout << " value1: (31) (30) (29..0) = " 00840 // DEBUG: << ( BITS_31 == ( BITS_31 & value1 )) << " " 00841 // DEBUG: << ( BITS_30 == ( BITS_30 & value1 )) << " " 00842 // DEBUG: << ( BITS_29_00 & value1 ) << endl 00843 // DEBUG: << " value2: (31) (30) (29..0) = " 00844 // DEBUG: << ( BITS_31 == ( BITS_31 & value2 )) << " " 00845 // DEBUG: << ( BITS_30 == ( BITS_30 & value2 )) << " " 00846 // DEBUG: << ( BITS_29_00 & value2 ) << endl ; 00847 00848 } 00849 00850 } else { 00851 00852 // The most significant two (31,30) bits 00853 // are zero-ed. 00854 00855 for ( i = 0 ; i < nBits ; i++ ) { 00856 out[i] = BITS_29_00 & ( ~in[i] ) ; 00857 } 00858 } 00859 00860 // Make a "last word alignment correction", by suppressing all meaningles 00861 // fantom "1" in the last word. 00862 // As it's might be seen from the code below, this kind of correction 00863 // is only done, when the last word is uncompressed and contains 00864 // less then 30 meaningfull bits. 00865 // 00866 // NOTE: The correction mechanism is based on an idea of a "magic 00867 // quantum" of 30 events. 00868 00869 d_ULong rem30 = getNumEvents() % 30 ; 00870 00871 if ( rem30 && nBits ) { 00872 00873 // DEBUG: cout << endl ; 00874 // DEBUG: cout << "BdbBMIndexQueryAPI::NOT rem30 " << rem30 << endl ; 00875 00876 if ( ! IS_COMPRESSED(out[nBits-1])) { 00877 00878 // Make a proper mask in order to enable the meaningfull 00879 // bits only. 00880 00881 d_ULong bits29_00 = 0 ; 00882 00883 for ( i = 0 ; i < rem30 ; i++ ) { 00884 bits29_00 = ( 1 << i ) | bits29_00 ; 00885 } 00886 00887 d_ULong value1 = out[nBits-1] ; 00888 00889 out[nBits-1] = bits29_00 & out[nBits-1] ; 00890 00891 d_ULong value2 = out[nBits-1]; 00892 00893 // DEBUG: cout << endl ; 00894 // DEBUG: cout << " value1: (31) (30) (29..0) = " 00895 // DEBUG: << ( BITS_31 == ( BITS_31 & value1 )) << " " 00896 // DEBUG: << ( BITS_30 == ( BITS_30 & value1 )) << " " 00897 // DEBUG: << ( BITS_29_00 & value1 ) << endl 00898 // DEBUG: << " value2: (31) (30) (29..0) = " 00899 // DEBUG: << ( BITS_31 == ( BITS_31 & value2 )) << " " 00900 // DEBUG: << ( BITS_30 == ( BITS_30 & value2 )) << " " 00901 // DEBUG: << ( BITS_29_00 & value2 ) << endl ; 00902 00903 } 00904 } 00905 00906 return BdbcSuccess ; 00907 } 00908 00909 BdbStatus 00910 BdbBMIndexQueryAPI::AND(ooVArray(d_ULong)& out, 00911 const ooVArray(d_ULong)& in1, 00912 const ooVArray(d_ULong)& in2) 00913 { 00914 BdbStatus status ; 00915 d_ULong i ; 00916 d_ULong size1 = in1.size() ; 00917 d_ULong size2 = in2.size() ; 00918 00919 // Perform AND depending 00920 // on the compressing method. 00921 00922 if ( isCompressed()) { 00923 00924 CompressionContext context(out) ; 00925 00926 d_ULong num30 = getNumEvents() / 30 ; 00927 d_ULong rem30 = getNumEvents() % 30 ; 00928 00929 d_ULong next1 = 0 ; 00930 d_ULong next2 = 0 ; 00931 00932 // First we perform operation on "full" 30-bits words. 00933 00934 d_ULong value1 ; 00935 d_ULong value2 ; 00936 00937 d_ULong p1 ; 00938 d_ULong p2 ; 00939 00940 d_Boolean empty1 = true ; 00941 d_Boolean empty2 = true ; 00942 00943 for ( i = 0 ; i < num30 ; i++ ) { 00944 00945 // Load the next (compressed/un-compressed) words 00946 // if nessesary. 00947 // Advance the "next" indexes as well. 00948 // 00949 // NOTE: indirect checking for the vectors consistency 00950 // is done before to load next portion of data. 00951 00952 if ( empty1 ) { 00953 00954 if ( next1 >= size1 ) { 00955 error("- input vectors are inconsistent.") ; 00956 return BdbcError ; 00957 } 00958 00959 value1 = in1[next1++] ; 00960 } 00961 00962 if ( empty2 ) { 00963 00964 if ( next2 >= size1 ) { 00965 error("- input vectors are inconsistent.") ; 00966 return BdbcError ; 00967 } 00968 00969 value2 = in2[next2++] ; 00970 } 00971 00972 // Get next portion of 30 bits depending 00973 // on whether the input word is compressed or not. 00974 // Update "empty" flag if desired. 00975 00976 if ( IS_COMPRESSED(value1)) { 00977 00978 p1 = GET_30(value1) ; 00979 empty1 = IS_EMPTY(value1) ; 00980 00981 } else { 00982 00983 p1 = value1 ; 00984 empty1 = true ; 00985 00986 } 00987 00988 if ( IS_COMPRESSED(value2)) { 00989 00990 p2 = GET_30(value2) ; 00991 empty2 = IS_EMPTY(value2) ; 00992 00993 } else { 00994 00995 p2 = value2 ; 00996 empty2 = true ; 00997 00998 } 00999 01000 // Perform the operation on the values. 01001 // Save the results in the output vector. 01002 01003 status = context.compress(p1 & p2, 0) ; 01004 if ( BdbcSuccess != status ) { 01005 return status ; 01006 } 01007 01008 } 01009 01010 // Then we perform operation on the last word having less 01011 // then 30 usefull bits if desired, of course. 01012 // Save results in output vector. 01013 01014 if ( rem30 ) { 01015 01016 // Check if both vectors have the same length. 01017 01018 if (( next1 >= size1 ) || ( next2 >= size2 )) { 01019 error("- input vectors are inconsistent.") ; 01020 return BdbcError ; 01021 } 01022 01023 status = context.compress(in1[next1] & in2[next2], rem30) ; 01024 if ( BdbcSuccess != status ) { 01025 return status ; 01026 } 01027 } 01028 01029 // Synchronize the context. 01030 01031 status = context.synchronize() ; 01032 if ( BdbcSuccess != status ) { 01033 return status ; 01034 } 01035 01036 } else { 01037 01038 // Check if both vectors have the same length. 01039 01040 if ( size1 != size2 ) { 01041 error("- vectors have different length.") ; 01042 return BdbcError ; 01043 } 01044 01045 // (Re-)allocate output vector of the same 01046 // size as the input ones. 01047 01048 status = out.resize(size1) ; 01049 if ( BdbcSuccess != status ) { 01050 error("- vector resize.") ; 01051 return status ; 01052 } 01053 01054 for ( i = 0 ; i < size1 ; i++ ) { 01055 out[i] = in1[i] & in2[i] ; 01056 } 01057 } 01058 01059 return BdbcSuccess ; 01060 } 01061 01062 BdbStatus 01063 BdbBMIndexQueryAPI::OR(ooVArray(d_ULong)& out, 01064 const ooVArray(d_ULong)& in1, 01065 const ooVArray(d_ULong)& in2) 01066 { 01067 BdbStatus status ; 01068 d_ULong i ; 01069 d_ULong size1 = in1.size() ; 01070 d_ULong size2 = in2.size() ; 01071 01072 // Perform OR depending 01073 // on the compressing method. 01074 01075 if ( isCompressed()) { 01076 01077 CompressionContext context(out) ; 01078 01079 d_ULong num30 = getNumEvents() / 30 ; 01080 d_ULong rem30 = getNumEvents() % 30 ; 01081 01082 // DEBUG: cout << "BdbBMIndexQueryAPI::OR" << endl 01083 // DEBUG: << " num30 = " << num30 << endl 01084 // DEBUG: << " rem30 = " << rem30 << endl 01085 // DEBUG: << " size1 = " << size1 << endl 01086 // DEBUG: << " size2 = " << size2 << endl ; 01087 01088 d_ULong next1 = 0 ; 01089 d_ULong next2 = 0 ; 01090 01091 // First we perform operation on "full" 30-bits words. 01092 01093 d_ULong value1 ; 01094 d_ULong value2 ; 01095 01096 d_ULong p1 ; 01097 d_ULong p2 ; 01098 01099 d_Boolean empty1 = true ; 01100 d_Boolean empty2 = true ; 01101 01102 for ( i = 0 ; i < num30 ; i++ ) { 01103 01104 // Load the next (compressed/un-compressed) words 01105 // if nessesary. 01106 // Advance the "next" indexes as well. 01107 // 01108 // NOTE: indirect checking for the vectors consistency 01109 // is done before to load next portion of data. 01110 01111 if ( empty1 ) { 01112 01113 if ( next1 >= size1 ) { 01114 error("- input vectors are inconsistent.") ; 01115 01116 cout << "BdbBMIndexQueryAPI::OR" << endl 01117 << " i = " << i << endl 01118 << " next1 = " << next1 << endl ; 01119 01120 return BdbcError ; 01121 } 01122 01123 value1 = in1[next1++] ; 01124 } 01125 01126 if ( empty2 ) { 01127 01128 if ( next2 >= size2 ) { 01129 error("- input vectors are inconsistent.") ; 01130 01131 cout << "BdbBMIndexQueryAPI::OR" << endl 01132 << " i = " << i << endl 01133 << " next2 = " << next2 << endl ; 01134 01135 return BdbcError ; 01136 } 01137 01138 value2 = in2[next2++] ; 01139 } 01140 01141 // DEBUG: cout << endl ; 01142 // DEBUG: cout << "BdbBMIndexQueryAPI::OR num30" << endl 01143 // DEBUG: << " value1: (31) (30) (29..0) = " 01144 // DEBUG: << ( BITS_31 == ( BITS_31 & value1 )) << " " 01145 // DEBUG: << ( BITS_30 == ( BITS_30 & value1 )) << " " 01146 // DEBUG: << ( BITS_29_00 & value1 ) << endl 01147 // DEBUG: << " value2: (31) (30) (29..0) = " 01148 // DEBUG: << ( BITS_31 == ( BITS_31 & value2 )) << " " 01149 // DEBUG: << ( BITS_30 == ( BITS_30 & value2 )) << " " 01150 // DEBUG: << ( BITS_29_00 & value2 ) << endl ; 01151 01152 // Get next portion of 30 bits depending 01153 // on whether the input word is compressed or not. 01154 // Update "empty" flag if desired. 01155 01156 if ( IS_COMPRESSED(value1)) { 01157 01158 p1 = GET_30(value1) ; 01159 empty1 = IS_EMPTY(value1) ; 01160 01161 } else { 01162 01163 p1 = value1 ; 01164 empty1 = true ; 01165 01166 } 01167 01168 if ( IS_COMPRESSED(value2)) { 01169 01170 p2 = GET_30(value2) ; 01171 empty2 = IS_EMPTY(value2) ; 01172 01173 } else { 01174 01175 p2 = value2 ; 01176 empty2 = true ; 01177 01178 } 01179 01180 // DEBUG: cout << endl 01181 // DEBUG: << " value1: (31) (30) (29..0) = " 01182 // DEBUG: << ( BITS_31 == ( BITS_31 & value1 )) << " " 01183 // DEBUG: << ( BITS_30 == ( BITS_30 & value1 )) << " " 01184 // DEBUG: << ( BITS_29_00 & value1 ) << endl 01185 // DEBUG: << " value2: (31) (30) (29..0) = " 01186 // DEBUG: << ( BITS_31 == ( BITS_31 & value2 )) << " " 01187 // DEBUG: << ( BITS_30 == ( BITS_30 & value2 )) << " " 01188 // DEBUG: << ( BITS_29_00 & value2 ) << endl ; 01189 01190 // Perform the operation on the values. 01191 // Save the results in the output vector. 01192 01193 status = context.compress(p1 | p2, 0) ; 01194 if ( BdbcSuccess != status ) { 01195 return status ; 01196 } 01197 01198 } 01199 01200 // Then we perform operation on the last word having less 01201 // then 30 usefull bits if desired, of course. 01202 // Save results in output vector. 01203 01204 if ( rem30 ) { 01205 01206 // Check if both vectors have the same length. 01207 01208 if (( next1 >= size1 ) || ( next2 >= size2 )) { 01209 error("- input vectors are inconsistent.") ; 01210 return BdbcError ; 01211 } 01212 01213 // DEBUG: d_ULong value1 = in1[next1] ; 01214 // DEBUG: d_ULong value2 = in2[next2] ; 01215 // DEBUG: 01216 // DEBUG: cout << endl ; 01217 // DEBUG: cout << "BdbBMIndexQueryAPI::OR rem30" << endl 01218 // DEBUG: << " value1: (31) (30) (29..0) = " 01219 // DEBUG: << ( BITS_31 == ( BITS_31 & value1 )) << " " 01220 // DEBUG: << ( BITS_30 == ( BITS_30 & value1 )) << " " 01221 // DEBUG: << ( BITS_29_00 & value1 ) << endl 01222 // DEBUG: << " value2: (31) (30) (29..0) = " 01223 // DEBUG: << ( BITS_31 == ( BITS_31 & value2 )) << " " 01224 // DEBUG: << ( BITS_30 == ( BITS_30 & value2 )) << " " 01225 // DEBUG: << ( BITS_29_00 & value2 ) << endl ; 01226 01227 status = context.compress(in1[next1] | in2[next2], rem30) ; 01228 if ( BdbcSuccess != status ) { 01229 return status ; 01230 } 01231 } 01232 01233 // Synchronize the context. 01234 01235 status = context.synchronize() ; 01236 if ( BdbcSuccess != status ) { 01237 return status ; 01238 } 01239 01240 } else { 01241 01242 // Check if both vectors have the same length. 01243 01244 if ( size1 != size2 ) { 01245 error("- vectors have different length.") ; 01246 return BdbcError ; 01247 } 01248 01249 // (Re-)allocate output vector of the same 01250 // size as the input ones. 01251 01252 status = out.resize(size1) ; 01253 if ( BdbcSuccess != status ) { 01254 error("- vector resize.") ; 01255 return status ; 01256 } 01257 01258 for ( i = 0 ; i < size1 ; i++ ) { 01259 out[i] = in1[i] | in2[i] ; 01260 } 01261 } 01262 01263 return BdbcSuccess ; 01264 } 01265 01266 BdbStatus 01267 BdbBMIndexQueryAPI::ONE(ooVArray(d_ULong)& out, 01268 d_ULong elements) 01269 { 01270 return ONE_OR_ZERO(out, elements, 1) ; 01271 } 01272 01273 BdbStatus 01274 BdbBMIndexQueryAPI::ZERO(ooVArray(d_ULong)& out, 01275 d_ULong elements) 01276 { 01277 return ONE_OR_ZERO(out, elements, 0) ; 01278 } 01279 01280 BdbStatus 01281 BdbBMIndexQueryAPI::ONE_OR_ZERO(ooVArray(d_ULong)& out, 01282 d_ULong elements, 01283 d_ULong bit) 01284 { 01285 BdbStatus status ; 01286 d_ULong i ; 01287 d_ULong vectorSize ; 01288 d_ULong num30 = (BITS_29_00 & elements) / 30 ; // Use 30 bits only. 01289 d_ULong rem30 = (BITS_29_00 & elements) % 30 ; // Use 30 bits only. 01290 01291 // Create a bit vector with all the elements set either to "1" or to "0", 01292 // depending on the value of specified parameter. 01293 // The vector is created either compressed or not depending 01294 // on the status of the open database. 01295 01296 if ( isCompressed()) { 01297 01298 // COMPRESSED vectors. 01299 01300 vectorSize = 1 ; 01301 if ( rem30 ) { 01302 vectorSize++ ; 01303 } 01304 01305 status = out.resize(vectorSize) ; 01306 if ( BdbcSuccess != status ) { 01307 error("- vector resize.") ; 01308 return status ; 01309 } 01310 01311 // Compress the first word of the vector. 01312 01313 out[0] = ( BITS_31 | ( bit << 30 )) | ( 30 * num30 ) ; 01314 01315 // Fill the second word of the vector by raw bit string if desired. 01316 01317 if ( rem30 ) { 01318 01319 out[1] = 0 ; 01320 01321 for ( i = 0 ; i < rem30 ; i++ ) { 01322 out[1] = out[1] | ( bit << i ) ; 01323 } 01324 } 01325 01326 } else { 01327 01328 // NON-COMPRESSED vectors. 01329 01330 vectorSize = num30 ; 01331 if ( rem30 ) { 01332 vectorSize++ ; 01333 } 01334 01335 status = out.resize(vectorSize) ; 01336 if ( BdbcSuccess != status ) { 01337 error("- vector resize.") ; 01338 return status ; 01339 } 01340 01341 // Fill the first complete words of the vector by 01342 // raw bit strings. 01343 01344 for ( d_ULong j = 0 ; j < vectorSize - 1 ; j++ ) { 01345 01346 out[j] = 0 ; 01347 01348 for ( i = 0 ; i < 30 ; i++ ) { 01349 out[j] = out[j] | ( bit << i ) ; 01350 } 01351 01352 } 01353 01354 // Fill the last word of the vector by raw bit string if desired. 01355 01356 if ( rem30 ) { 01357 01358 out[vectorSize-1] = 0 ; 01359 01360 for ( i = 0 ; i < rem30 ; i++ ) { 01361 out[vectorSize-1] = out[vectorSize-1] | ( bit << i ) ; 01362 } 01363 } 01364 } 01365 01366 return BdbcSuccess ; 01367 } 01368 01369 d_ULong 01370 BdbBMIndexQueryAPI::GET_30(d_ULong& value) 01371 { 01372 01373 // Decrement input value by 30. 01374 01375 value = ( BITS_31_30 & value ) | (( BITS_29_00 & value ) - 30 ) ; 01376 01377 // Return the mask of "30-th" depending on the compressing 01378 // contents: "1" or "0". 01379 01380 if ( BITS_30 == ( BITS_30 & value )) 01381 return BITS_29_00 ; 01382 else 01383 return 0 ; 01384 } 01385 01386 01387 /** ---------------------------------------------------------- 01388 ** The following helper functions gather the query estimation 01389 ** statistics based on already done events pre-selections. 01390 ** ---------------------------------------------------------- 01391 **/ 01392 01393 d_ULong 01394 BdbBMIndexQueryAPI::estimateNumEvents(const ooVArray(d_ULong)& in) 01395 { 01396 d_ULong events = 0 ; 01397 d_ULong vectorSize = in.size() ; 01398 01399 // DEBUG: cout << endl ; 01400 // DEBUG: cout << "BdbBMIndexQueryAPI::estimateNumEvents vectorSize = " << vectorSize << endl ; 01401 // DEBUG: 01402 // DEBUG: cout << "1: events = " << events << endl ; 01403 01404 for ( d_ULong i = 0 ; i < vectorSize ; i++ ) { 01405 01406 d_ULong value = in[i] ; 01407 01408 01409 // DEBUG: cout << endl ; 01410 // DEBUG: cout << " value: (31) (30) (29..0) = " 01411 // DEBUG: << ( BITS_31 == ( BITS_31 & value )) << " " 01412 // DEBUG: << ( BITS_30 == ( BITS_30 & value )) << " " 01413 // DEBUG: << ( BITS_29_00 & value ) << endl ; 01414 01415 // For compressed words, we take into account only those 01416 // words where the "1"-s were compressed. 01417 // 01418 // Otherwise we count each bit in a word. In this case 01419 // a small optimization is done in order to skip the completelly 01420 // "empty" (= 0) words. 01421 01422 d_ULong mask = ( BITS_31_30 & value ) ; 01423 01424 switch ( mask ) { 01425 01426 case BITS_31_30: 01427 01428 events = events + ( BITS_29_00 & value ) ; 01429 01430 // DEBUG: cout << "2: events = " << events << endl ; 01431 01432 break ; 01433 01434 case BITS_31: 01435 case BITS_30: 01436 01437 // DEBUG: cout << "x: value = " << value << endl ; 01438 // DEBUG: cout << " mask = " << mask << endl ; 01439 // DEBUG: cout << " BITS_31_30 = " << BITS_31_30 << endl ; 01440 01441 break ; 01442 01443 default: 01444 01445 if ( value ) { 01446 for ( d_ULong j = 0 ; j < 30 ; j++ ) { 01447 if ( value & ( 1 << j )) { 01448 events++ ; 01449 } 01450 } 01451 } 01452 01453 // DEBUG: cout << "3: events = " << events << endl ; 01454 01455 break ; 01456 } 01457 } 01458 01459 // DEBUG: cout << "4: events = " << events << endl ; 01460 01461 return events ; 01462 } 01463 01464 /**-------------------------- 01465 ** Transaction management 01466 **-------------------------- 01467 **/ 01468 01469 void 01470 BdbBMIndexQueryAPI::startUpdate( const char* theTag ) 01471 { 01472 BdbApplication* theApp = BdbApplication::instance( ); 01473 theApp->startUpdate( "Indexing", theTag ); 01474 } 01475 01476 void 01477 BdbBMIndexQueryAPI::startRead( const char* theTag ) 01478 { 01479 BdbApplication* theApp = BdbApplication::instance( ); 01480 theApp->startRead( "Indexing", theTag ); 01481 } 01482 01483 void 01484 BdbBMIndexQueryAPI::abort( ) 01485 { 01486 BdbApplication* theApp = BdbApplication::instance( ); 01487 theApp->abort( "Indexing" ); 01488 } 01489 01490 void 01491 BdbBMIndexQueryAPI::commit( ) 01492 { 01493 BdbApplication* theApp = BdbApplication::instance( ); 01494 theApp->commit( "Indexing" ); 01495 } 01496 01497 /** ----------------------------------------------------------- 01498 ** Implementation for the nested class of CompressionContext 01499 ** ----------------------------------------------------------- 01500 **/ 01501 01502 BdbBMIndexQueryAPI::CompressionContext::CompressionContext(ooVArray(d_ULong)& out) : 01503 _isCompressing(false), 01504 _out(out) 01505 { 01506 } 01507 01508 BdbBMIndexQueryAPI::CompressionContext::~CompressionContext() 01509 { 01510 synchronize() ; 01511 } 01512 01513 BdbStatus 01514 BdbBMIndexQueryAPI::CompressionContext::compress(d_ULong value, d_ULong rem30) 01515 { 01516 BdbStatus status ; 01517 01518 // Is input value compressed ? 01519 01520 if ( IS_COMPRESSED(value)) { 01521 01522 if ( _isCompressing ) { 01523 01524 // Are we compressing the same ("0" or "1")? 01525 01526 if ((( _isZero ) && ( ! value )) 01527 || 01528 (( ! _isZero ) && ( value ))) { 01529 01530 // Yes. We are already compressing the same. 01531 // Here we just update the compression counter. 01532 01533 _counter += ( BITS_29_00 & value ) ; 01534 01535 } else { 01536 01537 // Since we were compressing "something" different, 01538 // first we have to flash it and then start 01539 // compressing new stuff. 01540 01541 status = synchronize() ; 01542 if ( status != BdbcSuccess ) { 01543 return status ; 01544 } 01545 01546 _isCompressing = true ; 01547 _isZero = ( BITS_30 != ( BITS_30 & value )) ; 01548 _counter = ( BITS_29_00 & value ) ; 01549 01550 } 01551 01552 } else { 01553 01554 // Start compressing new stuff. 01555 01556 _isCompressing = true ; 01557 _isZero = ( BITS_30 != ( BITS_30 & value )) ; 01558 _counter = ( BITS_29_00 & value ) ; 01559 01560 } 01561 01562 } else { 01563 01564 // Check if it's the last uncompleted word of the bit string, 01565 // having other then 30 "usefull" bits. 01566 // In this case we just flush the existing compression and flush 01567 // this last word as well. 01568 // Otherwise we will try to make a routine compression if possible. 01569 01570 if ( rem30 ) { 01571 01572 if ( _isCompressing ) { 01573 01574 status = synchronize() ; 01575 if ( status != BdbcSuccess ) { 01576 return status ; 01577 } 01578 } 01579 01580 // Select meaningfull bits only. 01581 01582 d_ULong usefull_bits = 0 ; 01583 01584 for ( d_ULong i = 0 ; i < rem30 ; i++ ) { 01585 usefull_bits = ( 1 << i ) | usefull_bits ; 01586 } 01587 01588 value = usefull_bits & value ; 01589 01590 // Then imediatelly flash the new value. 01591 01592 status = _out.extend(value) ; 01593 if ( status != BdbcSuccess ) { 01594 return status ; 01595 } 01596 01597 } else { 01598 01599 // Possible to compress this word? 01600 01601 if (( BITS_29_00 == ( BITS_29_00 & value )) || ( ! value )) { 01602 01603 if ( _isCompressing ) { 01604 01605 // Are we compressing the same ("0" or "1")? 01606 01607 if ((( _isZero ) && ( ! value )) 01608 || 01609 (( ! _isZero ) && ( value ))) { 01610 01611 // Yes. We are already compressing the same. 01612 // Here we just update the compression counter. 01613 01614 _counter += 30 ; 01615 01616 } else { 01617 01618 // Since we were compressing "something" different, 01619 // first we have to flash it and then start 01620 // compressing new stuff. 01621 01622 status = synchronize() ; 01623 if ( status != BdbcSuccess ) { 01624 return status ; 01625 } 01626 01627 _isCompressing = true ; 01628 _isZero = ! value ; 01629 _counter = 30 ; 01630 01631 } 01632 } else { 01633 01634 // Start compressing new stuff. 01635 01636 _isCompressing = true ; 01637 _isZero = ! value ; 01638 _counter = 30 ; 01639 01640 } 01641 01642 } else { 01643 01644 // Compressing is not possible. 01645 // If we are already compressing somthing, we should 01646 // flash compression buffer before to flush the temporary one. 01647 01648 status = synchronize() ; 01649 if ( status != BdbcSuccess ) { 01650 return status ; 01651 } 01652 01653 // Then imediatelly flash the new value. 01654 01655 status = _out.extend(value) ; 01656 if ( status != BdbcSuccess ) { 01657 return status ; 01658 } 01659 } 01660 } 01661 } 01662 01663 // DEBUG: cout << "CompressionContext: value = " << value 01664 // << " _counter = " << _counter << endl ; 01665 // DEBUG: cout << " _out.size() =" << (d_ULong) _out.size() << endl ; 01666 01667 return BdbcSuccess ; 01668 } 01669 01670 BdbStatus 01671 BdbBMIndexQueryAPI::CompressionContext::synchronize() 01672 { 01673 BdbStatus status ; 01674 01675 // If we are already compressing somthing, we should 01676 // flash compression buffer. 01677 01678 if ( _isCompressing ) { 01679 01680 if ( _isZero ) { 01681 _counter = BITS_31 | _counter ; 01682 } else { 01683 _counter = BITS_31_30 | _counter ; 01684 } 01685 01686 status = _out.extend(_counter) ; 01687 if ( status != BdbcSuccess ) { 01688 return status ; 01689 } 01690 01691 _isCompressing = false ; 01692 } 01693 01694 return BdbcSuccess ; 01695 } 01696 01697 ///////////////// 01698 // End Of File // 01699 /////////////////
BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us
Page Owner: Jacek Becla
Last Update: October 04, 2002