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  

/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