![]() |
|
|
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 /BdbTrees/BdbTreeNode.cc
Go to the documentation of this file.00001 //-------------------------------------------------------------------------- 00002 // File and Version Information: 00003 // $Id: BdbTreeNode.cc,v 1.40 2002/04/25 02:00:52 patton Exp $ 00004 // 00005 // Description: 00006 // Class BdbTreeNode implementation file. This class represents a node 00007 // in a tree. A node may have a parent, and multiple children, which 00008 // themselves may be tree nodes, or leaf objects. This is the transient 00009 // wrapper class that provides the user interface to the persistent 00010 // BdbTreeNodeP class. 00011 // 00012 // Environment: 00013 // Software developed for the BaBar Detector at the SLAC B-Factory. 00014 // 00015 // Author List: 00016 // David R. Quarrie Original Author 00017 // 00018 // Copyright Information: 00019 // Copyright (C) 1998 Lawrence Berkeley Laboratory 00020 // 00021 //------------------------------------------------------------------------ 00022 00023 //----------------------- 00024 // This Class's Header -- 00025 //----------------------- 00026 #include "BdbTrees/BdbTreeNode.hh" 00027 00028 //------------- 00029 // C Headers -- 00030 //------------- 00031 extern "C" { 00032 #include <assert.h> 00033 #include <ctype.h> 00034 #include <stddef.h> 00035 #include <string.h> 00036 #include <unistd.h> 00037 } 00038 00039 //--------------------------------- 00040 // Collaborating Class's Headers -- 00041 //--------------------------------- 00042 #include "ErrLogger/ErrLog.hh" 00043 #include "BdbUtil/BdbPathName.hh" 00044 #include "BdbAccess/BdbDbAccessMgr.hh" 00045 #include "BdbAccess/BdbContAccessMgr.hh" 00046 #include "BdbApplication/BdbDomain.hh" 00047 #include "BdbApplication/BdbDebug.hh" 00048 #include "BdbTrees/BdbMetaData.hh" 00049 #include "BdbTrees/BdbTreesErrors.hh" 00050 #include "BdbTrees/BdbTreeNodeCache.hh" 00051 #include "BdbTrees/BdbTreeNodeLocking.hh" 00052 00053 //----------------------------------------------------------------------- 00054 // Local Macros, Typedefs, Structures, Unions and Forward Declarations -- 00055 //----------------------------------------------------------------------- 00056 00057 static const char rcsid[] = "$Id: BdbTreeNode.cc,v 1.40 2002/04/25 02:00:52 patton Exp $"; 00058 00059 00060 BdbTreeNodeCache* BdbTreeNode::_tnCache = new BdbTreeNodeCache(); 00061 BdbTreeNodeLocking* BdbTreeNode::_tnLock = new BdbTreeNodeLocking(); 00062 const d_Boolean BdbTreeNode::USE_CACHE = (getenv("BDB_DO_NOT_USE_TREE_NODE_CACHE") == 0); 00063 00064 00065 // ---------------------------------------- 00066 // -- Public Function Member Definitions -- 00067 // ---------------------------------------- 00068 00069 //---------------- 00070 // Constructors -- 00071 //---------------- 00072 00073 BdbTreeNode::BdbTreeNode( ) 00074 : BdbAbsWrapper( ) 00075 { 00076 } 00077 00078 BdbTreeNode::BdbTreeNode( BdbTreeNode& theParent, 00079 const char* const theName, 00080 BdbHandleAny& placement ) 00081 : BdbAbsWrapper( ) 00082 { 00083 BdbHandle(BdbTreeNodeP) theParentP = theParent.persistent( ); 00084 BdbHandleAny usePlacement = placement; 00085 if ( BdbIsNull( usePlacement ) ) { 00086 usePlacement = theParentP; 00087 } 00088 BdbHandle(BdbTreeNodeP) theNodeP; 00089 theNodeP = new(usePlacement) BdbTreeNodeP( theParentP, theName ); 00090 if ( ! BdbIsNull( theNodeP ) ) { 00091 setPersistent( theNodeP ); 00092 theParentP->replace( theNodeP, theName ); 00093 } 00094 } 00095 00096 BdbTreeNode::BdbTreeNode( BdbHandle(BdbTreeNodeP)& theNode ) 00097 : BdbAbsWrapper( ) 00098 { 00099 setObject( theNode ); 00100 } 00101 00102 BdbTreeNode::BdbTreeNode( const BdbTreeNode& theNode ) 00103 : BdbAbsWrapper( ) 00104 { 00105 BdbHandleAny theObj = theNode.object( ); 00106 setObject( theObj ); 00107 } 00108 00109 //-------------- 00110 // Destructor -- 00111 //-------------- 00112 00113 BdbTreeNode::~BdbTreeNode( ) 00114 { 00115 } 00116 00117 //------------- 00118 // Selectors -- 00119 //------------- 00120 00121 d_ULong 00122 BdbTreeNode::count( ) const 00123 { 00124 return persistent( )->count( ); 00125 } 00126 00127 const char* 00128 BdbTreeNode::name( ) const 00129 { 00130 return persistent( )->name( ); 00131 } 00132 00133 const char* 00134 BdbTreeNode::fullName( ) const 00135 { 00136 return persistent( )->fullName( ); 00137 } 00138 00139 const char* 00140 BdbTreeNode::pathName( ) const 00141 { 00142 return persistent( )->pathName( ); 00143 } 00144 00145 //-------------- 00146 // Operations -- 00147 //-------------- 00148 00149 BdbStatus 00150 BdbTreeNode::add( BdbTreeNode& aChild, const char* const theName ) 00151 { 00152 BdbHandle(BdbTreeNodeP) aChildP = aChild.persistent( ); 00153 BdbStatus result = updateAndWait( ); 00154 if (BdbcSuccess == result ) { 00155 result = persistent( )->add( aChildP, theName ); 00156 } else { 00157 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00158 "BdbTreeNode::add", name( ) ); 00159 } 00160 return result; 00161 } 00162 00163 BdbStatus 00164 BdbTreeNode::add( BdbHandle(BdbPersObj)& aChild, const char* const theName ) 00165 { 00166 BdbStatus result = updateAndWait( ); 00167 if (BdbcSuccess == result ) { 00168 result = persistent( )->add( aChild, theName ); 00169 } else { 00170 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00171 "BdbTreeNode::add", name( ) ); 00172 } 00173 return result; 00174 } 00175 00176 BdbStatus 00177 BdbTreeNode::child( BdbTreeNode& aChild, const char* const theName ) const 00178 { 00179 BdbHandle(BdbPersObj) aChildP; 00180 BdbStatus result = BdbcError; 00181 00182 if ( persistent( )->childIsTreeNode( theName ) ) { 00183 result = persistent( )->child( aChildP, theName ); 00184 } 00185 aChild.setPersistent( (BdbHandle(BdbTreeNodeP)&)aChildP ); 00186 return result; 00187 } 00188 00189 BdbStatus 00190 BdbTreeNode::child( BdbHandle(BdbPersObj)& aChild, const char* const theName ) const 00191 { 00192 BdbStatus result = persistent( )->child( aChild, theName ); 00193 return result; 00194 } 00195 00196 BdbStatus 00197 BdbTreeNode::child( BdbHandle(BdbPersObj)& aChild, 00198 const char* const theName, 00199 ooTypeNumber theType ) const 00200 { 00201 BdbStatus result = persistent( )->child( aChild, theName, theType ); 00202 return result; 00203 } 00204 00205 BdbStatus 00206 BdbTreeNode::child( BdbHandle(BdbPersObj)& aChild, 00207 const char* const theName, 00208 ooTypeNumber theTypes[], d_ULong numTypes ) const 00209 { 00210 BdbStatus result = persistent( )->child( aChild, theName, theTypes, numTypes ); 00211 return result; 00212 } 00213 00214 BdbStatus 00215 BdbTreeNode::clear( ) 00216 { 00217 BdbStatus result = updateAndWait( ); 00218 if (BdbcSuccess == result ) { 00219 result = persistent( )->clear( ); 00220 } else { 00221 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00222 "BdbTreeNode::clear", name( ) ); 00223 } 00224 return result; 00225 } 00226 00227 BdbStatus 00228 BdbTreeNode::clearAndDestroy( ) 00229 { 00230 BdbStatus result = updateAndWait( ); 00231 if (BdbcSuccess == result ) { 00232 result = persistent( )->clearAndDestroy( ); 00233 } else { 00234 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00235 "BdbTreeNode::remove", name( ) ); 00236 } 00237 return result; 00238 } 00239 00240 d_Boolean 00241 BdbTreeNode::hasChild( const char* const theName ) const 00242 { 00243 return persistent( )->hasChild( theName ); 00244 } 00245 00246 d_Boolean 00247 BdbTreeNode::hasChild( BdbTreeNode& aChild, d_Boolean descend ) const 00248 { 00249 BdbHandle(BdbTreeNodeP) aChildP = aChild.persistent( ); 00250 return persistent( )->hasChild( aChildP, descend ); 00251 } 00252 00253 d_Boolean 00254 BdbTreeNode::hasChild( BdbHandle(BdbPersObj)& aChild, d_Boolean descend ) const 00255 { 00256 return persistent( )->hasChild( aChild, descend ); 00257 } 00258 00259 BdbStatus 00260 BdbTreeNode::makeChild( BdbTreeNode& aNode, const char* const theName ) 00261 { 00262 BdbHandle(BdbTreeNodeP) theNodeP; 00263 BdbStatus result = updateAndWait( ); 00264 if (BdbcSuccess == result ) { 00265 result = persistent( )->makeChild( theNodeP, theName ); 00266 if ( BdbcSuccess == result ) { 00267 aNode.setPersistent( theNodeP ); 00268 } 00269 } else { 00270 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00271 "BdbTreeNode::makeChild", name( ) ); 00272 } 00273 return result; 00274 } 00275 00276 BdbStatus 00277 BdbTreeNode::parent( BdbTreeNode& theParent ) const 00278 { 00279 BdbHandle(BdbTreeNodeP) theParentP; 00280 BdbStatus result = persistent( )->parent( theParentP ); 00281 theParent.setPersistent( theParentP ); 00282 return result; 00283 } 00284 00285 BdbStatus 00286 BdbTreeNode::remove( const char* const theName ) 00287 { 00288 BdbStatus result = updateAndWait( ); 00289 if (BdbcSuccess == result ) { 00290 result = persistent( )->remove( theName ); 00291 } else { 00292 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00293 "BdbTreeNode::remove", name( ) ); 00294 } 00295 return result; 00296 } 00297 00298 BdbStatus 00299 BdbTreeNode::remove( BdbTreeNode& aChild ) 00300 { 00301 BdbHandle(BdbTreeNodeP) aChildP = aChild.persistent( ); 00302 BdbStatus result = updateAndWait( ); 00303 if (BdbcSuccess == result ) { 00304 result = persistent( )->remove( aChildP ); 00305 } else { 00306 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00307 "BdbTreeNode::remove", name( ) ); 00308 } 00309 return result; 00310 } 00311 00312 BdbStatus 00313 BdbTreeNode::remove( BdbHandle(BdbPersObj)& aChild ) 00314 { 00315 BdbStatus result = updateAndWait( ); 00316 if (BdbcSuccess == result ) { 00317 result = persistent( )->remove( aChild ); 00318 } else { 00319 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00320 "BdbTreeNode::remove", name( ) ); 00321 } 00322 return result; 00323 } 00324 00325 BdbStatus 00326 BdbTreeNode::removeAndDestroy( const char* const theName ) 00327 { 00328 BdbStatus result = updateAndWait( ); 00329 if (BdbcSuccess == result ) { 00330 result = persistent( )->removeAndDestroy( theName ); 00331 } else { 00332 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00333 "BdbTreeNode::removeAndDestroy", name( ) ); 00334 } 00335 return result; 00336 } 00337 00338 BdbStatus 00339 BdbTreeNode::removeAndDestroy( BdbTreeNode& aChild ) 00340 { 00341 BdbHandle(BdbTreeNodeP) aChildP = aChild.persistent( ); 00342 BdbStatus result = updateAndWait( ); 00343 if (BdbcSuccess == result ) { 00344 result = persistent( )->removeAndDestroy( aChildP ); 00345 } else { 00346 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00347 "BdbTreeNode::removeAndDestroy", name( ) ); 00348 } 00349 return result; 00350 } 00351 00352 BdbStatus 00353 BdbTreeNode::removeAndDestroy( BdbHandle(BdbPersObj)& aChild ) 00354 { 00355 BdbStatus result = updateAndWait( ); 00356 if (BdbcSuccess == result ) { 00357 result = persistent( )->removeAndDestroy( aChild ); 00358 } else { 00359 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00360 "BdbTreeNode::removeAndDestroy", name( ) ); 00361 } 00362 return result; 00363 } 00364 00365 BdbStatus 00366 BdbTreeNode::replace( BdbTreeNode& aChild, const char* const theName ) 00367 { 00368 BdbHandle(BdbTreeNodeP) aChildP = aChild.persistent( ); 00369 BdbStatus result = updateAndWait( ); 00370 if (BdbcSuccess == result ) { 00371 result = persistent( )->replace( aChildP, theName ); 00372 } else { 00373 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00374 "BdbTreeNode::replace", name( ) ); 00375 } 00376 return result; 00377 } 00378 00379 BdbStatus 00380 BdbTreeNode::replace( BdbHandle(BdbPersObj)& aChild, const char* const theName ) 00381 { 00382 BdbStatus result = updateAndWait( ); 00383 if (BdbcSuccess == result ) { 00384 result = persistent( )->replace( aChild, theName ); 00385 } else { 00386 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00387 "BdbTreeNode::replace", name( ) ); 00388 } 00389 return result; 00390 } 00391 00392 BdbStatus 00393 BdbTreeNode::upgradeName( ) 00394 { 00395 return persistent( )->upgradeName( ); 00396 } 00397 00398 BdbStatus 00399 BdbTreeNode::moveTo( const char* const thePath ) 00400 // Move this transient tree node to reference the persistent tree node 00401 // that corresponds to the specified path. This obeys Unix file syntax. 00402 // An absolute path begins with the "/" character and must specify the 00403 // authorization level and any relevant sublevels. A relative path omits 00404 // the leading "/" character. Moving up the tree is denoted by "../". 00405 { 00406 BdbTreeNode theNode; 00407 BdbHandle(BdbTreeNodeP) theNodeP; 00408 char theFragment[256]; 00409 const char* fragmentStart = thePath; 00410 const char* fragmentEnd = thePath; 00411 size_t fragmentLength; 00412 int nodePathL = 0; // for cache 00413 BdbStatus result = BdbcSuccess; 00414 00415 if ( NULL != thePath ) { 00416 if ( ! isNull( ) ) { 00417 theNode = *this; 00418 setNull( ); 00419 } 00420 result = BdbcError; 00421 if ( BdbPathName::separator() == *thePath ) { 00422 // it is important to use cache first, because theNode.fullName() touches "Root" container 00423 if ( USE_CACHE ) { 00424 // Try to move to the farthest cached tree-node (or Root) 00425 if ( BdbcSuccess == findBestCachedNode(thePath, theNode, fragmentStart) ) { 00426 if ( 0 == fragmentStart ) { // exact match 00427 result = BdbcSuccess; 00428 } 00429 } else { 00430 if ( BdbcSuccess != theNode.moveToRoot( ) ) { 00431 return BdbSignal(BdbcUserError, BdbTreesErrFunctionFailed, 0, 00432 "BdbTreeNode::moveTo", "in moveToRoot 1") ; 00433 } 00434 fragmentStart++; 00435 } 00436 nodePathL = fragmentStart - thePath; 00437 } else { 00438 if ( ! theNode.isNull( ) && ( 0 == strcmp( thePath, theNode.fullName( ) ) ) ) { 00439 // It's identical - no movement is necessary 00440 COUT1 << "BdbTreeNode::moveTo: Cached path" << endl; 00441 result = BdbcSuccess; 00442 } else { 00443 // It's not identical - Move to the root tree-node. 00444 if ( BdbcSuccess != theNode.moveToRoot( ) ) { 00445 return BdbSignal(BdbcUserError, BdbTreesErrFunctionFailed, 0, 00446 "BdbTreeNode::moveTo", "in moveToRoot 2") ; 00447 } 00448 fragmentStart++; 00449 } 00450 } 00451 } 00452 if ( BdbcSuccess != result ) { 00453 00454 // Traverse the path 00455 result = BdbcSuccess; 00456 while ( ( BdbcSuccess == result ) && 00457 ( NULL != ( fragmentEnd = strchr( fragmentStart, BdbPathName::separator() ) ) ) ) { 00458 fragmentLength = fragmentEnd - fragmentStart; 00459 if ( 0 < fragmentLength ) { 00460 strncpy( theFragment, fragmentStart, fragmentLength ); 00461 theFragment[fragmentLength] = '\0'; 00462 result = theNode.moveOneLevel( theFragment, d_False ); 00463 if ( BdbcSuccess == result && USE_CACHE ) { // insert entry into the cache 00464 char nodePath[256]; 00465 nodePathL += fragmentLength; 00466 strncpy(nodePath, thePath, nodePathL); 00467 nodePath[nodePathL] = '\0'; 00468 BdbRef(BdbObj) r = (BdbRef(BdbObj)) theNode.persistent(); 00469 //cout << "TNCACHE: inserting \"" << nodePath 00470 // << "\", oid = " << r.sprint() << endl; 00471 _tnCache->insertEntry(nodePath, r); 00472 } 00473 } 00474 fragmentStart = fragmentEnd + 1; 00475 nodePathL++; 00476 } 00477 if ( BdbcSuccess == result ) { 00478 // Deal with last fragment 00479 fragmentLength = strlen( fragmentStart ); 00480 if ( 0 < fragmentLength ) { 00481 result = theNode.moveOneLevel( fragmentStart, d_False ); 00482 if ( BdbcSuccess == result && USE_CACHE ) { // insert entry into the cache 00483 char nodePath[256]; 00484 nodePathL += fragmentLength; 00485 strncpy(nodePath, thePath, nodePathL); 00486 nodePath[nodePathL] = '\0'; 00487 BdbRef(BdbObj) r = (BdbRef(BdbObj)) theNode.persistent(); 00488 //cout << "TNCACHE: inserting \"" << nodePath 00489 // << "\", oid = " << r.sprint() << endl; 00490 _tnCache->insertEntry(nodePath, r); 00491 } 00492 } 00493 } 00494 } 00495 if ( BdbcSuccess == result ) { 00496 *this = theNode; 00497 } 00498 } 00499 return result; 00500 } 00501 00502 00503 /** 00504 ** The function sets "theNode" to the farthest cached node. 00505 ** It also sets fragmentStart, to the first character after 00506 ** the part of the path corresponding to cached node. 00507 ** If no cached node is found, the function returns an error, 00508 ** and "theNode"/startAfterCached are not altered. 00509 ** Successful return and startAfterCached == 0 means 00510 ** that an exact match was found. 00511 **/ 00512 BdbStatus 00513 BdbTreeNode::findBestCachedNode(const char* thePath, 00514 BdbTreeNode& theNode, 00515 const char*& startAfterCached) 00516 { 00517 char theFragment[256]; 00518 strcpy(theFragment, thePath); 00519 char* fragmentEnd = theFragment; 00520 BdbRef(BdbObj) r; 00521 00522 if ( BdbcSuccess == _tnCache->findEntry(thePath, r) ) { 00523 startAfterCached = 0; 00524 BdbRef(BdbTreeNodeP) tnR = (BdbRef(BdbTreeNodeP)) r; 00525 BdbHandle(BdbTreeNodeP) tnH = tnR; 00526 theNode.setPersistent(tnH); 00527 COUT2 << "Used cached intermediate node " << thePath << endl; 00528 return BdbcSuccess; // exact match 00529 } 00530 00531 while ( NULL != ( fragmentEnd = strrchr(theFragment, BdbPathName::separator()) ) ) { 00532 *fragmentEnd = '\0'; 00533 if ( 0 == strlen(theFragment) ) { 00534 break; 00535 } 00536 if ( BdbcSuccess == _tnCache->findEntry(theFragment, r) ) { 00537 startAfterCached = thePath + strlen(theFragment) +1; 00538 //cout << "found tn for " << theFragment 00539 // << ", startAfterCached = " << startAfterCached << endl; 00540 BdbRef(BdbTreeNodeP) tnR = (BdbRef(BdbTreeNodeP)) r; 00541 BdbHandle(BdbTreeNodeP) tnH = tnR; 00542 theNode.setPersistent(tnH); 00543 COUT2 << "Used cached intermediate node " << thePath << endl; 00544 return BdbcSuccess; 00545 } 00546 } 00547 00548 return BdbcError; 00549 } 00550 00551 00552 BdbStatus 00553 BdbTreeNode::moveUp( ) 00554 // Move up to the parent node. 00555 { 00556 BdbHandle(BdbTreeNodeP) theParentP; 00557 BdbStatus result = persistent( )->parent( theParentP ); 00558 setPersistent( theParentP ); 00559 return result; 00560 } 00561 00562 BdbStatus 00563 BdbTreeNode::moveToRoot( const char* const theRootName ) 00564 // Move to the root node with the specified name. The default is "main". 00565 { 00566 BdbHandle(BdbPersObj) theObj; 00567 BdbHandle(BdbTreeNodeP) theRootP; 00568 const char* theSysName = lowerRootName( theRootName ); 00569 BdbStatus result = theObj.lookupObj( BdbApplicationOrDomain::activeInstance()->fd(), theSysName, BdbcRead ); 00570 if ( BdbcSuccess == result ) { 00571 00572 if ( ! BdbTreeNodeP::isTreeNode( theObj ) ) { 00573 BdbSignal( BdbcUserError, BdbTreesErrRootTreeNodeWrongType, 0, 00574 "BdbTreeNode::root", theRootName ); 00575 result = BdbcError; 00576 } else { 00577 theRootP = (BdbHandle(BdbTreeNodeP)&)theObj; 00578 } 00579 setPersistent( theRootP ); 00580 } 00581 return result; 00582 } 00583 00584 BdbStatus 00585 BdbTreeNode::moveToRootChild( const char* const theChildName, 00586 const char* const theRootName ) 00587 // Locate the tree node having the specified name as a child of the named root 00588 // tree node. This is a convenience function. The default root is "main". 00589 { 00590 BdbStatus result = moveToRoot( theRootName); 00591 if ( BdbcSuccess == result ) { 00592 result = moveTo( theChildName ); 00593 } 00594 return result; 00595 } 00596 00597 BdbStatus 00598 BdbTreeNode::makeTo( const char* const thePath, d_Boolean createIntermediate ) 00599 // Move this transient tree node to reference the persistent tree node 00600 // that corresponds to the specified path. This obeys Unix file syntax. 00601 // An absolute path begins with the "/" character. A relative path omits 00602 // the leading "/" character. Moving up the tree is denoted by "../". 00603 // The "createIntermediate" flag determines whether any intermediate nodes 00604 // are created if required, or only the final destination node. 00605 { 00606 BdbTreeNode theNode; 00607 BdbHandle(BdbTreeNodeP) theNodeP; 00608 char theFragment[256]; 00609 const char* fragmentStart = thePath; 00610 const char* fragmentEnd = thePath; 00611 size_t fragmentLength; 00612 BdbStatus result = BdbcSuccess; 00613 00614 if ( NULL != thePath ) { 00615 if ( ! isNull( ) ) { 00616 theNode = *this; 00617 setNull( ); 00618 } 00619 result = BdbcError; 00620 if ( BdbPathName::separator() == *thePath ) { 00621 00622 // Absolute path - Look to see whether the new path is 00623 // identical to this one 00624 if ( ! theNode.isNull( ) && ( 0 == strcmp( thePath, theNode.fullName( ) ) ) ) { 00625 00626 // It's identical - no movement or creation is necessary 00627 COUT1 << "BdbTreeNode::makeTo: Cached path" << endl; 00628 result = BdbcSuccess; 00629 } else { 00630 00631 // It's not identical - Locate & create if necessary the 00632 // root tree-node. 00633 theNode.makeRoot( ); 00634 fragmentStart++; 00635 } 00636 } 00637 if ( BdbcSuccess != result ) { 00638 00639 // Traverse and create the path 00640 result = BdbcSuccess; 00641 while ( ( BdbcSuccess == result ) && 00642 ( NULL != ( fragmentEnd = strchr( fragmentStart, BdbPathName::separator() ) ) ) ) { 00643 fragmentLength = fragmentEnd - fragmentStart; 00644 if ( 0 < fragmentLength ) { 00645 strncpy( theFragment, fragmentStart, fragmentLength ); 00646 theFragment[fragmentLength] = '\0'; 00647 result = theNode.moveOneLevel( theFragment, createIntermediate ); 00648 } 00649 fragmentStart = fragmentEnd + 1; 00650 } 00651 if ( BdbcSuccess == result ) { 00652 00653 // Deal with last fragment 00654 fragmentLength = strlen( fragmentStart ); 00655 if ( 0 < fragmentLength ) { 00656 result = theNode.moveOneLevel( fragmentStart, d_True ); 00657 } 00658 } 00659 } 00660 if ( BdbcSuccess == result ) { 00661 *this = theNode; 00662 } 00663 } 00664 return result; 00665 } 00666 00667 BdbStatus 00668 BdbTreeNode::makeRoot( const char* const theRootName, 00669 const char* const placementContName ) 00670 // Locate & create if necessary the root tree node with the specified 00671 // name. The default is "main". 00672 { 00673 BdbStatus result = BdbcSuccess; 00674 BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance( ); 00675 00676 result = moveToRoot( theRootName ); 00677 if ( BdbcSuccess != result ) { 00678 00679 // Root tree node doesn't already exist. Close the current transaction 00680 // and start a new one to try to get sole access to the root container. 00681 theApp->commit("makeRoot") ; 00682 theApp->startUpdate("makeRoot") ; 00683 00684 BdbHandle(BdbDBObj) dbH; 00685 BdbDbAccessMgr dbAccessMgr; 00686 dbAccessMgr.openManagementDb( dbH, BdbcUpdate ); 00687 00688 BdbContAccessMgr contAccessMgr; 00689 BdbHandle(BdbContObj) contH; 00690 result = contAccessMgr.createContainer(dbH, contH, 00691 placementContName, 1, 10, 10); 00692 if ( BdbcSuccess == result ) { 00693 00694 // Now have guaranteed sole access to the root node container. 00695 // Check that the root node hasn't been created by someone else 00696 if ( BdbcSuccess != moveToRoot( theRootName ) ) { 00697 BdbHandle(BdbTreeNodeP) theRootP; 00698 theRootP = new(contH) BdbTreeNodeP( theRootName ); 00699 if ( ! BdbIsNull( theRootP ) ) { 00700 const char* theSysName = lowerRootName( theRootName ); 00701 BdbHandle(BdbFDObj) theFD = BdbApplicationOrDomain::activeInstance()->fd( ); 00702 result = theRootP.nameObj( theFD, theSysName ); 00703 if ( BdbcSuccess == result ) { 00704 setPersistent( theRootP ); 00705 } else { 00706 BdbSignal( BdbcUserError, BdbTreesErrUnableToNameRootTreeNode, 0, 00707 "BdbTreeNode::makeRoot", theRootName ); 00708 } 00709 } else { 00710 BdbSignal( BdbcUserError, BdbTreesErrUnableToCreateRootTreeNode, 0, 00711 "BdbTreeNode::makeRoot", theRootName ); 00712 result = BdbcError; 00713 } 00714 } 00715 } 00716 theApp->commit("makeRoot") ; 00717 theApp->startUpdate("makeRoot") ; 00718 } 00719 if ( BdbcSuccess != result ) { 00720 result = moveToRoot( theRootName ); 00721 } 00722 return result; 00723 } 00724 00725 BdbStatus 00726 BdbTreeNode::makeRootChild( const char* const theChildName, 00727 const char* const theRootName ) 00728 // Locate and create if necessary the tree node having the specified name as a 00729 // child of the named root tree node. This is a convenience function. The 00730 // default root is "main". 00731 { 00732 BdbStatus result = makeRoot( theRootName); 00733 if ( BdbcSuccess == result ) { 00734 result = makeTo( theChildName ); 00735 } 00736 return result; 00737 } 00738 00739 BdbStatus 00740 BdbTreeNode::makeRootChild( const char* const theName, 00741 const char* const theRootName, 00742 BdbHandleAny& placement ) 00743 { 00744 BdbStatus result = moveToRoot(theRootName) ; 00745 if ( result != BdbcSuccess ) { 00746 return BdbSignal(BdbcUserError, BdbTreesErrFunctionFailed, 0, "BdbTreeNode::makeRootChild", "in moveToRoot") ; 00747 } 00748 00749 const char* useName = theName; 00750 00751 // Deal with <user> as special (replaced by real user name 00752 if ( 0 == strcmp( useName, "<user>" ) ) { 00753 useName = BdbDomain::userName( ); 00754 } 00755 BdbHandle(BdbTreeNodeP) theParentP = persistent( ); 00756 result = child( *this, useName ); 00757 if ( BdbcSuccess != result) { 00758 00759 // Child doesn't exist - create it 00760 BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance( ); 00761 result = theApp->updateAndWait( placement, "BdbTreeNode" ); 00762 if ( BdbcSuccess == result ) { 00763 BdbHandle(BdbTreeNodeP) theNodeP; 00764 theNodeP = new(placement) BdbTreeNodeP( theParentP, useName ); 00765 if ( ! BdbIsNull( theNodeP ) ) { 00766 setPersistent( theNodeP ); 00767 result = theParentP->replace( theNodeP, useName ); 00768 } 00769 } else { 00770 BdbSignal( BdbcUserError, BdbTreesErrUpdateFailed, 0, 00771 "BdbTreeNode::makeRootChild" ); 00772 } 00773 } 00774 return result; 00775 } 00776 00777 BdbStatus 00778 BdbTreeNode::fetchMetaData( BdbMetaData& theData ) 00779 { 00780 BdbHandle(BdbMetaDataP) theDataP; 00781 BdbStatus result = updateAndWait( ); 00782 if (BdbcSuccess == result ) { 00783 result = persistent( )->fetchMetaData( theDataP ); 00784 if ( BdbcSuccess == result ) { 00785 theData.setPersistent( theDataP ); 00786 } 00787 } 00788 return result; 00789 } 00790 00791 BdbStatus 00792 BdbTreeNode::metaData( BdbMetaData& theData ) const 00793 { 00794 BdbHandle(BdbMetaDataP) theDataP; 00795 BdbStatus result = persistent( )->metaData( theDataP ); 00796 theData.setPersistent( theDataP ); 00797 return result; 00798 } 00799 00800 BdbHandle(BdbTreeNodeP) 00801 BdbTreeNode::persistent( ) const 00802 { 00803 BdbHandle(BdbTreeNodeP) h = (BdbHandle(BdbTreeNodeP)&) object( ); 00804 00805 assert( ! BdbIsNull( h ) ); 00806 00807 if ( BdbcSuccess != h.open(oocRead) ) { 00808 BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance(); 00809 d_Long oldWait = theApp->lockWait( ); 00810 d_ULong lw = (oldWait<300 ? 300 : oldWait); // wait up to 5 min 00811 ErrMsg( warning ) << "Problems with opening " << h.sprint() 00812 << " for reading, retrying once" 00813 << " (lockWait = " << lw << " sec)" << endmsg; 00814 theApp->setLockWait(lw); 00815 if ( BdbcSuccess != h.open(oocRead) ) { 00816 ErrMsg( fatal ) << "Unable to lock " << h.sprint() 00817 << " for reading, fd " 00818 << theApp->fd().sprint() << endmsg; 00819 } 00820 theApp->setLockWait( oldWait ); 00821 } 00822 ooRef(ooObj) r = h; 00823 _tnLock->add(r); 00824 00825 return h; 00826 } 00827 00828 //------------- 00829 // Operators -- 00830 //------------- 00831 00832 BdbTreeNode& 00833 BdbTreeNode::operator=( const BdbTreeNode& theOther ) 00834 { 00835 BdbHandleAny theObj = theOther.object( ); 00836 setObject( theObj ); 00837 return *this; 00838 } 00839 00840 // ------------------------------------------- 00841 // -- Protected Function Member Definitions -- 00842 // ------------------------------------------- 00843 00844 const char* 00845 BdbTreeNode::lowerRootName( const char* const theRootName ) 00846 // Return the root name in lower case. 00847 { 00848 static BdbTString theSysName; 00849 char lowerName[256]; 00850 size_t len = strlen( theRootName ); 00851 for ( size_t i = 0; i < len; i++ ) { 00852 lowerName[i] = tolower( theRootName[i] ); 00853 } 00854 lowerName[len] = '\0'; 00855 theSysName = "BdbTreeNodeP::"; 00856 theSysName += lowerName; 00857 return theSysName.data( ); 00858 } 00859 00860 BdbStatus 00861 BdbTreeNode::moveOneLevel( const char* const theName, 00862 d_Boolean createIfNeeded ) 00863 { 00864 BdbTreeNode theNode; 00865 BdbStatus result = BdbcError; 00866 const char* useName = theName; 00867 00868 if ( 0 == strcmp( useName, ".." ) ) { 00869 00870 // Move up to parent 00871 result = parent( theNode ); 00872 } else { 00873 00874 // Deal with <user> as special (replaced by real user name) 00875 if ( 0 == strcmp( useName, "<user>" ) ) { 00876 useName = BdbDomain::userName( ); 00877 } 00878 00879 // Test whether the child node already exists 00880 result = child( theNode, useName ); 00881 if ( ( BdbcSuccess != result ) && createIfNeeded ) { 00882 00883 // The child node doesn't exist - Check whether the name is used 00884 if ( ! hasChild( useName ) ) { 00885 00886 BdbHandleAny theHint = BdbTreeNodeP::clustering.updatedHint( ); 00887 if( theHint.isNull() ) { 00888 return( BdbcError ); 00889 } 00890 00891 // Make sure that we have update locks on both the 00892 // placement and parent node. 00893 BdbHandle(BdbTreeNodeP) parentHandle( persistent() ); 00894 if ( BdbcSuccess != parentHandle.update() ) { 00895 return( BdbcError ); 00896 } 00897 00898 if ( BdbcSuccess != theHint.update() ) { 00899 return( BdbcError ); 00900 } 00901 00902 // Now that we have an update lock on the tree node, 00903 // check again that the requested child doesn't exist in 00904 // case someone else got there while we were waiting for 00905 // the lock. 00906 result = child( theNode, useName ); 00907 if ( BdbcSuccess != result ) { 00908 00909 // Child still doesn't exist - create it and add it 00910 // to the node 00911 BdbHandle(BdbTreeNodeP) theNodeP; 00912 theNodeP = new(theHint) BdbTreeNodeP( parentHandle, 00913 useName ); 00914 if( theNodeP.isNull() ) { 00915 return( BdbcError ); 00916 } 00917 00918 theNode.setPersistent( theNodeP ); 00919 result = parentHandle->replace( theNodeP, useName ); 00920 } 00921 } 00922 } 00923 } 00924 if ( BdbcSuccess == result ) { 00925 *this = theNode; 00926 } 00927 return result; 00928 } 00929 00930 void 00931 BdbTreeNode::setPersistent( BdbHandle(BdbTreeNodeP)& aNode ) 00932 { 00933 setObject( aNode ); 00934 } 00935 00936 BdbStatus 00937 BdbTreeNode::updateAndWait( ) 00938 // Lock the node for sole access. In order to avoid deadlocks 00939 // do not wait indefinitely for the lock, but try for up to a default 00940 // timeout period. 00941 { 00942 BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance( ); 00943 BdbHandle(BdbTreeNodeP) theNodeP = persistent( ); 00944 BdbStatus result = theApp->updateAndWait( theNodeP, "update" ); 00945 if ( BdbcSuccess != result ) { 00946 BdbSignal( BdbcUserError, BdbTreesErrTreeUnableToUpdate, 0, 00947 "BdbTreeNode::updateAndWait", name( ) ); 00948 } 00949 return result; 00950 } 00951 00952 00953 void 00954 BdbTreeNode::startRecordingRLocks() 00955 { 00956 _tnLock->startRecording(); 00957 } 00958 00959 00960 void 00961 BdbTreeNode::dropRecordedRLocks() 00962 { 00963 _tnLock->stopRecordingAndUnlock(); 00964 } 00965
BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us
Page Owner: Jacek Becla
Last Update: October 04, 2002