![]() |
|
|
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 /BdbDistTools/BdbDistribution.cc
Go to the documentation of this file.00001 //-------------------------------------------------------------------------- 00002 // File and Version Information: 00003 // $Id: BdbDistribution.cc,v 1.20 2002/06/17 03:00:04 becla Exp $ 00004 // 00005 // Description: 00006 // Support for the distribution operations (attach, extract, ...) 00007 // 00008 // Environment: 00009 // Software developed for the BaBar Detector at the SLAC B-Factory. 00010 // 00011 // Author List: 00012 // Jean-Noel Albert Original Author 00013 // 00014 // Copyright Information: 00015 // Copyright (C) 1999 00016 // 00017 //------------------------------------------------------------------------ 00018 00019 //----------------------- 00020 // This Class's Header -- 00021 //----------------------- 00022 #include "BdbDistTools/BdbDistribution.hh" 00023 00024 //------------- 00025 // C Headers -- 00026 //------------- 00027 extern "C" { 00028 #include <stdio.h> 00029 #include <stdlib.h> 00030 #include <unistd.h> 00031 #include <strings.h> 00032 #include <sys/wait.h> 00033 } 00034 00035 //------------------------------- 00036 // Collaborating Class Headers -- 00037 //------------------------------- 00038 #include "BdbApplication/BdbDomain.hh" 00039 #include "BdbEvent/BdbEvent.hh" 00040 #include "BdbEvent/BdbEventT.hh" 00041 #include "BdbEventStore/BdbEventStore.hh" 00042 #include "BdbEventStore/BdbAbsCollectionT.hh" 00043 #include "BdbEventStore/BdbCollectionP.hh" 00044 #include "BdbTrees/BdbTreeAccess.hh" 00045 #include "BdbAccess/BdbTFileSystem.hh" 00046 #include "BdbAccess/BdbDbInfo.hh" 00047 #include "BdbTrees/BdbDbRegistrator.hh" 00048 #include "BdbAccess/BdbAuth.hh" 00049 #include "BdbAccess/BdbDbTreeSingleton.hh" 00050 #include "BdbDistTools/BdbDistMessage.hh" 00051 #include "BdbEvent/BdbEvent_001.hh" 00052 00053 BdbDistribution::BdbDistribution() 00054 { 00055 // setVerbose(BdbApplication::instance()->verbose()); 00056 } 00057 00058 BdbDistribution::~BdbDistribution() 00059 {} 00060 00061 //------------ 00062 // Services -- 00063 //------------ 00064 void BdbDistribution::setVerbose(d_Boolean mode) 00065 { 00066 // BdbApplication::instance()->setVerbose(mode); 00067 } 00068 00069 d_Boolean BdbDistribution::verbose () const 00070 { 00071 // return BdbApplication::instance()->verbose(); 00072 return( false ) ; 00073 } 00074 00075 BdbTString BdbDistribution::logfile(const char* name, const char* suffix) 00076 { 00077 char* tmp = getenv("BDBDIST_TMP"); 00078 if (0 == tmp) 00079 tmp = "/tmp"; 00080 BdbTString logname(tmp, "/", name, "-", BdbTString(getpid()), suffix); 00081 00082 // Remove any existing file 00083 if (access(logname, F_OK) == 0) 00084 unlink(logname); 00085 00086 return logname; 00087 } 00088 00089 // Translate BdbDistribution verbose, message, and error calls to 00090 // BdbDistMessage. 00091 // Note that BdbDistribution::message() indicates an error condition. 00092 00093 void BdbDistribution::verbose(BdbTString text) 00094 { 00095 BdbDistMessage::verbose (text.data()); 00096 } 00097 00098 void BdbDistribution::message(BdbTString text) 00099 { 00100 BdbDistMessage::warning (text.data()); 00101 } 00102 00103 BdbStatus BdbDistribution::error(BdbTString text) 00104 { 00105 // Print the error message 00106 message(text); 00107 00108 // Cancel the *** internal *** transaction, if any 00109 if (!_externalTransaction && !checkTransaction(BdbcNoOpen)) 00110 BdbDomain::activeInstance()->abort("BdbDistribution::error"); 00111 00112 // Signal the error 00113 return BdbcError; 00114 } 00115 00116 int BdbDistribution::execute(BdbTString command) 00117 { 00118 verbose ("> " + command); 00119 int stt = system(command); 00120 return WEXITSTATUS(stt); 00121 } 00122 00123 int BdbDistribution::catalogOperation(BdbTString command) 00124 { 00125 // Drop any lock before executing the operation 00126 int mode = getTransaction(); 00127 if (BdbcNoOpen != mode) 00128 BdbDomain::activeInstance()->commit("BdbDistribution::catalogOperation"); 00129 00130 // Execute the catalog operation 00131 int stt = execute(command); 00132 00133 // Reset the transaction in the initial mode 00134 if (BdbcRead == mode) 00135 BdbDomain::activeInstance()->startRead("BdbDistribution::catalogOperation"); 00136 else if (BdbcUpdate == mode) 00137 BdbDomain::activeInstance()->startUpdate("BdbDistribution::catalogOperation"); 00138 return stt; 00139 } 00140 00141 d_Boolean BdbDistribution::checkTransaction(int mode) 00142 { 00143 _externalTransaction = BdbcNoOpen != BdbDomain::activeInstance()->mode(); 00144 if (!_externalTransaction) 00145 return BdbcNoOpen == mode; // No transaction at all 00146 // Return true if asked for "No Open" 00147 else if (BdbcNoOpen == mode) 00148 return d_False; // Inside of a transaction: wrong 00149 00150 else if (BdbcUpdate == mode) 00151 return (mode == BdbDomain::activeInstance()->mode()); 00152 00153 return d_True; // At least in read mode 00154 } 00155 00156 int BdbDistribution::getTransaction() 00157 { 00158 return BdbDomain::activeInstance()->mode(); 00159 } 00160 00161 //-------------- 00162 // Operations -- 00163 //-------------- 00164 00165 /*********************************************************************************/ 00166 00167 // Context: NO TRANSACTION 00168 // *** existing transaction is aborted *** 00169 // 00170 // Access: Any 00171 // 00172 // Privileges: database authorization level 00173 00174 BdbStatus BdbDistribution::attachDb (BdbDistFile& filepath, int dbid, 00175 d_Boolean chmodRead, 00176 BdbTString dbname, d_Boolean force) 00177 { 00178 verbose("Attaching " + filepath.name() + " ..."); 00179 00180 // Check for the transaction mode 00181 if (!checkTransaction(BdbcNoOpen)) 00182 return error("Can't work inside a transaction"); 00183 00184 // Start an local transaction to be able to check for the privileges 00185 BdbDomain::activeInstance()->startRead("BdbDistribution::attachDb"); 00186 00187 // Preliminary checks 00188 if (!filepath.isFileExist()) 00189 return error("No such file: " + filepath.fullPath()); 00190 00191 if (!force && "" != dbname && filepath.name() != dbname) 00192 return error ("Not allowed to attach " + filepath.fullPath() + 00193 " as: " + dbname); 00194 00195 if ("" == dbname) 00196 dbname = filepath.name(); 00197 00198 BdbDistDatabase db(dbname.data()); 00199 if (db.isDbExist()) 00200 return error ("Database " + db.dbName() + 00201 " already exist: " + BdbTString(db.dbid())); 00202 00203 if (!filepath.isAuthorized()) 00204 return error ("No privilege to attach: " + filepath.fullPath()); 00205 00206 // Name an error file to receive the output of "ooattachdb" 00207 BdbTString errlog = logfile(dbname, ".err"); 00208 00209 // Attach command 00210 BdbTString command = "ooattachdb"; 00211 if (! verbose()) 00212 command += " -notitle -quiet"; 00213 command += " -db " + db.dbName(); 00214 command += " -id " + BdbTString(dbid); 00215 command += " -filepath " + filepath.filePath(); 00216 if ("" != filepath.host()) 00217 command += " -host " + filepath.host(); 00218 00219 command += " "; 00220 command += BdbDomain::activeInstance()->bootName(); 00221 00222 if (!verbose()) 00223 command += " 2> " + errlog; 00224 00225 // Execute the ooattachdb command 00226 if (0 != catalogOperation(command)) { 00227 message ("Attach command failed: " + command); 00228 if (!verbose()) 00229 execute("cat " + errlog); 00230 return BdbcError; 00231 } 00232 00233 // Remove the error log file 00234 unlink(errlog); 00235 00236 // Turn the file read/only 00237 if (chmodRead && BdbcSuccess != filepath.chmodRead()) 00238 return error("Failed to read protect: " + filepath.fullPath()); 00239 00240 // Commit the local transaction 00241 BdbDomain::activeInstance()->commit("BdbDistribution::attachDb"); 00242 00243 return BdbcSuccess; 00244 } 00245 00246 /*********************************************************************************/ 00247 /*********************************************************************************/ 00248 00249 // Context: NO TRANSACTION 00250 // *** existing transaction is aborted *** 00251 // 00252 // Access: Any 00253 // 00254 // Privileges: database authorization level 00255 00256 BdbStatus BdbDistribution::detachDb (BdbTString dbname, int retry, int delay) 00257 { 00258 verbose("Detaching " + dbname + " ..."); 00259 00260 // Check for the transaction mode 00261 if (!checkTransaction(BdbcNoOpen)) 00262 return error("Can't work inside a transaction"); 00263 00264 // Start an local transaction to be able to check for the privileges 00265 BdbDomain::activeInstance()->startRead("BdbDistribution::detachDb"); 00266 00267 // Privileges 00268 BdbDistDatabase db (dbname.data()); 00269 if (!db.isAuthorized()) 00270 return error("No privilege to detach " + dbname); 00271 00272 // Error log file to keep the oodetachdb message 00273 BdbTString errlog = logfile(dbname, ".err"); 00274 00275 // Detach command 00276 BdbTString command = "oodeletedb -force -catalogonly"; 00277 if (!verbose()) 00278 command += " -notitle -quiet"; 00279 command += " -db " + dbname; 00280 command += " "; 00281 command += BdbDomain::activeInstance()->bootName(); 00282 00283 if (!verbose()) 00284 command += " 2> " + errlog; 00285 00286 // Execute the detach command 00287 if (0 != catalogOperation(command)) { 00288 message ("Detach command failed: " + command); 00289 if (!verbose()) 00290 execute ("cat " + errlog); 00291 00292 for (int t = 0; t < retry; t++) { 00293 message ("Retrying in " + BdbTString(delay) + " seconds..."); 00294 sleep(delay); 00295 if (0 == catalogOperation(command)) { 00296 verbose("Success !"); 00297 break; 00298 } 00299 00300 message ("Detach command failed: " + command); 00301 if (!verbose()) 00302 execute ("cat " + errlog); 00303 } 00304 00305 if (retry >= 0) 00306 message ("Retry limit exceeded..."); 00307 00308 return BdbcError; 00309 } 00310 00311 // Remove the error log file 00312 unlink(errlog); 00313 00314 // Commit the local transaction 00315 BdbDomain::activeInstance()->commit("BdbDistribution::detachDb"); 00316 00317 return BdbcSuccess; 00318 } 00319 00320 /*********************************************************************************/ 00321 /*********************************************************************************/ 00322 00323 // Context: Update Transaction 00324 // 00325 // Access: Update 00326 // 00327 // Privileges: database authorization level 00328 00329 BdbStatus BdbDistribution::changeDb (BdbDistDatabase& db, 00330 BdbDistFile& filepath, 00331 d_Boolean chmodRead, d_Boolean force) 00332 { 00333 verbose ("Changing " + db.dbName() + " ..."); 00334 00335 // Check for the transaction mode 00336 if (!checkTransaction(BdbcUpdate)) 00337 return error ("Need an update transaction"); 00338 00339 // Preliminary checks 00340 if (!db.isDbExist()) 00341 return error ("No such database: " + db.dbName()); 00342 00343 // Existing file 00344 if (!force && !filepath.isFileExist()) 00345 return error ("No such file: " + filepath.fullPath()); 00346 00347 // Check the system names 00348 if (!force && db.dbName() != filepath.name()) 00349 return error ("Not allowed to change: " + db.dbName() + 00350 " as: " + filepath.fullPath()); 00351 00352 // Privileges 00353 if (!db.isAuthorized()) 00354 return error ("No privilege to change: " + db.dbName()); 00355 00356 // Lock the database in update mode to be able to change it 00357 // The caller has to define the wait delay... 00358 verbose ("Trying to lock: " + db.dbName() + " ..."); 00359 if (BdbcSuccess != db.lock(oocLockUpdate)) 00360 return error ("Can't lock for update: " + db.dbName()); 00361 00362 verbose ("Lock granted..."); 00363 00364 // Send the Objectivity outputs in an error log file 00365 BdbTString errlog = logfile(db.dbName(), ".err"); 00366 FILE* flog = NULL; 00367 00368 if (!verbose()) 00369 flog = fopen(errlog, "w"); 00370 if (NULL == flog) 00371 flog = stdout; 00372 00373 // Execute the change operation 00374 BdbTString host; 00375 if ("" == filepath.host()) 00376 host = BdbTFileSystem::localHostName(); 00377 else 00378 host = filepath.host(); 00379 00380 // BdbStatus status = db.handle().change(db.dbName(), host, filepath.filePath(), flog); 00381 BdbRef(BdbDBObj) dbR = db.handle(); 00382 BdbStatus status = dbR.change(0, host, filepath.filePath(), flog); 00383 00384 if (stdout != flog) 00385 fclose (flog); 00386 00387 // Remove the error log, if the change success 00388 if (BdbcSuccess == status) 00389 unlink(errlog); 00390 00391 // Or print it on the user screen 00392 else if (!verbose()) 00393 execute ("cat " + errlog); 00394 00395 if (BdbcSuccess != status) 00396 return status; 00397 00398 // Turn the file read/only 00399 if (chmodRead && BdbcSuccess != filepath.chmodRead()) 00400 return error("Failed to read protect: " + filepath.fullPath()); 00401 00402 return BdbcSuccess; 00403 } 00404 00405 /*********************************************************************************/ 00406 /*********************************************************************************/ 00407 00408 // Context: Read transaction 00409 // 00410 // Access: Any 00411 // 00412 // Privileges: none 00413 00414 BdbStatus BdbDistribution::extractDb (BdbDistDatabase& db, 00415 BdbDistFile& outfile, 00416 d_Boolean supersed) 00417 { 00418 verbose ("Extracting " + db.dbName() + " ..."); 00419 00420 // Check for the transaction mode 00421 // Start a local transaction if needed 00422 if (checkTransaction(BdbcNoOpen)) 00423 BdbDomain::activeInstance()->startRead("BdbDistribution::extractDb"); 00424 00425 // Preliminary checks 00426 if (!db.isDbExist()) 00427 return error ("No such database: " + db.dbName()); 00428 00429 if (!db.isFileExist()) 00430 return error ("Database file does not exist: " + db.fullPath()); 00431 00432 // Existing destination file 00433 if (outfile.isFileExist()) { 00434 if (!supersed) 00435 return error ("Output file exists: " + outfile.fullPath()); 00436 00437 // Remove the output file 00438 if (BdbcSuccess != outfile.remove()) 00439 return error ("Failed to remove the existing output file: " + 00440 outfile.fullPath()); 00441 } 00442 00443 // Lock the database in read mode to be able to change it 00444 // The caller has to define the wait delay... 00445 verbose ("Trying to lock: " + db.dbName() + " ..."); 00446 if (BdbcSuccess != db.lock(oocLockRead)) 00447 return error ("Can't lock for read: " + db.dbName()); 00448 00449 verbose ("Lock granted..."); 00450 00451 // Get the size of the database -- to check the result of the transfer 00452 off_t size; 00453 if (BdbcSuccess != db.fileSize(size)) 00454 return error ("Can't get the size of the database file: " + db.fullPath()); 00455 00456 // Copy the file -- no cross node at this time 00457 if (BdbcSuccess != db.copy(outfile)) 00458 return error ("Failed to copy the database file: " + db.fullPath() + 00459 " to " + outfile.fullPath()); 00460 00461 // Check if the out file exists, with the correct size 00462 if (!outfile.isFileExist()) 00463 return error ("Ouput file does not exists: " + outfile.fullPath()); 00464 00465 off_t outsize; 00466 if (BdbcSuccess != outfile.fileSize(outsize)) 00467 return error ("Failed to get the size of the output file: " + 00468 outfile.fullPath()); 00469 00470 if (size != outsize) 00471 return error ("The output file size does not match the database size: " + 00472 outfile.fullPath()); 00473 00474 // Finish the local transaction 00475 if (!_externalTransaction) 00476 BdbDomain::activeInstance()->commit("BdbDistribution::extractDb"); 00477 return BdbcSuccess; 00478 } 00479 00480 /*********************************************************************************/ 00481 /*********************************************************************************/ 00482 00483 // Context: NO TRANSACTION 00484 // 00485 // Access: Update 00486 // 00487 // Privileges: database authorization level 00488 00489 BdbStatus BdbDistribution::removeDb (BdbTString dbname, int retry, int delay) 00490 { 00491 verbose ("Removing " + dbname + " ..."); 00492 00493 // Check for the transaction mode 00494 if (!checkTransaction(BdbcUpdate)) 00495 return error ("Need an update transaction"); 00496 00497 // Start a local transaction to be able to check for the privileges 00498 BdbDomain::activeInstance()->startRead("BdbDistribution::removeDb"); 00499 00500 // Preliminary checks 00501 BdbDistDatabase db (dbname.data()); 00502 if (!db.isDbExist()) 00503 return error ("No such database: " + dbname); 00504 00505 // Privileges 00506 if (!db.isAuthorized()) 00507 return error ("No privilege to remove: " + dbname); 00508 00509 // Lock the database in update mode 00510 // The caller has to define the wait delay... 00511 verbose ("Trying to lock: " + dbname + " ..."); 00512 if (BdbcSuccess != db.lock(oocLockUpdate)) 00513 return error ("Can't lock for update: " + dbname); 00514 00515 verbose ("Lock granted..."); 00516 00517 // Change the database to an invalid location, to prevent accesses 00518 BdbDistFile invfile ("/invalid/not/a/db"); 00519 if (BdbcSuccess != changeDb(db, invfile, d_True)) { 00520 BdbDomain::activeInstance()->abort("BdbDistribution::detachDb"); 00521 return error ("Remove failed"); 00522 } 00523 00524 // Commit the local transaction and try to detach the database 00525 BdbDomain::activeInstance()->commit("BdbDistribution::detachDb"); 00526 00527 return detachDb(dbname, retry, delay); 00528 } 00529 00530 /*********************************************************************************/ 00531 /*********************************************************************************/ 00532 00533 // Context: NO TRANSACTION 00534 // *** existing transaction is aborted *** 00535 // 00536 // Access: Update 00537 // 00538 // Privileges: database authorization level 00539 00540 BdbStatus BdbDistribution::shadowDb (BdbDistFile& filepath, int dbid) 00541 { 00542 verbose ("Shadowing " + filepath.name() + " ..."); 00543 00544 // Check for the transaction mode 00545 if (!checkTransaction(BdbcNoOpen)) 00546 return error("Can't work inside a transaction"); 00547 00548 // Start a local transaction 00549 BdbDomain::activeInstance()->startUpdate("BdbDistribution::shadowDb"); 00550 00551 // Preliminary checks 00552 if (filepath.isFileExist()) 00553 return error ("Target file exists -- use \"attachDb\": " + 00554 filepath.fullPath()); 00555 00556 BdbDistDatabase db(filepath.name().data()); 00557 if (db.isDbExist()) 00558 return error ("Database " + db.dbName() + 00559 " already exist: " + BdbTString(db.dbid())); 00560 00561 if (!filepath.isAuthorized()) 00562 return error ("No privilege to shadow: " + filepath.fullPath()); 00563 00564 // Create a dummy database in the federation directory 00565 verbose("Creating a dummy ." + filepath.name() + " database ..."); 00566 BdbDomain* tempApp = BdbDomain::activeInstance(); 00567 BdbDistFile dummyfile (BdbTString( tempApp->dirName(), 00568 "/.", db.dbName(), ".dummy"), 00569 tempApp->hostName()); 00570 if (dummyfile.isFileExist() && BdbcSuccess != dummyfile.remove()) 00571 return error("Failed to remove existing dummy database: " + 00572 dummyfile.fullPath()); 00573 00574 // Error log file to keep the oonewdb message 00575 BdbTString errlog = logfile(db.dbName(), ".err"); 00576 00577 // Create an empty database 00578 BdbTString command = "oonewdb -db " + db.dbName() + 00579 " -host " + dummyfile.host() + 00580 " -filepath " + dummyfile.filePath(); 00581 if (!verbose()) 00582 command += " -notitle -quiet"; 00583 command += " "; 00584 command += BdbDomain::activeInstance()->bootName(); 00585 00586 if (!verbose()) 00587 command += " 2> " + errlog; 00588 00589 if (0 != execute(command)) 00590 return error ("Failed to create the dummy database: " + 00591 dummyfile.fullPath()); 00592 00593 // Detach the dummy and attach it with the right dbid 00594 // Must be done out of a transaction 00595 BdbDistDatabase dummydb (db.dbName().data()); 00596 00597 BdbDomain::activeInstance()->commit("BdbDistribution::shadowDb"); 00598 00599 if (BdbcSuccess != detachDb(dummydb.dbName())) 00600 return error ("Can't detach the dummy database: " + db.dbName()); 00601 00602 // Attach with the right dbid 00603 if (BdbcSuccess != attachDb(dummyfile, dbid, d_False, db.dbName(), d_True)) 00604 return error ("Can't reattach the dummy database: " + 00605 dummyfile.fullPath()); 00606 00607 // Restart a transaction to be able to change the database 00608 BdbDomain::activeInstance()->startUpdate("BdbDistribution::shadowDb"); 00609 00610 // Change the dummy to the new location 00611 if (BdbcSuccess != changeDb(dummydb, filepath, d_False, d_True)) { 00612 BdbDomain::activeInstance()->abort("BdbDistribution::shadowDb"); 00613 return error ("Can't change the dummy: " + dummydb.dbName() + 00614 " to the shadow location: " + filepath.fullPath()); 00615 } 00616 00617 // Remove the dummy 00618 if (BdbcSuccess != dummyfile.remove()) 00619 message ("Failed to remove the dummy file: " + dummyfile.fullPath()); 00620 00621 // Final commit 00622 BdbDomain::activeInstance()->commit("BdbDistribution::shadowDb"); 00623 00624 return BdbcSuccess; 00625 } 00626 00627 /*********************************************************************************/ 00628 /*********************************************************************************/ 00629 00630 // Context: Update Transaction 00631 // 00632 // Access: Update 00633 // 00634 // Privileges: collection authorization level 00635 00636 BdbStatus BdbDistribution::replaceDb (BdbDistDatabase& db, BdbDistFile& impfile, 00637 d_Boolean chmodRead) 00638 { 00639 verbose("Replacing " + db.dbName() + " ..."); 00640 00641 // Check for the transaction mode 00642 if (!checkTransaction(BdbcUpdate)) 00643 return error ("Need an update transaction"); 00644 00645 // Preliminary checks 00646 if (!db.isDbExist()) 00647 return error ("No such database: " + db.dbName()); 00648 00649 // Existing file 00650 if (!impfile.isFileExist()) 00651 return error ("No such file: " + impfile.fullPath()); 00652 00653 if (!db.isAuthorized()) 00654 return error ("No privilege to attach: " + db.fullPath()); 00655 00656 // Lock the database in update mode to be able to change it 00657 // The caller has to define the wait delay... 00658 verbose ("Trying to lock: " + db.dbName() + " ..."); 00659 if (BdbcSuccess != db.lock(oocLockUpdate)) 00660 return error ("Can't lock for update: " + db.dbName()); 00661 00662 verbose ("Lock granted..."); 00663 00664 // Rename the database file (if any) 00665 BdbDistFile olddb (db.filePath() + "old", db.host(), db.pudPort()); 00666 00667 if (db.isFileExist()) { 00668 verbose ("Renaming " + db.fullPath() + " as old"); 00669 00670 // BdbDistFile olddb (db.filePath() + "old"); 00671 if (BdbcSuccess != db.rename(olddb)) 00672 return error ("Failed to rename " + db.dbName() + 00673 " as " + olddb.filePath()); 00674 } 00675 00676 // Install the new database 00677 // Warning: the new file and the old one can be in a different path 00678 // BdbDistFile newfile (db.filePath()); 00679 BdbDistFile newfile (impfile.directory() + "/" + db.fileName(), impfile.host(), impfile.pudPort()); 00680 if (BdbcSuccess != impfile.rename(newfile)) 00681 return error ("Failed to rename " + impfile.fullPath() + 00682 " as " + newfile.fullPath()); 00683 00684 // Change the database to this new file 00685 changeDb(db, newfile, chmodRead); 00686 00687 // Remove the old file 00688 if (olddb.isFileExist() && BdbcSuccess != olddb.remove()) 00689 message ("Failed to remove the old " + olddb.fullPath()); 00690 00691 return BdbcSuccess; 00692 } 00693 00694 /*********************************************************************************/ 00695 /*********************************************************************************/ 00696 00697 // Context: Update Transaction 00698 // 00699 // Access: Update 00700 // 00701 // Privileges: collection authorization level 00702 00703 BdbStatus BdbDistribution::attachCollection (BdbTString pathname, BdbTString oid, 00704 d_Boolean force, 00705 d_Boolean fixTreeNode) 00706 { 00707 verbose("Attaching collection " + pathname + 00708 " force " + BdbTString(force) + 00709 " fixtreenode " + BdbTString(fixTreeNode)); 00710 00711 // Check for the transaction mode 00712 if (!checkTransaction(BdbcUpdate)) 00713 return error ("Need an update transaction"); 00714 00715 // Convert the OID string to 4 numbers 00716 char* buffer = new char[oid.length() + 1]; 00717 strcpy(buffer, oid); 00718 00719 for (char* sep = buffer; *sep != '\0'; sep++) 00720 if (*sep == '-' || *sep == '#') 00721 *sep = ' '; 00722 00723 int dbid, contid, pageid, slotid; 00724 if (sscanf(buffer, "%d %d %d %d", &dbid, &contid, &pageid, &slotid) != 4) 00725 return error ("Invalid collection id: " + oid); 00726 00727 // Check if the collection exists 00728 // If yes, and if the collection has the same "oid", it's OK 00729 // else, if the "force" flag is not set, this is an error 00730 BdbHandle(BdbCollectionP) collH; 00731 BdbRef(BdbCollectionP) collR; 00732 00733 BdbEventStore* estore = BdbEventStore::instance(); 00734 d_Boolean deleteCollNode = false; 00735 00736 BdbAbsCollectionT<BdbEventT>* collection = 00737 estore->collection(pathname, (*(BdbEventT*)0)); 00738 if (0 != collection) { 00739 collH = collection->persistent(); 00740 collR = collH; 00741 00742 // Check the collection OID 00743 if (collR.get_DB() == dbid && collR.get_OC() == contid && 00744 collR.get_page() == pageid && collR.get_slot() == slotid) { 00745 // Same id. nothing to do unless user want to fix treenode 00746 if (! fixTreeNode ) { 00747 message("Collection " + pathname + 00748 " already exists with the same OID"); 00749 return BdbcSuccess; 00750 } 00751 } 00752 else if (!force) { 00753 // Different id; "force" not specified; 00754 // It's an error 00755 return error ("Collection " + pathname + 00756 " already exist with a diff. OID"); 00757 } 00758 else { 00759 // Different id; "force" specified; 00760 // Delete the collection 00761 //verbose("Removing obsolete collection " + pathname + " (diff. OID)"); 00762 //if (BdbcSuccess != estore->removeCollection(collection)) 00763 // return error ("Failed to remove existing collection " + pathname); 00764 00765 // AT: deletion of collection doesn't work if a collection was 00766 // created in a different federation. Instead, we delete a collection 00767 // node from the treenodes (later, just before creation of a new collnode) 00768 00769 deleteCollNode = true; 00770 } 00771 } 00772 00773 // Check for the tree node root, or create it 00774 char* treepath = new char[pathname.length() + 1]; 00775 strcpy(treepath, pathname); 00776 00777 char* collnode = strrchr(treepath, '/'); 00778 if (collnode == NULL) 00779 return error ("Invalid collection path: " + pathname); 00780 *collnode++ = '\0'; 00781 00782 BdbTreeNode node; 00783 BdbTreeAccess< BdbCollectionP > accessor; 00784 00785 // Create a dummy reference for attaching the collection to this tree node 00786 collR.set_DB(dbid); 00787 collR.set_OC(contid); 00788 collR.set_page(pageid); 00789 collR.set_slot(slotid); 00790 collH = collR; 00791 00792 if (BdbcSuccess != node.moveTo(treepath)) { 00793 verbose("Creating tree node path " + BdbTString(treepath)); 00794 00795 // Set up the autorization level 00796 // if (BdbcSuccess != estore->BdbDomain::setAuthLevel((const char* const)treepath)) { 00797 if (BdbcSuccess != estore->BdbDomain::setAuthLevel(treepath)) { 00798 delete[] treepath; 00799 return error ("No privilege"); 00800 } 00801 00802 if (BdbcSuccess != node.makeTo(treepath)) { 00803 delete[] treepath; 00804 return error ("Failed to create the tree node " + BdbTString(treepath)); 00805 } 00806 00807 } 00808 else { 00809 if (deleteCollNode) { 00810 verbose("Deleting collnode " + BdbTString(collnode) + 00811 " from " + BdbTString(treepath)); 00812 if (BdbcSuccess != accessor.remove(node, collnode)) { 00813 return ("Failed to delete " + BdbTString(collnode) + 00814 " from " + BdbTString(treepath)); 00815 } 00816 } 00817 } 00818 00819 //attach child node 00820 verbose("Attaching collection " + BdbTString(collnode)); 00821 if (BdbcSuccess != accessor.add(node, collH, collnode)) { 00822 delete[] treepath; 00823 return ("Failed to insert the collection " + BdbTString(collnode)); 00824 } 00825 00826 // But unless we are in the original production federation 00827 // We don't want to do so, cause in the analysis federation 00828 // this data must be readonly!! So, this operation is optional 00829 // Use BdbDistCollLoader -fixtreenode 00830 00831 if (fixTreeNode) { 00832 verbose("Fixing treenode for " + BdbTString(treepath)); 00833 BdbHandle(BdbTreeNodeP) nodeP = node.persistent(); 00834 collH->setTreeNode(nodeP); 00835 } 00836 00837 delete[] treepath; 00838 return BdbcSuccess; 00839 } 00840 00841 /*********************************************************************************/ 00842 /*********************************************************************************/ 00843 00844 // Context: Any 00845 // (the operation is done in an autonomous transaction) 00846 // 00847 // Access: n.a. 00848 // 00849 // Privileges: none 00850 00851 BdbStatus BdbDistribution::getFullDbs (ooTVArray(d_ULong)& dbs) 00852 { 00853 verbose("Reading the full databases list ..."); 00854 00855 BdbEventStore& estore( *BdbEventStore::instance( ) ); 00856 BdbEvsClusteringHint* hint = new BdbEvsClusteringHint(estore); 00857 return hint->getAllFullDbs(dbs); 00858 } 00859 00860 /*********************************************************************************/ 00861 /*********************************************************************************/ 00862 00863 // Context: Any 00864 // 00865 // Access: Any 00866 // 00867 // Privileges: System adminitrator 00868 00869 BdbStatus BdbDistribution::flushFullDbs (ooTVArray(d_ULong)& dbs) 00870 { 00871 verbose("Flushingding the full databases list ..."); 00872 00873 // Check for the transaction mode 00874 if (checkTransaction(BdbcNoOpen)) 00875 BdbDomain::activeInstance()->startRead("BdbDistribution::flushFullDbs"); 00876 00877 // Check the user privileges 00878 BdbAuth* auth = BdbAuth::instance( ); 00879 if (!auth->isAuthorized(BdbDomain::Events, BdbDomain::System)) 00880 return error ("No privileges"); 00881 00882 BdbEventStore& estore( *BdbEventStore::instance( ) ); 00883 BdbEvsClusteringHint* hint = new BdbEvsClusteringHint(estore); 00884 BdbStatus status = hint->removeFullDbsFromRegistry(dbs); 00885 00886 // Commit the local transaction, if any 00887 if (!_externalTransaction) 00888 BdbDomain::activeInstance()->commit("BdbDistribution::flushFullDbs"); 00889 00890 return status; 00891 } 00892 00893 /*********************************************************************************/ 00894 /*********************************************************************************/ 00895 00896 // Context: Update Transaction 00897 // 00898 // Access: Update 00899 // 00900 // Privileges: database authorization level 00901 00902 BdbStatus BdbDistribution::clusteringRecordDb (BdbDistDatabase& db) 00903 { 00904 verbose ("Registering " + db.dbName() + " ..."); 00905 00906 // Check for the transaction mode 00907 if (!checkTransaction(BdbcUpdate)) 00908 return error ("Need an update transaction"); 00909 00910 // Preliminary checks 00911 if (!db.isDbExist()) 00912 return error ("No such database: " + db.dbName()); 00913 00914 // Privileges 00915 if (!db.isAuthorized()) 00916 return error ("No privilege to manage: " + db.dbName()); 00917 00918 BdbDbTreeSingleton* treesingleton = BdbDbTreeSingleton::instance(); 00919 BdbDbInfo dbinfo (db.dbName(), db.host(), db.filePath()); 00920 if (BdbcSuccess != treesingleton->registerDb(dbinfo)) 00921 return error ("Failed to register " + db.dbName()); 00922 00923 return BdbcSuccess; 00924 } 00925 00926 /*********************************************************************************/ 00927 /*********************************************************************************/ 00928 00929 // This entry point is for the shadowed database 00930 BdbStatus BdbDistribution::clusteringRecordDb (const char* dbname, const char* host, 00931 const char* filepath) 00932 { 00933 verbose ("Registering " + BdbTString(dbname) + " ..."); 00934 00935 // Check for the transaction mode 00936 if (!checkTransaction(BdbcUpdate)) 00937 return error ("Need an update transaction"); 00938 00939 // Privileges 00940 BdbDistFile file(filepath); 00941 if (!file.isAuthorized()) 00942 return error ("No privilege to manage: " + BdbTString(dbname)); 00943 00944 BdbDbTreeSingleton* treesingleton = BdbDbTreeSingleton::instance(); 00945 BdbDbInfo dbinfo (dbname, host, filepath); 00946 if (BdbcSuccess != treesingleton->registerDb(dbinfo)) 00947 return error ("Failed to register " + BdbTString(dbname)); 00948 00949 return BdbcSuccess; 00950 } 00951 00952 /*********************************************************************************/ 00953 /*********************************************************************************/ 00954 00955 // Context: Update Transaction 00956 // 00957 // Access: Update 00958 // 00959 // Privileges: database authorization level 00960 00961 BdbStatus BdbDistribution::clusteringUnrecordDb (BdbDistDatabase& db) 00962 { 00963 verbose ("Unregistering " + db.dbName() + " ..."); 00964 00965 // Check for the transaction mode 00966 if (!checkTransaction(BdbcUpdate)) 00967 return error ("Need an update transaction"); 00968 00969 // Preliminary checks 00970 if (!db.isDbExist()) 00971 return error ("No such database: " + db.dbName()); 00972 00973 // Privileges 00974 if (!db.isAuthorized()) 00975 return error ("No privilege to manage: " + db.dbName()); 00976 00977 BdbDbTreeSingleton* treesingleton = BdbDbTreeSingleton::instance(); 00978 BdbDbInfo dbinfo (db.dbName(), db.host(), db.filePath()); 00979 00980 if (BdbcSuccess != treesingleton->unregisterDb(dbinfo)) 00981 return error ("Failed to unregister " + db.dbName()); 00982 00983 return BdbcSuccess; 00984 } 00985 00986 /*********************************************************************************/ 00987
BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us
Page Owner: Jacek Becla
Last Update: October 04, 2002