![]() |
|
|
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 /BdbEventStore/BdbEventStore.cc
Go to the documentation of this file.00001 //-------------------------------------------------------------------------- 00002 // File and Version Information: 00003 // $Id: BdbEventStore.cc,v 1.103 2002/06/21 21:56:54 becla Exp $ 00004 // 00005 // Description: 00006 // Class BdbEventStore implementation file. This class represents the 00007 // BaBar database application event store domain. 00008 // 00009 // Environment: 00010 // Software developed for the BaBar Detector at the SLAC B-Factory. 00011 // 00012 // Author List: 00013 // David R. Quarrie Original Author 00014 // 00015 // History: 00016 // 00017 //------------------------------------------------------------------------ 00018 //----------------------- 00019 // This Class's Header -- 00020 //----------------------- 00021 #include "BdbEventStore/BdbEventStore.hh" 00022 00023 //------------- 00024 // C Headers -- 00025 //------------- 00026 extern "C" { 00027 #include <assert.h> 00028 #include <stddef.h> 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <unistd.h> 00033 } 00034 00035 //--------------- 00036 // C++ Headers -- 00037 //--------------- 00038 #include <iostream.h> 00039 00040 //------------------------------- 00041 // Collaborating Class Headers -- 00042 //------------------------------- 00043 #include "ErrLogger/ErrLog.hh" 00044 #include "BdbUtil/BdbPathName.hh" 00045 #include "BdbDomainOODB/BdbDomainOODB.hh" 00046 #include "BdbApplication/BdbDebug.hh" 00047 #include "BdbApplication/BdbRWMultiInhibitPolicy.hh" 00048 #include "BdbApplication/BdbEvsFSNamesStr.hh" 00049 #include "BdbAccess/BdbAuth.hh" 00050 #include "BdbAccess/BdbSingleBootInhibitFactory.hh" 00051 #include "BdbAccess/BdbDbTreeSingleton.hh" 00052 #include "BdbClustering/BdbEvsClusteringHint.hh" 00053 #include "BdbClustering/BdbSpClusteringHint.hh" 00054 #include "BdbEvent/BdbEventT.hh" 00055 #include "BdbEvent/BdbEventTag.hh" 00056 #include "BdbEventStore/BdbCollectionTCollTIterator.hh" 00057 #include "BdbEventStore/BdbEventStoreErrors.hh" 00058 #include "BdbEventStore/BdbEventStoreIterator.hh" 00059 #include "BdbEventStore/BdbFetchCollTFactory.hh" 00060 #include "BdbEventStore/BdbCollectionTFactory.hh" 00061 #include "BdbEventStore/BdbBridgeCollTIterator.hh" 00062 #include "BdbEventStore/BdbTreeCollTIterator.hh" 00063 #include "BdbEventStore/BdbVectorCollTIterator.hh" 00064 #include "BdbEventStore/BdbCollectionTIterator.hh" 00065 #include "BdbEventStore/BdbBridgeCollectionT.hh" 00066 #include "BdbEventStore/BdbTreeCollectionT.hh" 00067 #include "BdbEventStore/BdbVectorCollectionT.hh" 00068 #include "BdbEventStore/BdbTreeNodeCollectionTIterator.hh" 00069 #include "BdbTrees/BdbDbRegistrator.hh" 00070 #include "BdbEventStore/BdbCollTItemIterator.hh" 00071 00072 00073 //----------------------------------------------------------------------- 00074 // Local Macros, Typedefs, Structures, Unions and Forward Declarations -- 00075 //----------------------------------------------------------------------- 00076 00077 static const char rcsid[] = "$Id: BdbEventStore.cc,v 1.103 2002/06/21 21:56:54 becla Exp $"; 00078 00079 // ------------------------------------ 00080 // -- Static Data Member Definitions -- 00081 // ------------------------------------ 00082 00083 BdbEventStore* BdbEventStore::_instance = 0; 00084 00085 d_Boolean BdbEventStore::_isClusteringConfigured( d_False ); 00086 d_Boolean BdbEventStore::_ownsClustering( d_False ); 00087 d_Boolean BdbEventStore::_useNestedCollTrans( 0 == getenv("BDB_NO_NESTED_COLL_TRANS") ); 00088 00089 BdbAbstractClusteringHint* BdbEventStore::_nodeHint( 0 ); 00090 BdbAbstractClusteringHint* BdbEventStore::_treeCollHint( 0 ); 00091 BdbAbstractClusteringHint* BdbEventStore::_vecCollHint( 0 ); 00092 BdbAbstractClusteringHint* BdbEventStore::_bridgeCollHint( 0 ); 00093 00094 // ---------------------------------------- 00095 // -- Static Function Member Definitions -- 00096 // ---------------------------------------- 00097 00098 //---------- 00099 // Public -- 00100 //---------- 00101 00102 bool 00103 BdbEventStore::exists( ) 00104 { 00105 bool result = ( 0 != _instance ); 00106 return result; 00107 } 00108 00109 BdbEventStore* 00110 BdbEventStore::instance( ) 00111 { 00112 if ( 0 == _instance ) { 00113 _instance = new BdbEventStore( ); 00114 00115 static BdbDbRegistrator registrator; 00116 BdbDbTreeSingleton::instance()->setRegistrator(®istrator); 00117 if ( ! _instance->hasInhibitPolicy( ) ) { 00118 _instance->setInhibitPolicy( new BdbRWMultiInhibitPolicy( new BdbSingleBootInhibitFactory() ) ); 00119 } 00120 } 00121 return _instance; 00122 } 00123 00124 d_Boolean 00125 BdbEventStore::useNestedCollTrans() 00126 { 00127 return _useNestedCollTrans; 00128 } 00129 00130 00131 // ---------------------------------------- 00132 // -- Public Function Member Definitions -- 00133 // ---------------------------------------- 00134 00135 //------------------ 00136 // Constructor(s) -- 00137 //------------------ 00138 00139 const size_t kInitialRetainedLength( 2 ); 00140 00141 BdbEventStore::BdbEventStore( ) 00142 : BdbDomain( Events, BdbDomainOODB::Optional ), 00143 _intermediateNodes( d_True ) , 00144 _retainedList( new RetainedToken[ kInitialRetainedLength ] ) , 00145 _retainedDepth( 0 ) , 00146 _retainedLength( kInitialRetainedLength ) , 00147 _lastPath( 0 ) 00148 { 00149 setStrategyObj(new BdbEvsFSNamesStr); 00150 setInitialAuthLevel( User ); 00151 } 00152 00153 //-------------- 00154 // Destructor -- 00155 //-------------- 00156 00157 BdbEventStore::~BdbEventStore( ) 00158 { 00159 } 00160 00161 //------------------------------------ 00162 // Federation retention and release -- 00163 // ----------------------------------- 00164 00165 BdbTransToken 00166 BdbEventStore::currentTrans() const 00167 { 00168 return( currentTransToken() ); 00169 } 00170 00171 size_t 00172 BdbEventStore::findRetainedTrans( const BdbTransToken& token ) const 00173 { 00174 size_t index( 0 ); 00175 while( ( _retainedDepth != index ) && 00176 ( token != (_retainedList[ index ])._token ) ) { 00177 index++; 00178 } 00179 00180 return( index ); 00181 } 00182 00183 BdbTransToken 00184 BdbEventStore::retainTrans() 00185 { 00186 const BdbTransToken token( currentTrans() ); 00187 00188 if( BdbcInValidTransToken == token ) { 00189 ErrMsg( fatal ) << "There is no valid transaction for this domain" 00190 << endmsg; 00191 ::abort(); 00192 } 00193 00194 size_t index( findRetainedTrans( token ) ); 00195 00196 // If already in the list increase count 00197 if( _retainedDepth != index ) { 00198 (_retainedList[ index ])._count++; 00199 00200 // If count was originally zero, re-hold the transaction 00201 if( 1 == ((_retainedList[ index ])._count) ) { 00202 holdCurrentTrans(); 00203 } 00204 return( _retainedList[ index ]._token ); 00205 } 00206 00207 // Expand the list if necessary 00208 if( _retainedDepth == _retainedLength ) { 00209 RetainedToken* newList = new RetainedToken[ _retainedLength * 2 ]; 00210 memcpy( newList , 00211 _retainedList , 00212 _retainedLength * sizeof( RetainedToken ) ); 00213 delete [] _retainedList; 00214 _retainedList = newList; 00215 _retainedLength = _retainedLength * 2; 00216 } 00217 00218 // place transaction into retained list 00219 _retainedList[ _retainedDepth ]._token = token; 00220 _retainedList[ _retainedDepth ]._count = 1; 00221 _retainedDepth++; 00222 00223 // hold the Transaction 00224 holdCurrentTrans(); 00225 00226 return( token ); 00227 } 00228 00229 void 00230 BdbEventStore::releaseTrans( const BdbTransToken& token ) 00231 { 00232 size_t index( findRetainedTrans( token ) ); 00233 00234 // If not in the list then abort 00235 if( _retainedDepth == index ) { 00236 ErrMsg( fatal ) << "Can not release and transaction when it has not" 00237 << " been retained" 00238 << endmsg; 00239 ::abort(); 00240 } 00241 00242 // decrement count and finished is still retained 00243 (_retainedList[ index ])._count--; 00244 if( 0 != (_retainedList[ index ])._count ) { 00245 return; 00246 } 00247 00248 // If we are releasing the current transaction simply unlock it and 00249 // finish. 00250 if( token == currentTrans() ) { 00251 dropCurrentTrans(); 00252 return; 00253 } 00254 00255 // Otherwise lock the current transaction if necessary, unlock the 00256 /// requested transaction and the retore the original 00257 bool tempLock( false ); 00258 if( !currentTransIsHeld() ) { 00259 holdCurrentTrans(); 00260 tempLock = !false; 00261 } 00262 00263 const BdbTransToken originalToken( setCurrentTrans( token ) ); 00264 dropCurrentTrans(); 00265 setCurrentTrans( originalToken ); 00266 00267 if( tempLock ) { 00268 dropCurrentTrans(); 00269 } 00270 } 00271 00272 BdbTransToken 00273 BdbEventStore::setCurrentTrans( const BdbTransToken& token ) 00274 { 00275 BdbTransToken originalToken( currentTransToken() ); 00276 BdbDomain::setCurrentTrans( token ); 00277 return( originalToken ); 00278 } 00279 00280 void 00281 BdbEventStore::changeDefaultFed( const char* name ) 00282 { 00283 // If the requested federation matches the current one do nothing. 00284 if( 0 == strcmp( bootName() , 00285 name ) ) { 00286 return; 00287 } 00288 00289 setLastPath( 0 ); 00290 setDefaultBootName( name ); 00291 } 00292 00293 void 00294 BdbEventStore::newEvsTrans( const char* name ) 00295 { 00296 changeDefaultFed( name ); 00297 newCurrentTrans(); 00298 } 00299 00300 // phase 3.3 extension to allow creation of output transaction 00301 // associated with a different federation 00302 // 00303 BdbTransToken BdbEventStore::createOutputTrans(const char *bootName){ 00304 00305 BdbTransToken originalTrans(currentTrans()); 00306 newCurrentTrans(bootName); 00307 retainTrans(); 00308 return (originalTrans); 00309 00310 } 00311 00312 //--------------------------------------------- 00313 // General Selectors, Modifiers & Operations -- 00314 // -------------------------------------------- 00315 00316 void 00317 BdbEventStore::configureClustering( ) 00318 { 00319 BdbAbstractClusteringHint* treeCollHint; 00320 BdbAbstractClusteringHint* vecCollHint; 00321 BdbAbstractClusteringHint* bridgeCollHint; 00322 00323 if ( ! _isClusteringConfigured ) { 00324 00325 activate(); 00326 00327 // Setup clustering hints for the Tree Nodes 00328 _nodeHint = new BdbSpClusteringHint( *this ); 00329 _nodeHint->setComponent( "nod" ); 00330 BdbHintSetDelegate( BdbTreeNodeP, _nodeHint ); 00331 00332 // Setup clustering hints for the Collections 00333 treeCollHint = new BdbEvsClusteringHint( *this ); 00334 vecCollHint = new BdbEvsClusteringHint( *this ); 00335 bridgeCollHint = new BdbEvsClusteringHint( *this ); 00336 treeCollHint->setComponent( "col" ); 00337 vecCollHint->setComponent( "col" ); 00338 this->configureClustering( treeCollHint , 00339 vecCollHint , 00340 bridgeCollHint); 00341 _ownsClustering = d_True; 00342 00343 deactivate(); 00344 00345 _isClusteringConfigured = d_True; 00346 } 00347 } 00348 00349 void 00350 BdbEventStore::configureClustering( BdbAbstractClusteringHint* aTreeCollHint , 00351 BdbAbstractClusteringHint* aVecCollHint , 00352 BdbAbstractClusteringHint* aBridgeCollHint ) 00353 { 00354 if ( _ownsClustering ) { 00355 delete _treeCollHint; 00356 delete _vecCollHint; 00357 delete _bridgeCollHint; 00358 _ownsClustering = d_False; 00359 } 00360 00361 _treeCollHint = aTreeCollHint; 00362 BdbHintSetDelegate( BdbTreeCollectionP, _treeCollHint ); 00363 _vecCollHint = aVecCollHint; 00364 BdbHintSetDelegate( BdbVectorCollectionP, _vecCollHint ); 00365 _bridgeCollHint = aVecCollHint; 00366 BdbHintSetDelegate( BdbBridgeCollectionP, _bridgeCollHint ); 00367 } 00368 00369 00370 bool 00371 BdbEventStore::isAccessAllowed( const char* userName ) const 00372 { 00373 BdbAuth* theAuth = BdbAuth::instance( ); 00374 activate(); 00375 bool result( theAuth->isAccessAllowed( Events, userName ) ); 00376 deactivate(); 00377 return result; 00378 } 00379 00380 BdbStatus 00381 BdbEventStore::readAttempt( BdbHandleAny& theObj ) 00382 { 00383 BdbStatus result; 00384 d_Long oldWait = lockWait( ); 00385 setLockWait( BdbcNoWait ); 00386 result = theObj.open( BdbcRead ); 00387 setLockWait( oldWait ); 00388 return result; 00389 } 00390 00391 //------------------------------------------------ 00392 // Collection Selectors, Modifiers & Operations -- 00393 // ----------------------------------------------- 00394 BdbAbsCollectionT< BdbEventT >* 00395 BdbEventStore::collection( const char* theCollPath, 00396 const BdbEventT&, 00397 bool allowNestedCollTrans ) 00398 { 00399 bool useNestedCollTrans( ( _useNestedCollTrans ) && 00400 ( allowNestedCollTrans ) ); 00401 00402 BdbAbsCollectionT< BdbEventT >* theTransient( 0 ); 00403 00404 char* theCollStem = BdbPathName::stem( theCollPath, 00405 true); 00406 char* theNodePath = BdbPathName::absolute( validLastPath() , 00407 theCollStem ); 00408 delete [] theCollStem; 00409 00410 if( useNestedCollTrans ) { 00411 startNestedUpdate(); 00412 } 00413 BdbTreeNode collectionNode; 00414 BdbStatus result = treeNode( collectionNode, theNodePath ); 00415 if ( BdbcSuccess == result ) { 00416 00417 // Ok, the node exists, now see whether the specified collection 00418 // exists. The following code attempts to locate the collection 00419 // by name, and checks that the returned object is of the 00420 // desired type. 00421 const char* theCollName = BdbPathName::leaf( theCollPath ); 00422 ooTypeNumber theTypes[] = { 00423 ooTypeN(BdbCollectionP) , 00424 ooTypeN(BdbTreeCollectionP) , 00425 ooTypeN(BdbVectorCollectionP) , 00426 ooTypeN(BdbBridgeCollectionP) 00427 }; 00428 BdbHandle(BdbCollectionP) theCollP; 00429 result = collectionNode.child( theCollP, theCollName, theTypes, 4 ); 00430 delete [] theCollName; 00431 if ( BdbcSuccess == result ) { 00432 theTransient = getCollection( theCollP ); 00433 } 00434 } 00435 if( 0 != theTransient ) { 00436 if( useNestedCollTrans ) { 00437 theTransient->invalidateCachedHandle(); 00438 } 00439 setLastPath( theNodePath ); 00440 } else { 00441 delete [] theNodePath; 00442 } 00443 00444 if( useNestedCollTrans ) { 00445 commitNested(); 00446 } 00447 00448 return theTransient; 00449 } 00450 00451 00452 BdbAbsCollectionT< BdbEventT >* 00453 BdbEventStore::getCollection( BdbHandle( BdbCollectionP )& thePersistent ) 00454 { 00455 // There is a problem with using ooIsKindOf, which would be the 00456 // "correct" approach. Using this puts a read lock on the returned 00457 // item, which can cause unnecessary interference. The following list 00458 // should contain the Type Numbers for all known subclasses of the 00459 // BdbCollectionP persistent collection base class. This is obviously 00460 // not ideal since this list will have to be maintained by hand. 00461 ooTypeNumber theTypes[] = { 00462 ooTypeN(BdbCollectionP) , 00463 ooTypeN(BdbTreeCollectionP) , 00464 ooTypeN(BdbVectorCollectionP) , 00465 ooTypeN(BdbBridgeCollectionP) 00466 }; 00467 ooTypeNumber persistentType( thePersistent.typeN( ) ); 00468 if( persistentType == theTypes[1] ) { 00469 return( new BdbTreeCollectionT<BdbEventT>( (BdbHandle(BdbTreeCollectionP)&)thePersistent ) ); 00470 } else if ( persistentType == theTypes[2] ) { 00471 return( new BdbVectorCollectionT<BdbEventT>( (BdbHandle(BdbVectorCollectionP)&)thePersistent ) ); 00472 } else if ( persistentType == theTypes[3] ) { 00473 return( new BdbBridgeCollectionT<BdbEventT>( (BdbHandle(BdbBridgeCollectionP)&)thePersistent ) ); 00474 } 00475 return( 0 ); 00476 } 00477 00478 00479 00480 BdbCollectionTIterator< BdbEventT >* 00481 BdbEventStore::getIterator( BdbAbsCollectionT< BdbEventT >& theDescrOverrideTarget , 00482 BdbHandle( BdbCollectionP )& thePersistent , 00483 d_ULong initialIndex ) 00484 { 00485 // There is a problem with using ooIsKindOf, which would be the 00486 // "correct" approach. Using this puts a read lock on the returned 00487 // item, which can cause unnecessary interference. The following list 00488 // should contain the Type Numbers for all known subclasses of the 00489 // BdbCollectionP persistent collection base class. This is obviously 00490 // not ideal since this list will have to be maintained by hand. 00491 ooTypeNumber theTypes[] = { 00492 ooTypeN(BdbCollectionP) , 00493 ooTypeN(BdbTreeCollectionP) , 00494 ooTypeN(BdbVectorCollectionP) , 00495 ooTypeN(BdbBridgeCollectionP) 00496 }; 00497 ooTypeNumber persistentType( thePersistent.typeN( ) ); 00498 if( persistentType == theTypes[1] ) { 00499 return( new BdbTreeCollTIterator<BdbEventT>( theDescrOverrideTarget , 00500 (BdbHandle(BdbTreeCollectionP)&)thePersistent , 00501 initialIndex ) ); 00502 } else if ( persistentType == theTypes[2] ) { 00503 return( new BdbVectorCollTIterator<BdbEventT>( theDescrOverrideTarget , 00504 (BdbHandle(BdbVectorCollectionP)&)thePersistent , 00505 initialIndex ) ); 00506 } else if ( persistentType == theTypes[3] ) { 00507 return( new BdbBridgeCollTIterator<BdbEventT>( theDescrOverrideTarget , 00508 (BdbHandle(BdbBridgeCollectionP)&)thePersistent , 00509 initialIndex ) ); 00510 } 00511 return( 0 ); 00512 } 00513 00514 00515 BdbStatus 00516 BdbEventStore::moveCollection( BdbAbsCollectionT<BdbEventT>*& theCollection, 00517 const char* const theCollPath ) 00518 // Move an existing collection to the specified collection path name. 00519 { 00520 char* theCollName = BdbPathName::leaf( theCollPath ); 00521 BdbStatus result = BdbcError; 00522 00523 // Check for valid name 00524 if ( 0 != theCollName ) { 00525 00526 // New name is valid - remove the collection from event store but don't delete it 00527 result = removeCollection( theCollection, d_True ); 00528 if ( BdbcSuccess == result ) { 00529 00530 char* theCollStem = BdbPathName::stem( theCollPath, 00531 true ); 00532 char* theNodePath = BdbPathName::absolute( validLastPath() , 00533 theCollStem ); 00534 delete [] theCollStem; 00535 00536 AuthLevels theAuthLevel = getAuthLevel ( theNodePath ); 00537 const char* theAuthName = getAuthName ( theNodePath ); 00538 00539 // Check that we have update access to the new location 00540 if ( setAuthLevel( theAuthLevel, theAuthName ) ) { 00541 00542 // Update access granted. 00543 // Fetch the node, creating it if necessary. 00544 // BdbTreeNode origNode = currentNode(); 00545 BdbTreeNode collectionNode; 00546 result = fetchTreeNode( collectionNode, theNodePath ); 00547 if ( BdbcSuccess == result ) { 00548 00549 // Now we have to lock both the collection 00550 // and tree node for update in order to be sure that we 00551 // have sole update access to them both. 00552 BdbHandle(BdbCollectionP) theCollP = theCollection->persistent( ); 00553 BdbHandle(BdbTreeNodeP) theNodeP = collectionNode.persistent( ); 00554 BdbHandleAny theHandles[2]; 00555 theHandles[0] = theCollP; 00556 theHandles[1] = theNodeP; 00557 BdbDomain* theApp = BdbDomain::activeInstance( ); 00558 result = updateAndWait( theHandles, 2, 00559 BdbDomain::DomainNames[BdbDomain::Events] ); 00560 if ( BdbcSuccess == result ) { 00561 00562 // Now we have sole access. Check that no-one else has created 00563 // an item with the same name while we were waiting for the 00564 // update locks 00565 result = theNodeP->hasChild( theCollName ); 00566 if ( BdbcSuccess != result ) { 00567 00568 // Collection doesn't already exist - create it 00569 theCollP->setCollName( theCollName ); 00570 theCollP->setTreeNode( theNodeP ); 00571 result = theNodeP->add( theCollP, theCollName ); 00572 } 00573 } else { 00574 BdbSignal( BdbcUserError, BdbEventStoreErrUnableToUpdate, 0, 00575 "BdbEventStore::moveCollection", theCollName ); 00576 } 00577 } 00578 if ( BdbcSuccess == result ) { 00579 setLastPath( theNodePath ); 00580 theNodePath = 0; 00581 } 00582 } 00583 delete [] theNodePath; 00584 } 00585 } else { 00586 BdbSignal( BdbcUserError, BdbEventStoreErrCollectionNotNamed, 0, 00587 "BdbEventStore::moveCollection" ); 00588 } 00589 delete [] theCollName; 00590 return result; 00591 } 00592 00593 BdbStatus 00594 BdbEventStore::removeCollection( BdbAbsCollectionT<BdbEventT>*& theCollection, 00595 d_Boolean bypassDelete ) 00596 { 00597 BdbStatus result = BdbcError; 00598 if ( 0 != theCollection && ! theCollection->isNull( ) ) { 00599 00600 // Check whether the we have privilege to remove this collection 00601 const char* theFullName = theCollection->pathName( ); 00602 char* theNodePath = BdbPathName::stem( theFullName ); 00603 AuthLevels theAuthLevel = getAuthLevel ( theNodePath ); 00604 const char* theAuthName = getAuthName ( theNodePath ); 00605 delete [] theNodePath; 00606 00607 if ( setAuthLevel( theAuthLevel, theAuthName ) ) { 00608 00609 // Remove the collection from the event store 00610 BdbTreeNode theNode; 00611 result = theCollection->treeNode( theNode ); 00612 if ( BdbcSuccess == result ) { 00613 theNode.remove( theCollection->name( ) ); 00614 } 00615 if ( ! bypassDelete ) { 00616 theCollection->setDeleted( ); 00617 } 00618 result = BdbcSuccess; 00619 } 00620 } 00621 return result; 00622 } 00623 00624 BdbStatus 00625 BdbEventStore::removeCollection( const char* const theCollPath, d_Boolean bypassDelete ) 00626 { 00627 BdbStatus result = BdbcError; 00628 BdbAbsCollectionT<BdbEventT>* theCollection = collection( theCollPath, (*(BdbEventT*)0) ); 00629 if ( 0 != theCollection ) { 00630 result = removeCollection( theCollection, bypassDelete ); 00631 } 00632 return result; 00633 } 00634 00635 00636 BdbStatus 00637 BdbEventStore::fetchCollection( BdbAbsCollectionT<BdbEventT>*& theCollection, 00638 const char* const theCollPath, 00639 BdbCollectionTFactory<BdbEventT>& factory, 00640 d_ULong initialSize ) 00641 // Locate Collection for the specified collection path name, creating 00642 // it as a tree collection if it doesn't already exist. Note that we use 00643 // a pessimistic algorithm for determining whether the user has adequate 00644 // authorization rights to create the collection. If they don't have 00645 // adequate rights the request will fail even if the specified collection 00646 // already exists. This assumes that their intent in using this function 00647 // is to add to the specified collection. 00648 { 00649 BdbStatus result( BdbcError ); 00650 theCollection = 0; 00651 00652 char* theFullCollName = BdbPathName::absolute( validLastPath(), 00653 theCollPath ); 00654 BdbFetchCollTFactory< BdbEventT > factoryToUse( factory ); 00655 theCollection = factoryToUse.getCollection( theFullCollName, initialSize ); 00656 00657 if ( ( 0 != theCollection ) && (! theCollection->isNull( ) ) ) { 00658 result = BdbcSuccess; 00659 } 00660 00661 delete [] theFullCollName; 00662 00663 return result; 00664 } 00665 00666 00667 //----------------------------------------------- 00668 // Tree-Node Selectors, Modifiers & Operations -- 00669 // ---------------------------------------------- 00670 00671 BdbStatus 00672 BdbEventStore::fetchTreeNode( BdbTreeNode& theNode, 00673 const char* const theNodePath ) 00674 // Fetch and create if necessary the tree-node for the specified 00675 // node path name. 00676 // Note that we use a pessimistic algorithm for determining whether the user 00677 // has adequate authorization rights to create the node. If they don't have 00678 // adequate rights the request will fail even if the specified node 00679 // already exists. This assumes that their intent in using this function 00680 // is to add to the specified node. 00681 { 00682 AuthLevels theAuthLevel = getAuthLevel ( theNodePath ); 00683 const char* theAuthName = getAuthName ( theNodePath ); 00684 BdbTreeNode origNode = theNode; 00685 BdbStatus result = BdbcError; 00686 00687 if ( setAuthLevel( theAuthLevel, theAuthName ) ) { 00688 result = treeNode( theNode, theNodePath ); 00689 if ( BdbcSuccess != result ) { 00690 result = createTreeNode( theNode, theNodePath ); 00691 } 00692 } 00693 if ( BdbcSuccess != result ) { 00694 theNode = origNode; 00695 } 00696 return result; 00697 } 00698 00699 BdbStatus 00700 BdbEventStore::fetchTreeNode( BdbTreeNode& theNode, 00701 AuthLevels theAuthLevel, 00702 const char* const theAuthName ) 00703 // Fetch and create if necessary the top-level tree-node for the specified 00704 // authorization level and name. 00705 // Note that we use a pessimistic algorithm for determining whether the user 00706 // has adequate authorization rights to create the node. If they don't have 00707 // adequate rights the request will fail even if the specified node 00708 // already exists. This assumes that their intent in using this function 00709 // is to add to the specified node. 00710 { 00711 assert( isAuthLevelValid( theAuthLevel ) ); 00712 BdbTreeNode origNode = theNode; 00713 BdbStatus result = BdbcError; 00714 00715 if ( setAuthLevel( theAuthLevel, theAuthName ) ) { 00716 result = treeNode( theNode, theAuthLevel, theAuthName ); 00717 if ( BdbcSuccess != result ) { 00718 result = createTreeNode( theNode, theAuthLevel, theAuthName ); 00719 } 00720 } 00721 if ( BdbcSuccess != result ) { 00722 theNode = origNode; 00723 } 00724 return result; 00725 } 00726 00727 BdbStatus 00728 BdbEventStore::treeNode( BdbTreeNode& theNode, 00729 const char* const theNodePath ) 00730 // Locate the tree-node for the specified node path name. 00731 { 00732 BdbStatus result = BdbcSuccess; 00733 if ( ( 0 == theNodePath ) || ( '/' != *theNodePath ) ) { 00734 00735 // Relative path - Move to initial default location if necessary. 00736 if ( theNode.isNull( ) ) { 00737 result = treeNode( theNode, User ); 00738 } 00739 } 00740 if ( BdbcSuccess == result ) { 00741 result = theNode.moveTo( theNodePath ); 00742 } 00743 return result; 00744 } 00745 00746 BdbStatus 00747 BdbEventStore::treeNode( BdbTreeNode& theNode, 00748 AuthLevels theAuthLevel, 00749 const char* const theAuthName ) 00750 // Locate the top-level tree-node for the specified authorization level 00751 // & name. 00752 { 00753 assert( isAuthLevelValid( theAuthLevel ) ); 00754 const char* topName = authLevelName( theAuthLevel ); 00755 const char* useName = useAuthName( theAuthLevel, theAuthName ); 00756 BdbStatus result = theNode.moveToRootChild( topName ); 00757 if ( ( BdbcSuccess == result ) && ( 0 != useName ) ) { 00758 result = theNode.moveTo( useName ); 00759 } 00760 return result; 00761 } 00762 00763 //------------- 00764 // Operators -- 00765 //------------- 00766 00767 // ------------------------------------------- 00768 // -- Protected Function Member Definitions -- 00769 // ------------------------------------------- 00770 00771 void 00772 BdbEventStore::initialize( ) 00773 { 00774 } 00775 00776 bool 00777 BdbEventStore::isAuthorized( AuthLevels theAuthLevel, 00778 const char* const theAuthName ) 00779 { 00780 assert( isAuthLevelValid( theAuthLevel ) ); 00781 BdbAuth* theAuth = BdbAuth::instance( ); 00782 activate(); 00783 bool result( theAuth->isAuthorized( domain(), 00784 theAuthLevel, 00785 theAuthName ) ); 00786 deactivate(); 00787 return result; 00788 } 00789 00790 BdbStatus 00791 BdbEventStore::createTreeNode( BdbTreeNode& theNode, 00792 const char* const theNodePath ) 00793 // Create the tree-node for the specified tree-node path name 00794 { 00795 AuthLevels theAuthLevel = getAuthLevel( theNodePath ); 00796 const char* theAuthName = getAuthName ( theNodePath ); 00797 BdbStatus result; 00798 00799 result = createTreeNode( theNode, theAuthLevel, theAuthName ); 00800 if ( BdbcSuccess == result ) { 00801 // Top-level tree-node exists - walk down node tree 00802 const char* theRelPath = skipAuthName( theNodePath ); 00803 result = theNode.makeTo( theRelPath, _intermediateNodes ); 00804 } 00805 return result; 00806 } 00807 00808 BdbStatus 00809 BdbEventStore::createTreeNode( BdbTreeNode& theNode, 00810 AuthLevels theAuthLevel, 00811 const char* const theAuthName ) 00812 // Create the top-level tree-node for the specified authorization level & name 00813 { 00814 BdbTreeNode aNode; 00815 BdbStatus result = BdbcError; 00816 00817 assert( isAuthLevelValid( theAuthLevel ) ); 00818 const char* useName = useAuthName( theAuthLevel, theAuthName ); 00819 00820 theNode.setNull( ); 00821 00822 // Check whether the top-most tree node exists & create it if necessary 00823 const char* topName = authLevelName( theAuthLevel ); 00824 result = aNode.makeRootChild( topName ); 00825 if ( ( BdbcSuccess == result ) && ( 0 != useName ) ) { 00826 result = aNode.makeTo( useName, _intermediateNodes ); 00827 } 00828 if ( BdbcSuccess == result ) { 00829 BdbHandle(BdbTreeNodeP) aNodeP = aNode.persistent( ); 00830 theNode.setPersistent( aNodeP ); 00831 } 00832 return result; 00833 } 00834 00835 00836 void 00837 BdbEventStore::removeCollection( BdbTreeNode& theNode, 00838 BdbAbsCollectionT<BdbEventT>*& theCollection ) 00839 // Search collections in the specified tree node for other collections that 00840 // the specified collection has been added to, removing it from them prior to 00841 // removing the collection itself from the event store. 00842 { 00843 BdbAbsCollectionT<BdbEventT>* aCollection; 00844 BdbTreeNode aNode; 00845 BdbStatus status; 00846 00847 // Iterate over collections in this node 00848 BdbTreeNodeCollectionTIterator nodeIter( theNode ); 00849 00850 while ( BdbcSuccess == ( status = nodeIter.nextCollection( aCollection ) ) ) { 00851 if ( *theCollection == *aCollection ) { 00852 00853 // Remove the collection itself from this node 00854 BdbHandle(BdbCollectionP) theCollP = theCollection->persistent( ); 00855 status = theNode.remove( theCollP ); 00856 } else { 00857 00858 // Attempt to remove the collection from the other collection 00859 status = aCollection->removeCollection( *theCollection ); 00860 } 00861 } 00862 00863 // Iterate over child nodes 00864 while ( BdbcSuccess == ( status = nodeIter.next( aNode ) ) ) { 00865 removeCollection( aNode, theCollection ); 00866 } 00867 } 00868 00869 const char* 00870 BdbEventStore::validLastPath() const 00871 { 00872 if( 0 != _lastPath ) { 00873 return( _lastPath ); 00874 } 00875 00876 const char* topName = authLevelName( User ); 00877 const char* useName = const_cast< BdbEventStore* >( this )->useAuthName( User, 0 ); 00878 // need four extra char for three separators and the trminating '\0' 00879 size_t lengthTopName( strlen( topName ) ); 00880 size_t lengthUseName( strlen( useName ) ); 00881 char* result( new char[ lengthTopName + lengthUseName + 4 ] ); 00882 const char localSeparator( BdbPathName::separator() ); 00883 result[ 0 ] = localSeparator; 00884 strcpy( result + 1, topName ); 00885 result[ lengthTopName + 1 ] = localSeparator; 00886 strcpy( result + lengthTopName + 2, useName ); 00887 result[ lengthTopName + lengthUseName + 2 ] = localSeparator; 00888 result[ lengthTopName + lengthUseName + 3 ] = '\0'; 00889 // _lastPath should really be mutable 00890 const_cast< BdbEventStore* >( this )->_lastPath = result; 00891 return( result ); 00892 } 00893 00894 void 00895 BdbEventStore::setLastPath( char* lastPath ) 00896 { 00897 delete [] _lastPath; 00898 _lastPath = lastPath; 00899 } 00900
BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us
Page Owner: Jacek Becla
Last Update: October 04, 2002