Bdb packages | Design docs | Source docs | Guidelines | Recent releases

Search | Site Map .

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(&registrator);
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