Database.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021   Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #include <assert.h>
00026 #include "eyedb_p.h"
00027 #include "eyedb/DBM_Database.h"
00028 #include "IteratorBE.h"
00029 #include "OQLBE.h"
00030 #include "BEQueue.h"
00031 //#define FRONT_END
00032 #include "kernel.h"
00033 #include <eyedblib/butils.h>
00034 #include "db_p.h"
00035 #include "ExecutableCache.h"
00036 #include "oqlctb.h"
00037 #include <eyedb/GenHashTable.h>
00038 #include "version_p.h"
00039 
00040 #include <map>
00041 
00042 #define FULL_CACHE_OBJECTS
00043 #define CACHE_OBJECTS
00044 
00045 //#define STRICT_NOT_NESTED_TRANSACTIONS
00046 
00047 namespace eyedb {
00048 
00049   //static std::map<Database *, bool> db_list;
00050 
00051   LinkedList *Database::dbopen_list;
00052 
00053   //TransactionMode Database::global_def_trmod = idbReadWriteSharedTRMode;
00054   // changed the 19/10/99
00055 
00056   Bool Database::def_commit_on_close = False;
00057 
00058   Bool edb_is_back_end = False;
00059   //static char *default_voldir;
00060 
00061 #if 0
00062   static char *
00063   getPath(char *path, Bool inplace = False)
00064   {
00065     if (!path)
00066       return 0;
00067 
00068     if (*path == '/')
00069       return path;
00070 
00071     static char dirname[256], name[256];
00072 
00073     if (!*dirname) {
00074       const char *voldir = default_voldir;
00075 
00076       if (!voldir)
00077         voldir = ClientConfig::getCValue("databasedir");
00078 
00079       if (voldir)
00080         strcpy(dirname, voldir);
00081       else
00082         getcwd(dirname, sizeof(dirname)-1);
00083     }
00084 
00085     sprintf(name, "%s/%s", dirname, path);
00086 
00087     if (inplace) {
00088       strcpy(path, name);
00089       return path;
00090     }
00091     else {
00092       delete path;
00093       return strdup(name);
00094     }
00095   }
00096 #endif
00097 
00098   /*
00099     void Database::setDefaultVolumeDirectory(const char *voldir)
00100     {
00101     if (voldir)
00102     default_voldir = strdup(voldir);
00103     }
00104   */
00105 
00106   void Database::init(const char *_dbmdb_str)
00107   {
00108     //  printf("Database::Database(this=%p)\n", this);
00109     //db_list[this] = true;
00110 
00111     if (_dbmdb_str)
00112       dbmdb_str = strdup(_dbmdb_str);
00113     else {
00114       const char *str = getDefaultDBMDB();
00115       if (str)
00116         dbmdb_str = strdup(str);
00117       else
00118         dbmdb_str = 0;
00119     }
00120 
00121     name = 0;
00122     dbid = 0;
00123     uid = 0;
00124     m_protoid.invalidate();
00125 
00126     conn = (Connection *)0;
00127     dbh = (DbHandle *)0;
00128     open_refcnt = 0;
00129     temp_cache = new ObjCache(64);
00130     curtrs = 0;
00131     roottrs = 0;
00132     commit_on_close = False;
00133     commit_on_close_set = False;
00134     trs_cnt = 0;
00135     exec_cache = new ExecutableCache();
00136     trig_dl = 0;
00137     oqlInit = False;
00138     obj_register = 0;
00139     auto_register_on = False;
00140     store_on_commit = True;
00141 
00142     sch = 0;
00143     open_state = False;
00144     open_flag = (OpenFlag)0;
00145     is_back_end = edb_is_back_end;
00146     bequeue = new BEQueue;
00147 
00148     def_params = TransactionParams::getGlobalDefaultTransactionParams();
00149     version = 0;
00150 
00151     database_file = 0;
00152     datafile_cnt = 0;
00153     datafiles = 0;
00154 
00155     dataspace_cnt = 0;
00156     dataspaces = 0;
00157 
00158     _user   = (char *)0;
00159     _passwd = (char *)0;
00160     consapp_cnt = 0;
00161 
00162     setClass(Object_Class);
00163     sysclsDatabase::setConsApp(this);
00164     oqlctbDatabase::setConsApp(this);
00165     utilsDatabase::setConsApp(this);
00166   }
00167 
00168   Status
00169   Database::setDefaultTransactionParams(const TransactionParams &params)
00170   {
00171     Status s;
00172 
00173     if (s = Transaction::checkParams(params, False))
00174       return s;
00175 
00176     def_params = params;
00177     return Success;
00178   }
00179 
00180   TransactionParams
00181   Database::getDefaultTransactionParams()
00182   {
00183     return def_params;
00184   }
00185 
00186   Database::Database(const char *s, const char * _dbmdb_str) : Struct()
00187   {
00188     init(_dbmdb_str);
00189     name = strdup(s);
00190   }
00191 
00192   Database::Database(const char *s, int _dbid, const char * _dbmdb_str) : Struct()
00193   {
00194     init(_dbmdb_str);
00195     name = strdup(s);
00196     dbid = _dbid;
00197   }
00198 
00199   Database::Database(Connection *conn,
00200                      const char *dbname,
00201                      Database::OpenFlag flag,
00202                      const char *user,
00203                      const char *passwd)
00204   {
00205     init_open(conn, dbname, 0, flag, user, passwd);
00206   }
00207 
00208   Database::Database(Connection *conn,
00209                      const char *dbname,
00210                      const char *_dbmdb_str,
00211                      Database::OpenFlag flag,
00212                      const char *user,
00213                      const char *passwd)
00214   {
00215     init_open(conn, dbname, _dbmdb_str, flag, user, passwd);
00216   }
00217 
00218   void Database::init_open(Connection *conn,
00219                            const char *dbname,
00220                            const char *_dbmdb_str,
00221                            Database::OpenFlag flag,
00222                            const char *user,
00223                            const char *passwd)
00224   {
00225     init(_dbmdb_str);
00226     name = strdup(dbname);
00227     Status status = open(conn, flag, user, passwd);
00228     if (status)
00229       throw *status;
00230   }
00231 
00232   Database::Database(const Database &_db) : Struct(_db)
00233   {
00234     int r = _db.open_refcnt + 1;
00235     init(_db.dbmdb_str);
00236     name        = strdup(_db.name);
00237     dbid        = _db.dbid;
00238     conn        = _db.conn;
00239     sch         = _db.sch;
00240     open_flag   = _db.open_flag;
00241     dbh         = _db.dbh;
00242     is_back_end = _db.is_back_end;
00243     open_refcnt = r;
00244     version     = _db.version;
00245   }
00246 
00247   Database::Database(int _dbid, const char *_dbmdb_str) : Struct()
00248   {
00249     init(_dbmdb_str);
00250     dbid = _dbid;
00251   }
00252 
00253   char *Database::defaultDBMDB;
00254 
00255   const std::vector<std::string> & Database::getGrantedDBMDB()
00256   {
00257     static std::vector<std::string> granted_dbm;
00258 
00259     if (granted_dbm.size())
00260       return granted_dbm;
00261 
00262     const char *path = ServerConfig::getSValue("granted_dbm");
00263     if (!path) {
00264       const char *default_dbm = getDefaultServerDBMDB();
00265       if (default_dbm)
00266         granted_dbm.push_back(default_dbm);
00267       return granted_dbm;
00268     }
00269 
00270     char *p = strdup(path);
00271     char *sp = p;
00272 
00273     for (;;) {
00274       char *q = strchr(p, ',');
00275       if (q)
00276         *q = 0;
00277       granted_dbm.push_back(p);
00278       if (!q)
00279         break;
00280       p = q + 1;
00281     }
00282 
00283     free(sp);
00284     return granted_dbm;
00285   }
00286 
00287   const char *Database::getDefaultServerDBMDB()
00288   {
00289     return ServerConfig::getSValue("default_dbm");
00290     /*
00291       const std::vector<std::string> & granted_dbm = getGrantedDBMDB();
00292       if (granted_dbm.size())
00293       return granted_dbm[0].c_str();
00294 
00295       return "";
00296     */
00297   }
00298 
00299   const char *Database::getDefaultDBMDB()
00300   {
00301     if (!defaultDBMDB) {
00302       static char buff[256];
00303       const char *path = ClientConfig::getCValue("dbm");
00304       if (!path)
00305         return DBM_Database::defaultDBMDB;
00306       strcpy(buff, path);
00307       return buff;
00308     }
00309 
00310     return defaultDBMDB;
00311   }
00312 
00313   void Database::setDefaultDBMDB(const char *dbmdb_str)
00314   {
00315     free(defaultDBMDB);
00316     defaultDBMDB = strdup(dbmdb_str);
00317   }
00318 
00319   void Database::garbage()
00320   {
00321     //db_list.erase(db_list.find(this));
00322     //printf("Database::garbage(this=%p, %p, oql_info = %p)\n", this, dbh, oql_info);
00323     if (dbh)
00324       close();
00325 
00326     Exception::Mode mode = Exception::setMode(Exception::StatusMode);
00327     void (*handler)(Status, void *) = Exception::getHandler();
00328     Exception::setHandler(NULL);
00329 
00330     if (dbh)
00331       (void)close();
00332     Exception::setHandler(handler);
00333     Exception::setMode(mode);
00334     free(name);
00335     free(_user);
00336     free(_passwd);
00337     free(dbmdb_str);
00338     delete temp_cache;
00339     delete exec_cache;
00340     delete bequeue;
00341 
00342     if (sch)
00343       {
00344         sch->release();
00345         sch = NULL;
00346       }
00347 
00348     garbage_dat_dsp();
00349     Struct::garbage();
00350     delete obj_register;
00351   }
00352 
00353   Database::~Database()
00354   {
00355     garbageRealize();
00356   }
00357 
00358   const char *Database::getName(void) const
00359   {
00360     return name;
00361   }
00362 
00363   int Database::getDbid(void) const
00364   {
00365     return dbid;
00366   }
00367 
00368   Connection *Database::getConnection()
00369   {
00370     return conn;
00371   }
00372 
00373   BEQueue *Database::getBEQueue()
00374   {
00375     return bequeue;
00376   }
00377 
00378   void Database::setCommitOnClose(Bool _commit_on_close)
00379   {
00380     commit_on_close = _commit_on_close;
00381     commit_on_close_set = True;
00382   }
00383 
00384   Status Database::close(void)
00385   {
00386     RPCStatus status;
00387     if (dbh) {
00388       open_refcnt--;
00389       if (open_refcnt > 0) {
00390         ObjectPeer::decrRefCount(this);
00391         return Success;
00392       }
00393 
00394       Bool commit = (commit_on_close_set ? commit_on_close :
00395                      def_commit_on_close);
00396       if (curtrs) {
00397         RPCStatus rpc_status;
00398         if ((rpc_status = (commit ? eyedb::transactionCommit(dbh, 0 ) :
00399                            eyedb::transactionAbort(dbh, 0))) != RPCSuccess) {
00400           delete curtrs;
00401           curtrs = 0;
00402         }
00403       }
00404 
00405       if (isBackEnd())
00406         status = IDB_dbClose((DbHandle *)dbh->u.dbh);
00407       else
00408         status = dbClose(dbh);
00409 
00410       if (status == RPCSuccess) {
00411         free(dbh);
00412         dbh = 0;
00413         /*
00414           sch->release();
00415           sch = 0;
00416         */
00417         dbid = 0;
00418 
00419         dbopen_list->deleteObject(this);
00420 
00421         return Success;
00422       }
00423       else
00424         return StatusMake(status);
00425     }
00426 
00427     return Exception::make(IDB_DATABASE_CLOSE_ERROR, "database '%s' is not opened", getTName());
00428   }
00429 
00430   Status Database::init_db(Connection *ch)
00431   {
00432     sch = new Schema();
00433     eyedb_CHECK_RETURN(open(ch, DBRW, _user, _passwd));
00434 
00435     Status status = sch->init(this, True);
00436 
00437     if (status) {
00438       close();
00439       return status;
00440     }
00441     else {
00442       sch->setDatabase(this);
00443       return close();
00444     }
00445   }
00446 
00447   const char *
00448   Database::getTName() const
00449   {
00450     static char buff[16];
00451 
00452     if (name)
00453       return name;
00454 
00455     sprintf(buff, "#%d", dbid);
00456     return buff;
00457   }
00458 
00459   Status
00460   Database::invalidDbmdb(Error err) const
00461   {
00462     return Exception::make(err,
00463                            "dbmfile is not set for Database.handle '%s': check your `dbm' configuration variable or use `-eyedbdbm' command line option",
00464                            getTName());
00465     /* , or use argument #2 of Database constructor */
00466   }
00467 
00468   Status Database::create(Connection *ch,
00469                           DbCreateDescription *pdbdesc)
00470   {
00471     return create(ch, (char *)0, (char *)0, pdbdesc);
00472   }
00473 
00474   Status Database::create_prologue(DbCreateDescription &dbdesc,
00475                                    DbCreateDescription **pdbdesc)
00476   {
00477     if (!*pdbdesc) {
00478       eyedb_clear(dbdesc);
00479 
00480       eyedbsm::DbCreateDescription *d = &dbdesc.sedbdesc;
00481       if (!strcmp(name, DBM_Database::getDbName())) {
00482         strcpy(dbdesc.dbfile, dbmdb_str);
00483         char *q = strdup(dbmdb_str), *p;
00484 
00485         if ((p = strrchr(q, '.')) && !strchr(p, '/'))
00486           *p = 0;
00487 
00488         sprintf(d->dat[0].file, "%s.dat", q);
00489         delete q;
00490       }
00491       else {
00492         sprintf(dbdesc.dbfile, "%s.dbs", name);
00493         sprintf(d->dat[0].file, "%s.dat", name);
00494       }
00495 
00496       d->dat[0].mtype    = eyedbsm::BitmapType;
00497       d->dat[0].sizeslot = 32;
00498       d->dbid     = 0;
00499       d->ndat     = 1;
00500       d->dat[0].maxsize = 2000000;
00501       *pdbdesc = &dbdesc;
00502     }
00503     else if (!strcmp(name, DBM_Database::getDbName()) &&
00504              strcmp((*pdbdesc)->dbfile, dbmdb_str))
00505       return Exception::make(IDB_DATABASE_CREATE_ERROR,
00506                              "when creating a dbmfile, dbfile must be equal to dbmdb_str ('%s' != '%s')", (*pdbdesc)->dbfile, dbmdb_str);
00507 
00508     //getPath(dbdesc.dbfile, True);
00509 
00510     eyedbsm::DbCreateDescription *d = &(*pdbdesc)->sedbdesc;
00511 
00512     return Success;
00513   }
00514 
00515   Status Database::create(Connection *ch, const char *user,
00516                           const char *passwd,
00517                           DbCreateDescription *pdbdesc)
00518   {
00519     RPCStatus rpc_status;
00520     DbCreateDescription dbdesc;
00521 
00522     if (!dbmdb_str)
00523       return invalidDbmdb(IDB_DATABASE_CREATE_ERROR);
00524 
00525     if (!strcmp(name, DBM_Database::getDbName()))
00526       return Exception::make(IDB_DATABASE_CREATE_ERROR, "must use a DBM_Database object to create a DBM database\n");
00527 
00528     check_auth(user, passwd, "creating database");
00529     set_auth(user, passwd);
00530 
00531     create_prologue(dbdesc, &pdbdesc);
00532 
00533     rpc_status = dbCreate(ConnectionPeer::getConnH(ch), dbmdb_str,
00534                           user, passwd, name,
00535                           pdbdesc);
00536 
00537     if (rpc_status == RPCSuccess) {
00538       conn = ch;
00539       return init_db(ch);
00540     }
00541     else
00542       return StatusMake(rpc_status);
00543   }
00544 
00545   static Status
00546   remove_db_realize(ConnHandle *connh, const char *dbmdb_str,
00547                     const char *user, const char *passwd,
00548                     const char *name)
00549   {
00550     if (!connh)
00551       return Exception::make(IDB_DATABASE_REMOVE_ERROR, "connection is not set");
00552 
00553     RPCStatus status;
00554 
00555     check_auth_st(user, passwd, "deleting database", name);
00556 
00557     status = dbDelete(connh, dbmdb_str, user, passwd, name);
00558     if (status == RPCSuccess)
00559       return Success;
00560     else
00561       return StatusMake(status);
00562   }
00563 
00564 
00565   Status Database::remove(Connection *ch, const char *user,
00566                           const char *passwd)
00567   {
00568     if (!dbmdb_str)
00569       return invalidDbmdb(IDB_DATABASE_REMOVE_ERROR);
00570 
00571     check_auth(user, passwd, "removing database");
00572 
00573     return remove_db_realize(ConnectionPeer::getConnH(ch), dbmdb_str,
00574                              user, passwd, name);
00575   }
00576 
00577   Status Database::remove(const char *user, const char *passwd)
00578   {
00579     if (!dbmdb_str)
00580       return invalidDbmdb(IDB_DATABASE_REMOVE_ERROR);
00581   
00582     check_auth(user, passwd, "removing database");
00583   
00584     return remove_db_realize(ConnectionPeer::getConnH(conn), dbmdb_str,
00585                              user, passwd, name);
00586   }
00587 
00588 #define check_dbaccess(s, mode)  \
00589 if ((mode) !=  NoDBAccessMode && \
00590     (mode) !=  ReadDBAccessMode && \
00591     (mode) !=  ReadWriteDBAccessMode && \
00592     (mode) !=  ReadWriteExecDBAccessMode && \
00593     (mode) !=  ReadExecDBAccessMode && \
00594     (mode) !=  AdminDBAccessMode) \
00595   return Exception::make(s, "invalid database access mode 0x%x", (mode))
00596 
00597   Status Database::setUserDBAccess(Connection *ch, const char *username,
00598                                    int mode,
00599                                    const char *user,
00600                                    const char *passwd)
00601   {
00602     if (!dbmdb_str)
00603       return invalidDbmdb(IDB_SET_USER_DBACCESS_ERROR);
00604 
00605     check_auth(user, passwd, "setting user dbaccess");
00606 
00607     check_dbaccess(IDB_SET_USER_DBACCESS_ERROR, mode);
00608 
00609     conn = ch;
00610     RPCStatus rpc_status;
00611     rpc_status = userDBAccessSet(ConnectionPeer::getConnH(conn),
00612                                  dbmdb_str, user, passwd,
00613                                  name, username, mode);
00614     return StatusMake(rpc_status);
00615   }
00616 
00617   Status Database::setDefaultDBAccess(Connection *ch,
00618                                       int mode,
00619                                       const char *user,
00620                                       const char *passwd)
00621   {
00622     if (!dbmdb_str)
00623       return invalidDbmdb(IDB_SET_USER_DBACCESS_ERROR);
00624 
00625     check_auth(user, passwd, "setting default dbacess");
00626 
00627     check_dbaccess(IDB_SET_DEFAULT_DBACCESS_ERROR, mode);
00628 
00629     conn = ch;
00630     RPCStatus rpc_status;
00631     rpc_status = defaultDBAccessSet(ConnectionPeer::getConnH(conn),
00632                                     dbmdb_str, user, passwd,
00633                                     name, mode);
00634     return StatusMake(rpc_status);
00635   }
00636 
00637   Status Database::getInfo(const char *user, const char *passwd,
00638                            DbInfoDescription *pdbdesc) const
00639   {
00640     return getInfo(conn, user, passwd, pdbdesc);
00641   }
00642 
00643   Status Database::getInfo(Connection *ch, 
00644                            const char *user, const char *passwd,
00645                            DbInfoDescription *pdbdesc) const
00646   {
00647     if (!ch)
00648       return Exception::make(IDB_ERROR, "invalid null connection");
00649 
00650     check_auth_st(user, passwd, "get info database", name);
00651 
00652     return StatusMake(dbInfo(ConnectionPeer::getConnH(ch), dbmdb_str,
00653                              user, passwd,
00654                              name, 0, pdbdesc));
00655   }
00656 
00657   /* static */
00658   void Database::init(void)
00659   {
00660     dbopen_list = new LinkedList;
00661   }
00662 
00663   void Database::_release(void)
00664   {
00665     /*
00666     std::map<Database *, bool>::iterator begin = db_list.begin();
00667     std::map<Database *, bool>::iterator end = db_list.end();
00668     
00669     printf("oqml_release: %d\n", db_list.size());
00670     while (begin != end) {
00671       printf("release: %p %d\n", (*begin).first, (*begin).first->isValidObject());
00672       (*begin).first->release();
00673       ++begin;
00674     }
00675 
00676     db_list.clear();
00677     */
00678   }
00679 
00680   static Bool
00681   cmp_dbid(const Database *db, const void *xdbid)
00682   {
00683     int dbid = *(const int *)xdbid;
00684     return (db->getDbid() == dbid ? True : False);
00685   }
00686 
00687   static Bool
00688   cmp_dbname(const Database *db, const void *xdbname)
00689   {
00690     if (!xdbname || !db->getName())
00691       return False;
00692     return (!strcmp(db->getName(), (const char *)xdbname) ? True : False);
00693   }
00694 
00695   static Database *
00696   dbid_make_db(const void *xdbid, const char *dbmdb_str)
00697   {
00698     return new Database(*(const int *)xdbid, dbmdb_str);
00699   }
00700 
00701   static Database *
00702   dbname_make_db(const void *xdbname, const char *dbmdb_str)
00703   {
00704     return new Database((const char *)xdbname, dbmdb_str);
00705   }
00706 
00707   Status
00708   Database::getOpenedDB(int dbid, Database *dbref, Database *&pdb)
00709   {
00710     LinkedListCursor c(dbopen_list);
00711     Database *db;
00712     const char *dbmdb = dbref->getDBMDB();
00713 
00714     pdb = 0;
00715     while (c.getNext((void *&)db))
00716       if (!strcmp(db->getDBMDB(), dbref->getDBMDB()) && db->getDbid() == dbid) {
00717         if (pdb)
00718           return Exception::make
00719             (IDB_ERROR,
00720              "several opened databases with dbid #%d are opened: "
00721              "cannot choose", dbid);
00722         pdb = db;
00723       }
00724 
00725     if (pdb) {
00726       pdb->open_refcnt++; // preventing closing
00727       ObjectPeer::incrRefCount(pdb);    // preventing deleting
00728     }
00729 
00730     return Success;
00731   }
00732 
00733   Status
00734   Database::open(Connection *conn, int dbid,
00735                  const char *dbmdb_str,
00736                  const char *user, const char *passwd,
00737                  OpenFlag flag, const OpenHints *oh, Database **pdb)
00738   {
00739     return open_realize(conn, cmp_dbid, &dbid, dbmdb_str, flag, oh,
00740                         dbid_make_db, user, passwd, pdb);
00741   }
00742 
00743   Status
00744   Database::open(Connection *conn, const char *dbname,
00745                  const char *dbmdb_str,
00746                  const char *user, const char *passwd,
00747                  OpenFlag flag, const OpenHints *oh, Database **pdb)
00748   {
00749     return open_realize(conn, cmp_dbname, dbname, dbmdb_str, flag, oh,
00750                         dbname_make_db, user, passwd, pdb);
00751   }
00752 
00753   Status
00754   Database::open_realize(Connection *conn,
00755                          Bool (*cmp)(const Database *, const void *),
00756                          const void *user_data,
00757                          const char *dbmdb_str, OpenFlag flag,
00758                          const OpenHints *oh,
00759                          Database *(*make_db)(const void *, const char *),
00760                          const char *user,
00761                          const char *passwd,
00762                          Database **pdb)
00763   {
00764     LinkedListCursor c(dbopen_list);
00765 
00766     Database *db;
00767 
00768     /* LOCAL_REMOTE */
00769     OpenFlag oflag = flag;
00770     flag = (OpenFlag)(flag & ~_DBOpenLocal);
00771 
00772     while (c.getNext((void *&)db)) {
00773       // 26/08/02: changed : ``db->getConnection() == conn'' to :
00774       if (db->getConnection()->getConnHandle() == conn->getConnHandle() &&
00775           (*cmp)(db, user_data) && flag == (db->open_flag & ~_DBOpenLocal)) {
00776         // check authentication
00777         if ((!user && !passwd && !db->_user && !db->_passwd) ||
00778             (user && passwd && db->_user && db->_passwd &&
00779              !strcmp(db->_user, user) &&
00780              !strcmp(db->_passwd, passwd))) {
00781           db->open_refcnt++; // preventing closing
00782           ObjectPeer::incrRefCount(db);    // preventing deleting
00783           *pdb = db;
00784           return Success;
00785         }
00786       }
00787     }
00788 
00789     db = make_db(user_data, dbmdb_str);
00790 
00791     /* LOCAL_REMOTE */
00792     Status status = db->open(conn, oflag, oh, user, passwd);
00793     *pdb = !status ? db : 0;
00794     return status;
00795   }
00796 
00797   static Status
00798   check_open_flag(Database::OpenFlag flag)
00799   {
00800     return (flag == Database::DBRead ||
00801             flag == Database::DBRW ||
00802             flag == Database::DBReadLocal ||
00803             flag == Database::DBRWLocal ||
00804             flag == Database::DBReadAdmin ||
00805             flag == Database::DBRWAdmin ||
00806             flag == Database::DBReadAdminLocal ||
00807             flag == Database::DBRWAdminLocal ||
00808             flag == Database::DBSRead ||
00809             flag == Database::DBSReadLocal ||
00810             flag == Database::DBSReadAdmin) ?
00811       Success : Exception::make(IDB_INVALID_DBOPEN_FLAG,
00812                                 "opening flag %s",
00813                                 Database::getStringFlag(flag));
00814   }
00815 
00816   Status
00817   Database::open(Connection *ch, OpenFlag flag,
00818                  const char *user, const char *passwd)
00819   {
00820     return open(ch, flag, 0, user, passwd);
00821   }
00822 
00823   Status
00824   Database::open(Connection *ch, OpenFlag flag, const OpenHints *oh,
00825                  const char *user, const char *passwd)
00826   {
00827     if (dbh)
00828       return Exception::make(IDB_DATABASE_OPEN_ERROR,
00829                              "database '%s' already opened",
00830                              getTName());
00831 
00832     //eyedblib::display_time("%s %s", name, "::open #1");
00833 
00834     if (!dbmdb_str)
00835       return invalidDbmdb(IDB_DATABASE_OPEN_ERROR);
00836 
00837     check_auth(user, passwd, "opening database");
00838 
00839     Status status;
00840     if (status = check_open_flag(flag))
00841       return status;
00842 
00843     set_auth(user, passwd);
00844 
00845     is_back_end = edb_is_back_end;
00846 
00847     //eyedblib::display_time("%s %s", name, "::open #2");
00848     RPCStatus rpc_status;
00849 
00850     conn = ch;
00851     char *rname = 0;
00852     int rdbid = 0;
00853     char *pname = (char *)(name ? name : "");
00854 
00855     //eyedblib::display_time("%s %s", name, "::open #3");
00856     if (isBackEnd()) {
00857       int pid;
00858       DbHandle *ldbh;
00859 
00860       rpc_status = IDB_dbOpen(ConnectionPeer::getConnH(ch), (const char *&)dbmdb_str,
00861                               user, passwd,
00862                               pname, dbid, flag, (oh ? oh->maph : 0),
00863                               (oh ? oh->mapwide : 0),
00864                               &pid, &uid, (void *)this, &rname, &rdbid, 
00865                               &version, &ldbh);
00866       if (rpc_status != RPCSuccess)
00867         return StatusMake(rpc_status);
00868 
00869       //eyedblib::display_time("%s %s", name, "::open #4");
00870       dbh = (DbHandle *)malloc(sizeof(DbHandle));
00871 
00872       IDB_getLocalInfo(ldbh, &dbh->ldbctx, &dbh->sch_oid);
00873 
00874       dbh->ch = ConnectionPeer::getConnH(ch);
00875       dbh->ldbctx.local = rpc_True; // ?? oups
00876       dbh->u.dbh = ldbh;
00877       dbh->flags = flag & ~_DBOpenLocal;
00878       dbh->tr_cnt = 0;
00879       dbh->db = (void *)this;
00880       //eyedblib::display_time("%s %s", name, "::open #5");
00881     }
00882     else {
00883       rpc_status = dbOpen(ConnectionPeer::getConnH(ch), dbmdb_str,
00884                           user, passwd,
00885                           pname, dbid, flag, (oh ? oh->maph : 0),
00886                           (oh ? oh->mapwide : 0), &uid,
00887                           (void *)this, &rname, &rdbid, &version, &dbh);
00888       //eyedblib::display_time("%s %s", name, "::open #6");
00889       if (!rpc_status)
00890         dbh->db = (void *)this;
00891     }
00892 
00893     if (rpc_status != RPCSuccess)
00894       return StatusMake(rpc_status);
00895 
00896     if (rdbid)
00897       dbid = rdbid;
00898 
00899     if (rname) {
00900       if (rname != name)
00901         free(name);
00902       name = strdup(rname);
00903     }
00904 
00905     open_flag = flag;
00906 
00907     if (sch)
00908       return Success;
00909 
00910     open_state = True;
00911 
00912     //eyedblib::display_time("%s %s", name, "::open #7");
00913     transactionBegin();
00914 
00915     Oid sch_oid(dbh->sch_oid);
00916     if ((status = loadObject(&sch_oid,
00917                              (Object **)&sch)) ==
00918         Success)
00919       status = Success;
00920     else {
00921       /*
00922         fprintf(stderr, "error here!\n");
00923         status->print();
00924       */
00925     }
00926 
00927     //eyedblib::display_time("%s %s", name, "::open #8");
00928     transactionCommit();
00929 
00930     //eyedblib::display_time("%s %s", name, "::open #9");
00931     open_state = False;
00932 
00933     if (status == Success) {
00934       dbopen_list->insertObject(this);
00935       open_refcnt = 1;
00936     }
00937 
00938     if (!status) {
00939       transactionBegin();
00940       const Class *m_protclass = sch->getClass("protection");
00941       if (m_protclass)
00942         m_protoid = m_protclass->getOid();
00943       transactionCommit();
00944     }
00945   
00946     //eyedblib::display_time("%s %s", name, "::open #10");
00947     return status;
00948   }
00949 
00950   Status Database::set(ConnHandle *ch,
00951                        int _dbid,
00952                        int flag,
00953                        DbHandle *ldbh,
00954                        rpcDB_LocalDBContext *ldbctx,
00955                        const Oid *sch_oid,
00956                        unsigned int _version)
00957   {
00958     conn = ConnectionPeer::newIdbConnection(ch);
00959 
00960     dbid = _dbid;
00961     version = _version;
00962     dbh = (DbHandle *)malloc(sizeof(DbHandle));
00963 
00964     dbh->ch = ch;
00965     dbh->ldbctx = *ldbctx;
00966     dbh->tr_cnt = 0;
00967     dbh->ldbctx.local = rpc_True; // ?? oups
00968     dbh->u.dbh = ldbh;
00969     dbh->flags = flag & ~_DBOpenLocal;
00970     dbh->sch_oid = *sch_oid->getOid(); // was *sch_oid;
00971     dbh->db = (void *)this;
00972 
00973     is_back_end = True;
00974 
00975     open_state = True;
00976     open_flag = (OpenFlag)flag;
00977 
00978     Status status;
00979   
00980     sch = 0;
00981 
00982     if (status = transactionBegin())
00983       return status;
00984 
00985     if ((status = reloadObject(sch_oid,
00986                                (Object **)&sch)) ==
00987         Success)
00988       ;
00989 
00990     open_state = False;
00991 
00992     if (status == Success) {
00993       dbopen_list->insertObject(this);
00994       open_refcnt = 1;
00995     }
00996 
00997     transactionCommit();
00998     return status;
00999   }
01000 
01001   Status Database::rename(Connection *_conn, const char *newdbname,
01002                           const char *user, const char *passwd)
01003   {
01004     if (!dbmdb_str)
01005       return invalidDbmdb(IDB_DATABASE_RENAME_ERROR);
01006 
01007     check_auth(user, passwd, "renaming database");
01008 
01009     RPCStatus rpc_status;
01010 
01011     rpc_status = dbRename(ConnectionPeer::getConnH(_conn), dbmdb_str,
01012                           user, passwd,
01013                           name, newdbname);
01014     if (rpc_status == RPCSuccess) {
01015       free(name);
01016       name = strdup(newdbname);
01017       return Success;
01018     }
01019 
01020     return StatusMake(rpc_status);
01021   }
01022 
01023   Status Database::move(Connection *_conn,
01024                         DbCreateDescription *dbdesc,
01025                         const char *user, const char *passwd)
01026   {
01027     if (!dbmdb_str)
01028       return invalidDbmdb(IDB_DATABASE_MOVE_ERROR);
01029 
01030     // (FD) added 21/09/2007
01031     check_auth(user, passwd, "moving database");
01032 
01033     RPCStatus rpc_status;
01034 
01035     rpc_status = dbMove(ConnectionPeer::getConnH(_conn), dbmdb_str,
01036                         user, passwd,
01037                         name, dbdesc);
01038 
01039     return StatusMake(rpc_status);
01040   }
01041 
01042   Status Database::copy(Connection *_conn, const char *newdbname,
01043                         Bool newdbid, DbCreateDescription *dbdesc,
01044                         const char *user, const char *passwd)
01045   {
01046     if (!dbmdb_str)
01047       return invalidDbmdb(IDB_DATABASE_COPY_ERROR);
01048 
01049     if (!strcmp(name, newdbname))
01050       return Exception::make(IDB_DATABASE_COPY_ERROR, "cannot copy databases, names are identical '%s'", name);
01051 
01052     // (FD) added 26/09/2007
01053     check_auth(user, passwd, "copying database");
01054 
01055     RPCStatus rpc_status;
01056 
01057     rpc_status = dbCopy(ConnectionPeer::getConnH(_conn), dbmdb_str,
01058                         user, passwd,
01059                         name, newdbname, newdbid, dbdesc);
01060 
01061     return StatusMake(rpc_status);
01062   }
01063 
01064   Status Database::rename(const char *newdbname, const char *user,
01065                           const char *passwd)
01066   {
01067     if (!conn)
01068       return Exception::make(IDB_DATABASE_RENAME_ERROR, "connection is not set");
01069 
01070     //check_auth(user, passwd, "renaming database");
01071 
01072     return rename(conn, newdbname, user, passwd);
01073   }
01074 
01075   Status Database::move(DbCreateDescription *dbdesc,
01076                         const char *user, const char *passwd)
01077   {
01078     check_auth(user, passwd, "move database");
01079 
01080     return move(conn, dbdesc, user, passwd);
01081   }
01082 
01083   Status Database::copy(const char *newdbname, Bool newdbid,
01084                         DbCreateDescription *dbdesc,
01085                         const char *user, const char *passwd)
01086   {
01087     check_auth(user, passwd, "copying database");
01088 
01089     return copy(conn, newdbname, newdbid, dbdesc, user, passwd);
01090   }
01091 
01092 
01093   Bool Database::isBackEnd() const
01094   {
01095     return is_back_end;
01096   }
01097 
01098   Bool Database::isLocal() const
01099   {
01100     return (open_flag & _DBOpenLocal) ? True : False;
01101   }
01102 
01103   const char *Database::getDBMDB() const
01104   {
01105     return dbmdb_str;
01106   }
01107 
01108   DbHandle *Database::getDbHandle(void)
01109   {
01110     return dbh;
01111   }
01112 
01113   Transaction *Database::getCurrentTransaction(void)
01114   {
01115 #if 0
01116     if (!curtrs && dbh->tr_cnt)
01117       {
01118         fprintf(stderr, "in fact is in transaction!\n");
01119         return (Transaction *)1;
01120       }
01121     else if (!curtrs)
01122       fprintf(stderr, "is NOT in transaction!\n");
01123 #endif
01124     return curtrs;
01125   }
01126 
01127   Transaction *Database::getRootTransaction(void)
01128   {
01129     return roottrs;
01130   }
01131 
01132   DbHandle *
01133   database_getDbHandle(Database *db)
01134   {
01135     return (DbHandle *)(db->getDbHandle()->u.dbh);
01136   }
01137 
01138   Bool Database::isInTransaction() const
01139   {
01140     if (curtrs)
01141       return True;
01142   
01143     if (is_back_end)
01144       return IDB_getSeTrsCount(database_getDbHandle((Database *)this)) ?
01145         True : False;
01146 
01147     return dbh && dbh->tr_cnt ? True : False;
01148   }
01149 
01150   Status Database::transactionBegin(const TransactionParams &params)
01151   {
01152     if (!trs_cnt) {
01153       Status status = transactionBegin_realize(&params);
01154 
01155       if (status)
01156         return status;
01157     }
01158 #ifdef STRICT_NOT_NESTED_TRANSACTIONS
01159     else
01160       return Exception::make(IDB_ERROR,
01161                              "nested transactions are not yet implemented");
01162 #endif
01163 
01164     ++trs_cnt;
01165     return Success;
01166   }
01167 
01168   Status
01169   Database::transactionBegin()
01170   {
01171     if (!trs_cnt) {
01172       Status status = transactionBegin_realize(0);
01173 
01174       if (status)
01175         return status;
01176     }
01177 #ifdef STRICT_NOT_NESTED_TRANSACTIONS
01178     else
01179       return Exception::make(IDB_ERROR,
01180                              "nested transactions are not yet implemented");
01181 #endif
01182 
01183     ++trs_cnt;
01184     return Success;
01185   }
01186 
01187   Status
01188   Database::transactionBeginExclusive()
01189   {
01190     TransactionParams params = TransactionParams::getGlobalDefaultTransactionParams();
01191     params.lockmode = DatabaseW;
01192     params.wait_timeout = 1;
01193 
01194     Status s = transactionBegin(params);
01195     if (s && s->getStatus() == eyedbsm::LOCK_TIMEOUT)
01196       return Exception::make(IDB_ERROR,
01197                              "cannot acquire exclusive lock on database %s",
01198                              getName());
01199     return s;
01200   }
01201 
01202   Status Database::transactionBegin_realize
01203   (const TransactionParams *params)
01204   {
01205     RPCStatus rpc_status;
01206     TransactionId tid;
01207     Status s;
01208     TransactionParams sparams = def_params;
01209 
01210     IDB_LOG(IDB_LOG_TRANSACTION, ("database transaction begin\n"));
01211 
01212     if (!params)
01213       params = &sparams;
01214   
01215     if (s = Transaction::checkParams(*params))
01216       return s;
01217   
01218     Transaction *trs = new Transaction(this, *params);
01219 
01220     s = trs->begin();
01221 
01222     if (s == Success) {
01223       if (!curtrs)
01224         roottrs = trs;
01225       curtrs = trs;
01226     }
01227     else
01228       curtrs = 0;
01229 
01230     return s;
01231   }
01232 
01233   Status Database::transactionCommit(void)
01234   {
01235     //  printf("db->transactionCommit()\n");
01236     return transactionCommit_realize();
01237   }
01238 
01239   Status Database::transactionCommit_realize()
01240   {
01241     //printf("commitRealize(%d) %p\n", trs_cnt, curtrs);
01242     if (!curtrs || !trs_cnt)
01243       return Exception::make(IDB_NO_CURRENT_TRANSACTION, "transactionCommit");
01244 
01245     if (trs_cnt > 1) {
01246       --trs_cnt;
01247       return Success;
01248     }
01249 
01250     IDB_LOG(IDB_LOG_TRANSACTION, ("database transaction commit\n"));
01251 
01252     Status s;
01253 
01254     if (store_on_commit && obj_register) {
01255       s = storeRegisteredObjects();
01256       if (s) return s;
01257     }
01258 
01259     //  printf("db->transactionCommit_realize()\n\n");
01260 
01261     s = curtrs->commit();
01262     if (s) return s;
01263 
01264     Transaction *trs = curtrs;
01265 
01266     curtrs = 0;
01267 
01268     if (trs == roottrs)
01269       roottrs = 0;
01270 
01271     delete trs;
01272 
01273     purgeRelease();
01274     if (sch)
01275       sch->revert(False);
01276 
01277     --trs_cnt;
01278     return s;
01279   }
01280 
01281   Status Database::transactionAbort(void)
01282   {
01283     //  printf("db->transactionAbort()\n");
01284     return transactionAbort_realize();
01285   }
01286 
01287   Status Database::transactionAbort_realize()
01288   {
01289     //utlog("abort _ realize(%p, trs_cnt = %d)\n", curtrs, trs_cnt);
01290 
01291     //printf("abortRealize(%d) %p\n", trs_cnt, curtrs);
01292 
01293     if (!curtrs || !trs_cnt)
01294       return Exception::make(IDB_NO_CURRENT_TRANSACTION, "transactionAbort");
01295 
01296     if (trs_cnt > 1) {
01297       --trs_cnt;
01298       return Success;
01299     }
01300 
01301     IDB_LOG(IDB_LOG_TRANSACTION, ("database transaction abort\n"));
01302 
01303     Status s;
01304 
01305     s = curtrs->abort();
01306     if (s) return s;
01307 
01308     Transaction *trs = curtrs;
01309 
01310     curtrs = 0;
01311 
01312     if (trs == roottrs)
01313       roottrs = 0;
01314 
01315     delete trs;
01316 
01317     purgeOnAbort();
01318     purgeRelease();
01319     if (sch)
01320       sch->revert(True);
01321 
01322     --trs_cnt;
01323     return s;
01324   }
01325 
01326   Status
01327   Database::loadObjects(const OidArray &oid_array,
01328                         ObjectPtrVector &obj_vect,
01329                         const RecMode *rcm)
01330   {
01331     ObjectArray obj_array; // true of false ?
01332     Status s = loadObjects(oid_array, obj_array, rcm);
01333     if (s)
01334       return s;
01335     obj_array.makeObjectPtrVector(obj_vect);
01336     return Success;
01337   }
01338 
01339   Status
01340   Database::loadObjects(const OidArray &oid_array,
01341                         ObjectPtrVector &obj_vect,
01342                         LockMode lockmode,
01343                         const RecMode *rcm)
01344   {
01345     ObjectArray obj_array; // true of false ?
01346     Status s = loadObjects(oid_array, obj_array, lockmode, rcm);
01347     if (s)
01348       return s;
01349     obj_array.makeObjectPtrVector(obj_vect);
01350     return Success;
01351   }
01352 
01353   Status
01354   Database::loadObjects(const OidArray &oid_array,
01355                         ObjectArray &obj_array,
01356                         const RecMode *rcm)
01357   {
01358     return loadObjects(oid_array, obj_array, DefaultLock, rcm);
01359   }
01360 
01361   Status
01362   Database::loadObjects(const OidArray &oid_array,
01363                         ObjectArray &obj_array,
01364                         LockMode lockmode,
01365                         const RecMode *rcm)
01366   {
01367     int count = oid_array.getCount();
01368     Object **objs = (Object **)calloc(sizeof(Object *), count);
01369 
01370     obj_array.set(objs, count);
01371 
01372     for (int i = 0; i < count; i++) {
01373       const Oid *poid = &oid_array[i];
01374       Status status = loadObject(*poid, objs[i], lockmode, rcm);
01375       if (status)
01376         return status;
01377     }
01378 
01379     return Success;
01380   }
01381 
01382   Status
01383   Database::loadObject(const Oid &xoid, ObjectPtr &o_ptr,
01384                        const RecMode *recmode)
01385   {
01386     Object *o = 0;
01387     Status s = loadObject(xoid, o, recmode);
01388     o_ptr = o;
01389     return s;
01390   }
01391 
01392   Status
01393   Database::loadObject(const Oid &xoid, ObjectPtr &o_ptr,
01394                        LockMode lockmode,
01395                        const RecMode *recmode)
01396   {
01397     Object *o = 0;
01398     Status s = loadObject(xoid, o, lockmode, recmode);
01399     o_ptr = o;
01400     return s;
01401   }
01402 
01403   Status
01404   Database::reloadObject(const Oid &xoid, ObjectPtr &o_ptr,
01405                          const RecMode *recmode)
01406   {
01407     Object *o = 0;
01408     Status s = reloadObject(xoid, o, recmode);
01409     o_ptr = o;
01410     return s;
01411   }
01412 
01413   Status
01414   Database::reloadObject(const Oid &xoid, ObjectPtr &o_ptr,
01415                          LockMode lockmode,
01416                          const RecMode *recmode)
01417   {
01418     Object *o = 0;
01419     Status s = reloadObject(xoid, o, lockmode, recmode);
01420     o_ptr = o;
01421     return s;
01422   }
01423 
01424   Status
01425   Database::loadObject(const Oid &xoid, Object *&o,
01426                        const RecMode *recmode)
01427   {
01428     return loadObject(xoid, o, DefaultLock, recmode);
01429   }
01430 
01431   Status
01432   Database::loadObject(const Oid &xoid, Object *&o,
01433                        LockMode lockmode,
01434                        const RecMode *recmode)
01435   {
01436     return loadObject(&xoid, &o, lockmode, recmode);
01437   }
01438 
01439   Status
01440   Database::loadObject(const Oid *poid, Object **o,
01441                        const RecMode *recmode)
01442   {
01443     return loadObject(poid, o, DefaultLock, recmode);
01444   }
01445 
01446   Status
01447   Database::loadObject(const Oid *poid, Object **o,
01448                        LockMode lockmode,
01449                        const RecMode *recmode)
01450   {
01451     if (!poid->isValid())
01452       return Exception::make(IDB_ERROR, "loadObject: oid '%s' is invalid",
01453                              poid->getString());
01454 
01455     if (recmode->getType() != RecMode_NoRecurs)
01456       temp_cache->empty();
01457 
01458     return loadObject_realize(poid, o, lockmode, recmode);
01459   }
01460 
01461   Status
01462   Database::reloadObject(const Oid &_oid, Object *&o,
01463                          const RecMode *recmode)
01464   {
01465     return reloadObject(&_oid, &o, DefaultLock, recmode);
01466   }
01467 
01468   Status
01469   Database::reloadObject(const Oid &_oid, Object *&o,
01470                          LockMode lockmode,
01471                          const RecMode *recmode)
01472   {
01473     return reloadObject(&_oid, &o, lockmode, recmode);
01474   }
01475 
01476   Status
01477   Database::reloadObject(const Oid *poid, Object **o,
01478                          const RecMode *recmode)
01479   {
01480     return reloadObject(poid, o, DefaultLock, recmode);
01481   }
01482 
01483   Status
01484   Database::reloadObject(const Oid *poid, Object **o,
01485                          LockMode lockmode,
01486                          const RecMode *recmode)
01487   {
01488     if (!poid->isValid())
01489       return Exception::make(IDB_ERROR, "loadObject: oid '%s' is invalid",
01490                              poid->getString());
01491 
01492     if (recmode->getType() != RecMode_NoRecurs)
01493       temp_cache->empty();
01494 
01495     return loadObject_realize(poid, o, lockmode, recmode, True);
01496   }
01497 
01498   Status
01499   Database::loadObject_realize(const Oid *poid,
01500                                Object **o,
01501                                LockMode lockmode,
01502                                const RecMode *recmode,
01503                                Bool reload)
01504   {
01505     int obj_dbid = poid->getDbid();
01506     static int cnt;
01507 
01508     if (!poid->isValid())
01509       return Exception::make(IDB_ERROR, "invalid null oid");
01510 
01511     if (!obj_dbid)
01512       return Exception::make(IDB_ERROR, "oid '%s': invalid null database",
01513                              poid->toString());
01514 
01515     if (obj_dbid != dbid) {
01516       Database *xdb;
01517       Status status = getOpenedDB(obj_dbid, this, xdb);
01518       if (status) return status;
01519       if (!xdb)
01520         return Exception::make(IDB_DATABASE_LOAD_OBJECT_ERROR,
01521                                "cannot load object %s: "
01522                                "database ID #%d must be manually "
01523                                "opened by the client",
01524                                poid->toString(), obj_dbid);
01525       if (reload)
01526         return xdb->reloadObject(poid, o, lockmode, recmode);
01527       return xdb->loadObject(poid, o, lockmode, recmode);
01528     }
01529 
01530     //printf("trying to load %s\n", poid->toString());
01531 #ifdef CACHE_OBJECTS
01532     if (reload)
01533       uncacheObject(*poid);
01534     else if (curtrs && (*o = (Object *)curtrs->getObject(*poid))) {
01535       ObjectPeer::incrRefCount(*o);
01536       //printf("object %s in transaction cache\n", poid->getString());
01537       return Success;
01538     }
01539 #endif
01540 
01541     if (recmode->getType() != RecMode_NoRecurs &&
01542         (*o = (Object *)temp_cache->getObject(*poid)))
01543       return Success;
01544 
01545     RPCStatus rpc_status;
01546     ObjectHeader hdr;
01547     Status status = Success;
01548 
01549     Data o_idr = 0;
01550     const Class *cl;
01551 
01552 #ifdef PROBE
01553     p_probeM(eyedb_probe_h, 1);
01554 #endif
01555   
01556     short datid;
01557     if (isLocal())
01558       rpc_status = objectRead(dbh, 0, &o_idr, &datid, poid->getOid(), &hdr,
01559                               lockmode, (void **)&cl);
01560     else {
01561       if ((rpc_status = objectRead(dbh, 0, &o_idr, &datid, poid->getOid(),
01562                                    0,
01563                                    lockmode, 0)) ==
01564           RPCSuccess) {
01565         Offset offset = 0;
01566         object_header_decode(o_idr, &offset, &hdr);
01567 
01568         cl = sch->getClass(hdr.oid_cl, True);
01569         if (cl && !ObjectPeer::isRemoved(hdr)) {
01570           Size o_idr_size = cl->getIDRObjectSize();
01571           if (o_idr_size > hdr.size) {
01572             o_idr = (Data)realloc(o_idr, o_idr_size);
01573             memset(o_idr + hdr.size, 0, o_idr_size - hdr.size);
01574             hdr.size = o_idr_size;
01575           }
01576         }
01577       }
01578     }
01579 
01580 #ifdef PROBE
01581     p_probeM(eyedb_probe_h, 1);
01582 #endif
01583     if (!rpc_status) {
01584       const Datafile *datafile;
01585       status = getDatafile(datid, datafile);
01586       if (status)
01587         return status;
01588 
01589       const Dataspace *dataspace = datafile->getDataspace();
01590       if (!dataspace) {
01591         return Exception::make(IDB_DATABASE_LOAD_OBJECT_ERROR,
01592                                "loading object %s: "
01593                                "cannot find dataspace for datafile %d",
01594                                poid->getString(),
01595                                datafile->getId());
01596       }
01597 
01598       short dspid = dataspace->getId();
01599 
01600       Status (*make)(Database *, const Oid *, Object **,
01601                      const RecMode *,
01602                      const ObjectHeader *, Data,
01603                      LockMode lockmode,
01604                      const Class *) =
01605         getMakeFunction(hdr.type);
01606 
01607       if (!make)
01608         return Exception::make(IDB_ERROR,
01609                                "internal error: unknown object type "
01610                                "for oid %s (type:%x)", poid->getString(),
01611                                hdr.type);
01612 
01613       status = make(this, poid, o, recmode, &hdr, o_idr, lockmode, cl);
01614       
01615 #ifdef PROBE
01616       p_probeM(eyedb_probe_h, 2);
01617 #endif
01618       if (!status) {
01619         ObjectPeer::setDatabase(*o, this);
01620         ObjectPeer::loadEpilogue(*o, *poid, hdr, o_idr);
01621         if (recmode->getType() != RecMode_NoRecurs)
01622           temp_cache->insertObject(*poid, (void *)*o);
01623 
01624         Status s = (*o)->setDataspace(dataspace);
01625         if (s)
01626           s->print();
01627         (*o)->setDspid(dspid);
01628 
01629 #ifdef FULL_CACHE_OBJECTS
01630         if (curtrs)
01631           curtrs->cacheObject(*poid, *o);
01632 #endif
01633       }
01634 
01635 #ifdef PROBE
01636       p_probeM(eyedb_probe_h, 2);
01637 #endif
01638       return status;
01639     }
01640 
01641     free(o_idr);
01642 
01643     if (rpc_status->err == eyedbsm::OBJECT_PROTECTED) {
01644       *o = new UnreadableObject(this);
01645       ObjectPeer::setOid(*o, *poid);
01646       return Success;
01647     }
01648 
01649     return StatusMake(rpc_status);
01650   }
01651 
01652   Status
01653   Database::isRemoved(const Oid &poid, Bool &isremoved) const
01654   {
01655     RPCStatus rpc_status;
01656     Class *cl;
01657     unsigned char data[IDB_OBJ_HEAD_SIZE];
01658     rpc_status = dataRead(dbh, 0, IDB_OBJ_HEAD_SIZE, data, 0, poid.getOid());
01659     if (rpc_status)
01660       return StatusMake(rpc_status);
01661 
01662     Offset offset = 0;
01663     ObjectHeader hdr;
01664 
01665     if (!object_header_decode(data, &offset, &hdr))
01666       return Exception::make(IDB_INVALID_OBJECT_HEADER,
01667                              "Database::isRemoved");
01668 
01669     isremoved = IDBBOOL(hdr.xinfo & IDB_XINFO_REMOVED);
01670     return Success;
01671   }
01672 
01673   Status Database::removeObject(const Oid &poid,
01674                                 const RecMode *rcm)
01675   {
01676     return removeObject(&poid, rcm);
01677   }
01678 
01679   Status Database::removeObject(const Oid *poid,
01680                                 const RecMode *rcm)
01681   {
01682     Object *o;
01683     Status status;
01684 
01685     if ((open_flag & _DBRW) != _DBRW)
01686       return Exception::make(IDB_OBJECT_REMOVE_ERROR, "remove object '%s': database '%s' is not opened for writing", poid->getString(), name);
01687 
01688 #ifdef CACHE_OBJECTS
01689     int must_load = (!curtrs || !(o = (Object *)curtrs->getObject(*poid)));
01690 
01691     if (must_load)
01692 #endif
01693       {
01694         status = loadObject(poid, &o, rcm);
01695 
01696         if (status)
01697           return status;
01698       }
01699 
01700     status = o->remove(rcm);
01701 
01702 #ifdef CACHE_OBJECTS
01703     if (must_load)
01704 #endif
01705       o->release();
01706 
01707     return status;
01708   }
01709 
01710   Status
01711   Database::setObjectLock(const Oid &_oid, LockMode lockmode)
01712   {
01713     RPCStatus rpc_status;
01714     int alockmode;
01715     if ((rpc_status = eyedb::setObjectLock(dbh, _oid.getOid(), lockmode, &alockmode))
01716         != RPCSuccess)
01717       return StatusMake(rpc_status);
01718     
01719     return Success;
01720   }
01721 
01722   Status
01723   Database::setObjectLock(const Oid &_oid, LockMode lockmode,
01724                           LockMode &alockmode)
01725   {
01726     RPCStatus rpc_status;
01727     int _alockmode;
01728     if ((rpc_status = eyedb::setObjectLock(dbh, _oid.getOid(), lockmode, &_alockmode))
01729         != RPCSuccess)
01730       return StatusMake(rpc_status);
01731 
01732     alockmode = (LockMode)_alockmode;
01733     return Success;
01734   }
01735 
01736   Status
01737   Database::getObjectLock(const Oid &_oid, LockMode &alockmode)
01738   {
01739     RPCStatus rpc_status;
01740     int _alockmode;
01741     if ((rpc_status = eyedb::getObjectLock(dbh, _oid.getOid(), &_alockmode))
01742         != RPCSuccess)
01743       return StatusMake(rpc_status);
01744 
01745     alockmode = (LockMode)_alockmode;
01746     return Success;
01747   }
01748 
01749   Status Database::makeObject(const Oid *poid,
01750                               const ObjectHeader *hdr,
01751                               Data _idr,
01752                               Object **o, Bool useCache)
01753   {
01754     if (!poid->isValid())
01755       return Exception::make(IDB_ERROR, "makeObject: oid '%s' is invalid",
01756                              poid->getString());
01757     temp_cache->empty();
01758     return makeObject_realize(poid, hdr, _idr, o, useCache);
01759   }
01760 
01761   Status Database::makeObject_realize(const Oid *poid,
01762                                       const ObjectHeader *hdr,
01763                                       Data _idr,
01764                                       Object **o, Bool useCache)
01765   {
01766     if (*o = (Object *)temp_cache->getObject(*poid))
01767       return Success;
01768 
01769 #ifdef CACHE_OBJECTS
01770     // 18/05/99 WE DO NOT USE CACHE anymore
01771     //  if (useCache && curtrs && (*o = (Object *)curtrs->getObject(*poid)))
01772     if (0) {
01773       ObjectPeer::incrRefCount(*o);
01774       if (!memcmp(_idr, (*o)->getIDR(), hdr->size))
01775         return Success;
01776       else {
01777         fprintf(stderr, "invalid cache for object '%s'\n", 
01778                 poid->getString());
01779         utlog("invalid cache for object '%s'\n", 
01780               poid->getString());
01781       }
01782     }
01783 #endif
01784 
01785     Status status = Success;
01786     Bool copy = False;
01787 
01788     Class *cl = sch->getClass(ClassOidDecode(_idr));
01789     Size _obj_sz = hdr->size;
01790     if (cl) {
01791       Size _psize, _vsize;
01792       _obj_sz = cl->getIDRObjectSize(&_psize, &_vsize);
01793       if (_vsize) {
01794         Data cp_idr = (unsigned char *)malloc(_obj_sz);
01795         memcpy(cp_idr, _idr, hdr->size);
01796         memset(cp_idr + _psize, 0, _vsize);
01797         _idr = cp_idr;
01798         copy = True;
01799       }
01800     }
01801 
01802     Status (*make)(Database *, const Oid *, Object **,
01803                    const RecMode *,
01804                    const ObjectHeader *, Data,
01805                    LockMode lockmode,
01806                    const Class *) =
01807       getMakeFunction(hdr->type);
01808 
01809     if (!make)
01810       return Exception::make(IDB_ERROR,
01811                              "internal error: unknown object type "
01812                              "for oid %s (type:%x)", poid->getString(),
01813                              hdr->type);
01814 
01815     status = make(this, poid, o, NoRecurs,
01816                   hdr, _idr, DefaultLock, 0);
01817 
01818     if (!status) {
01819       status = (*o)->setDatabase(this);
01820       if (status) {
01821         if (copy) free(_idr);
01822         return status;
01823       }
01824 
01825       ObjectPeer::setOid(*o, *poid);
01826       ObjectPeer::setModify(*o, False);
01827       
01828       if (!(*o)->getIDR()) {
01829         Data cp_idr = (unsigned char *)malloc(hdr->size);
01830         memcpy(cp_idr, _idr, hdr->size);
01831         ObjectPeer::setIDR(*o, cp_idr, hdr->size);
01832       }
01833 
01834       ObjectPeer::setTimes(*o, *hdr);
01835       temp_cache->insertObject(*poid, (void *)*o);
01836     }
01837     // added the else if on the 15/04/99
01838     else if (copy)
01839       free(_idr);
01840 
01841     return status;
01842   }
01843 
01844   Bool
01845   Database::isOpened() const
01846   {
01847     return IDBBOOL(open_flag);
01848   }
01849 
01850   Database::OpenFlag Database::getOpenFlag(void) const
01851   {
01852     return open_flag;
01853   }
01854 
01855   const Schema *Database::getSchema(void) const
01856   {
01857     return sch;
01858   }
01859 
01860   void Database::setSchema(Schema *_sch)
01861   {
01862     sch = _sch;
01863     if (sch)
01864       sch->setDatabase(this);
01865   }
01866 
01867   Schema *Database::getSchema(void)
01868   {
01869     return sch;
01870   }
01871 
01872   void Database::insertTempCache(const Oid& poid, void *o)
01873   {
01874     temp_cache->insertObject(poid, o);
01875   }
01876 
01877   void Database::cacheObject(Object *o)
01878   {
01879 #ifdef CACHE_OBJECTS
01880     if (curtrs) {
01881       Oid _oid = o->getOid();
01882       if (_oid.isValid())
01883         curtrs->cacheObject(_oid, o);
01884     }
01885 #endif
01886   }
01887 
01888   Object *
01889   Database::getCacheObject(const Oid &xoid)
01890   {
01891 #ifdef CACHE_OBJECTS
01892     return (curtrs ? curtrs->getObject(xoid) : 0);
01893 #else
01894     return 0;
01895 #endif
01896   }
01897 
01898   ObjectList *
01899   Database::getRegisteredObjects()
01900   {
01901     return (obj_register ? obj_register->getObjects() : 0);
01902   }
01903 
01904   static inline Oid
01905   obj2oid(const Object *o)
01906   {
01907     //  assert(!(((unsigned long)o) & 0x7));
01908     return Oid(((unsigned long)o)>>3, 1, 1);
01909   }
01910 
01911   ObjCache *
01912   Database::makeRegister()
01913   {
01914     return new ObjCache(512);
01915   }
01916 
01917   void
01918   Database::clearRegister()
01919   {
01920     delete obj_register;
01921     obj_register = (auto_register_on ? makeRegister() : 0);
01922   }
01923 
01924   void
01925   Database::storeOnCommit(Bool on)
01926   {
01927     if (on == store_on_commit)
01928       return;
01929 
01930     store_on_commit = on;
01931     if (store_on_commit && !auto_register_on) {
01932       auto_register_on = True;
01933       clearRegister();
01934     }
01935   }
01936 
01937   void
01938   Database::autoRegisterObjects(Bool on)
01939   {
01940     if (on == auto_register_on)
01941       return;
01942 
01943     auto_register_on = on;
01944     clearRegister();
01945   }
01946 
01947   void
01948   Database::addToRegister(const Object *o, Bool force)
01949   {
01950     if (auto_register_on || force) {
01951       if (!obj_register)
01952         obj_register = makeRegister();
01953       obj_register->insertObject(obj2oid(o), (void *)o);
01954     }
01955   }
01956 
01957   void
01958   Database::rmvFromRegister(const Object *o)
01959   {
01960     if (obj_register)
01961       obj_register->deleteObject(obj2oid(o));
01962   }
01963 
01964   Status
01965   Database::storeRegisteredObjects()
01966   {
01967     if (!obj_register)
01968       return Exception::make(IDB_ERROR,
01969                              "Database::storeRegisteredObjects(): "
01970                              "objects are not registered: use Database::registerObjects(True)");
01971 
01972     ObjectList *list = getRegisteredObjects();
01973 
01974     if (!list)
01975       return Success;
01976 
01977     ObjectListCursor c(list);
01978     Object *o;
01979     while (c.getNext(o)) {
01980       //printf("storing registered objects %p\n", o);
01981       Status s = o->store(RecMode::FullRecurs);
01982       if (s) {delete list; return s;}
01983     }
01984 
01985     delete list;
01986     return Success;
01987   }
01988 
01989   void
01990   Database::uncacheObject(Object *o)
01991   {
01992 #ifdef CACHE_OBJECTS
01993     if (curtrs)
01994       curtrs->uncacheObject(o);
01995 #endif
01996   }
01997 
01998   void Database::uncacheObject(const Oid &_oid)
01999   {
02000 #ifdef CACHE_OBJECTS
02001     if (curtrs)
02002       curtrs->uncacheObject(_oid);
02003 #endif
02004   }
02005 
02006   Bool Database::isOpeningState()
02007   {
02008     return open_state;
02009   }
02010 
02011   Status Database::containsObject(const Oid &_oid, Bool &found)
02012   {
02013     found = False;
02014     int _state;
02015     eyedbsm::Oid moid;
02016 
02017     RPCStatus rpc_status = objectCheck(dbh, _oid.getOid(), &_state, &moid);
02018 
02019     if (rpc_status != RPCSuccess)
02020       return StatusMake(rpc_status);
02021 
02022     found = (_state ? True : False);
02023     return Success;
02024   }
02025 
02026 
02027   Status Database::create()
02028   {
02029     return Exception::make(IDB_NOT_YET_IMPLEMENTED, "Database::create");
02030   }
02031 
02032   Status Database::update()
02033   {
02034     return Exception::make(IDB_NOT_YET_IMPLEMENTED, "Database::update");
02035   }
02036 
02037   Status Database::realize(const RecMode*)
02038   {
02039     return Exception::make(IDB_NOT_YET_IMPLEMENTED, "Database::realize");
02040   }
02041 
02042   Status Database::remove(const RecMode*)
02043   {
02044     return Exception::make(IDB_NOT_YET_IMPLEMENTED, "Database::remove");
02045   }
02046 
02047   Status
02048   Database::getObjectClass(const Oid &poid, Oid &cls_oid)
02049   {
02050     RPCStatus rpc_status;
02051     Class *cl;
02052     unsigned char data[IDB_OBJ_HEAD_SIZE];
02053     rpc_status = dataRead(dbh, 0, IDB_OBJ_HEAD_SIZE, data, 0, poid.getOid());
02054     if (rpc_status)
02055       return StatusMake(rpc_status);
02056 
02057     Offset offset = 0;
02058     ObjectHeader hdr;
02059 
02060     if (!object_header_decode(data, &offset, &hdr))
02061       return Exception::make(IDB_INVALID_OBJECT_HEADER,
02062                              "Database::isRemoved");
02063 
02064     cls_oid = hdr.oid_cl;
02065     return Success;
02066   }
02067 
02068   Status
02069   Database::getObjectClass(const Oid &_oid, Class *&_class)
02070   {
02071     _class = 0;
02072 
02073     if (!_oid.isValid())
02074       return Exception::make(IDB_ERROR, "invalid null oid");
02075 
02076     int obj_dbid = _oid.getDbid();
02077 
02078     if (!obj_dbid)
02079       return Exception::make(IDB_ERROR, "oid '%s': invalid null database",
02080                              _oid.toString());
02081 
02082     if (obj_dbid != dbid) {
02083       Database *xdb;
02084       Status status = getOpenedDB(obj_dbid, this, xdb);
02085       if (status) return status;
02086 
02087       if (!xdb)
02088         return Exception::make(IDB_DATABASE_GET_OBJECT_CLASS_ERROR,
02089                                "cannot get class of object %s: "
02090                                "database ID #%d must be manually "
02091                                "opened by the client",
02092                                _oid.getString(), obj_dbid);
02093       
02094       return xdb->getObjectClass(_oid, _class);
02095     }
02096 
02097     eyedbsm::Oid moid;
02098     int _state;
02099 
02100     RPCStatus rpc_status = objectCheck(dbh, _oid.getOid(), &_state, &moid);
02101 
02102     if (rpc_status != RPCSuccess)
02103       return StatusMake(rpc_status);
02104 
02105     if (!_state)
02106       return Exception::make(IDB_ERROR, "cannot find class of object %s",
02107                              _oid.toString());
02108 
02109     Oid cloid(moid);
02110 
02111     // added this kludge (?) the 6/10/99
02112     Class *clx;
02113     if (!cloid.isValid() && (clx = sch->getClass(_oid))) {
02114       if (!strcmp(clx->getName(), "class") || !strcmp(clx->getName(), "set") ||
02115           !strcmp(clx->getName(), "set<object*>") ||
02116           !strcmp(clx->getName(), "object")) // last test added 2/5/00
02117         _class = sch->getClass("class");
02118     }
02119     else
02120       _class = sch->getClass(cloid);
02121 
02122 #if 0
02123     if (!_class) {
02124       ClassConversion::Context *conv_ctx = 0;
02125       Status s = ClassConversion::getClass(this, cloid,
02126                                            (const Class *&)_class,
02127                                            conv_ctx);
02128       if (s) return s;
02129     }
02130 #endif
02131 
02132     if (!_class)
02133       return Exception::make(IDB_ERROR, "cannot find class of object %s: "
02134                              "invalid class %s",
02135                              _oid.toString(), cloid.toString());
02136     return Success;
02137   }
02138 
02139   //
02140   // protection part
02141   //
02142 
02143   Status Database::setObjectProtection(const Oid &obj_oid,
02144                                        const Oid &prot_oid)
02145   {
02146     RPCStatus rpc_status;
02147 
02148     rpc_status = objectProtectionSet(getDbHandle(), obj_oid.getOid(),
02149                                      prot_oid.getOid());
02150 
02151     return StatusMake(rpc_status);
02152   }
02153 
02154   Status Database::setObjectProtection(const Oid &obj_oid,
02155                                        Protection *prot)
02156   {
02157     return setObjectProtection(obj_oid, prot->getOid());
02158   }
02159 
02160   Status Database::getObjectProtection(const Oid &obj_oid,
02161                                        Oid &prot_oid)
02162   {
02163     RPCStatus rpc_status;
02164     eyedbsm::Oid _prot_oid;
02165 
02166     rpc_status = objectProtectionGet(getDbHandle(), obj_oid.getOid(),
02167                                      &_prot_oid);
02168 
02169     if (!rpc_status) {
02170       prot_oid.setOid(_prot_oid);
02171       return Success;
02172     }
02173 
02174     prot_oid.invalidate();
02175     return StatusMake(rpc_status);
02176   }
02177 
02178   Status Database::getObjectProtection(const Oid &obj_oid,
02179                                        Protection *&prot)
02180   {
02181     Oid prot_oid;
02182     Status status = getObjectProtection(obj_oid, prot_oid);
02183 
02184     if (status)
02185       return status;
02186 
02187     return loadObject(&prot_oid, (Object **)&prot);
02188   }
02189 
02190   void Database::updateSchema(const SchemaInfo &schinfo)
02191   {
02192     if (schinfo.class_cnt) {
02193       for (int i = 0; i < schinfo.class_cnt; i++) {
02194         Object *o;
02195         Class *cl = sch->getClass(schinfo.class_oid[i]);
02196         if (cl) {uncacheObject(cl); sch->suppressClass(cl);}
02197         loadObject(&schinfo.class_oid[i], &o);
02198       }
02199 
02200       sch->complete(True, True);
02201     }
02202   }
02203 
02204   const char *
02205   Database::getVersion(void) const
02206   {
02207     return convertVersionNumber(version);
02208   }
02209 
02210   void
02211   Database::setIncoherency()
02212   {
02213     if (curtrs)
02214       curtrs->setIncoherency();
02215   }
02216 
02217   const char *
02218   Database::getStringFlag(OpenFlag flags)
02219   {
02220     static std::string s;
02221 
02222     if (flags & _DBRead)
02223       s = "read";
02224     else if (flags & _DBSRead)
02225       s = "sread";
02226     else if (flags & _DBRW)
02227       s = "read/write";
02228     else
02229       s = "<unknown>";
02230 
02231     if (flags & _DBAdmin)
02232       s += "/admin";
02233     if (flags & _DBOpenLocal)
02234       s += "/local";
02235 
02236     return s.c_str();
02237   }
02238 
02239   //
02240   // Purge action management
02241   //
02242 
02243   struct PurgeAction {
02244     void (*purge_action)(void *);
02245     void *purge_data;
02246 
02247     PurgeAction(void (*_purge_action)(void *), void *_purge_data) :
02248       purge_action(_purge_action), purge_data(_purge_data) { }
02249   };
02250 
02251   void
02252   Database::addPurgeActionOnAbort(void (*purge_action)(void *),
02253                                   void *purge_data)
02254   {
02255     purge_action_list.insertObjectLast
02256       (new PurgeAction(purge_action, purge_data));
02257   }
02258 
02259   void
02260   Database::purgeOnAbort()
02261   {
02262     LinkedListCursor c(purge_action_list);
02263     PurgeAction *purge_action;
02264 
02265     while (c.getNext((void *&)purge_action))
02266       purge_action->purge_action(purge_action->purge_data);
02267   }
02268 
02269   void
02270   Database::purgeRelease()
02271   {
02272     LinkedListCursor c(purge_action_list);
02273     PurgeAction *purge_action;
02274     while (c.getNext((void *&)purge_action))
02275       delete purge_action;
02276     purge_action_list.empty();
02277   }
02278 
02279   void 
02280   Database::add(GenHashTable *_hashapp, consapp_t *_consapp)
02281   {
02282     hashapp[consapp_cnt] = _hashapp;
02283     consapp[consapp_cnt] = _consapp;
02284     consapp_cnt++;
02285     assert(consapp_cnt <= sizeof(hashapp)/sizeof(hashapp[0]));
02286   }
02287 
02288   Database::consapp_t
02289   Database::getConsApp(const Class *_class)
02290   {
02291     if (!consapp_cnt)
02292       return 0;
02293 
02294     const char *_name = _class->getName();
02295     const char *_aliasname = _class->getStrictAliasName();
02296 
02297     for (int i = 0; i < consapp_cnt; i++)
02298       {
02299         int ind = hashapp[i]->get(_name);
02300         if (ind >= 0) return consapp[i][ind];
02301 
02302         if (_aliasname)
02303           {
02304             ind = hashapp[i]->get(_aliasname);
02305             if (ind >= 0) return consapp[i][ind];
02306           }
02307       }
02308 
02309     return 0;
02310   }
02311 
02312   void
02313   Database::garbage_dat_dsp()
02314   {
02315     free(database_file);
02316     for (int i = 0; i < datafile_cnt; i++)
02317       delete datafiles[i];
02318     delete[] datafiles;
02319 
02320     for (int i = 0; i < dataspace_cnt; i++)
02321       delete dataspaces[i];
02322     delete[] dataspaces;
02323   }
02324 
02325   const Datafile **
02326   Database::get_datafiles(const eyedbsm::Dataspace *dsp)
02327   {
02328     const Datafile **dats = new const Datafile *[dsp->ndat];
02329     for (int i = 0; i < dsp->ndat; i++)
02330       dats[i] = datafiles[dsp->datid[i]];
02331     return dats;
02332   }
02333 
02334   void
02335   Database::make_dat_dsp(const DbInfoDescription &dbdesc)
02336   {
02337     garbage_dat_dsp();
02338 
02339     database_file = strdup(dbdesc.dbfile);
02340     const eyedbsm::DbInfoDescription *sed = &dbdesc.sedbdesc;
02341     datafile_cnt = sed->ndat;
02342     datafiles = new Datafile *[datafile_cnt];
02343 
02344     for (int i = 0; i < datafile_cnt; i++) {
02345       const eyedbsm::Datafile *dat = &sed->dat[i];
02346       datafiles[i] = new Datafile(this, (unsigned short)i,
02347                                   dat->dspid, dat->file, dat->name,
02348                                   dat->maxsize,
02349                                   (eyedbsm::MapType)dat->mtype, dat->sizeslot,
02350                                   (DatType)dat->dtype);
02351     }
02352 
02353     dataspace_cnt = sed->ndsp;
02354     dataspaces = new Dataspace *[dataspace_cnt];
02355 
02356     for (int i = 0; i < dataspace_cnt; i++) {
02357       const eyedbsm::Dataspace *dsp = &sed->dsp[i];
02358       const Datafile **dsp_datafiles = get_datafiles(dsp);
02359       dataspaces[i] = new Dataspace(this, (unsigned short)i,
02360                                     dsp->name, dsp_datafiles,
02361                                     dsp->ndat);
02362       for (int j = 0; j < dsp->ndat; j++)
02363         const_cast<Datafile *>(dsp_datafiles[j])->setDataspace(dataspaces[i]);
02364     }
02365   }
02366 
02367   Status
02368   Database::getDatDspPrologue(Bool fetch, const char *user,
02369                               const char *passwd)
02370   {
02371     if (datafiles && !fetch)
02372       return Success;
02373 
02374     DbInfoDescription dbdesc;
02375     Status s = getInfo(user, passwd, &dbdesc);
02376     if (s) return s;
02377     make_dat_dsp(dbdesc);
02378     return Success;
02379   }
02380 
02381   Status
02382   Database:: getDatabasefile(const char *&_database_file,
02383                              Bool fetch, const char *user,
02384                              const char *passwd)
02385   {
02386     Status s = getDatDspPrologue(fetch, user, passwd);
02387     if (s) return s;
02388 
02389     _database_file = database_file;
02390     return Success;
02391   }
02392 
02393   Status
02394   Database::getDatafiles(const Datafile **&_datafiles, unsigned int &cnt,
02395                          Bool fetch, const char *user, const char *passwd)
02396   {
02397     Status s = getDatDspPrologue(fetch, user, passwd);
02398     if (s) return s;
02399 
02400     _datafiles = const_cast<const Datafile **>(datafiles);
02401     cnt = datafile_cnt;
02402     return Success;
02403   }
02404 
02405   Status
02406   Database::getDatafile(unsigned short id, const Datafile *&datafile,
02407                         Bool fetch, const char *user, const char *passwd)
02408   {
02409     Status s = getDatDspPrologue(fetch, user, passwd);
02410     if (s) return s;
02411 
02412     if (id >= datafile_cnt)
02413       return Exception::make(IDB_ERROR, "datafile #%d not found in database "
02414                              "%s", id, name);
02415 
02416     datafile = datafiles[id];
02417     return Success;
02418   }
02419 
02420   Status
02421   Database::getDatafile(const char *name_or_file,
02422                         const Datafile *&datafile,
02423                         Bool fetch, const char *user, const char *passwd)
02424   {
02425     if (eyedblib::is_number(name_or_file))
02426       return getDatafile(atoi(name_or_file), datafile, fetch, user, passwd);
02427 
02428     Status s = getDatDspPrologue(fetch, user, passwd);
02429     if (s) return s;
02430 
02431     for (int i = 0; i < datafile_cnt; i++)
02432       if (!strcmp(name_or_file, datafiles[i]->getName()) ||
02433           !strcmp(name_or_file, datafiles[i]->getFile())) {
02434         datafile = datafiles[i];
02435         return Success;
02436       }
02437 
02438     return Exception::make(IDB_ERROR, "datafile %s not found in database "
02439                            "%s", name_or_file, name);
02440   }
02441 
02442   Status
02443   Database::getDataspaces(const Dataspace **&_dataspaces,
02444                           unsigned int &cnt,
02445                           Bool fetch, const char *user, const char *passwd)
02446   {
02447     Status s = getDatDspPrologue(fetch, user, passwd);
02448     if (s) return s;
02449 
02450     _dataspaces = const_cast<const Dataspace **>(dataspaces);
02451     cnt = dataspace_cnt;
02452     return Success;
02453   }
02454 
02455   Status
02456   Database::getDataspace(unsigned short id, const Dataspace *&dataspace,
02457                          Bool fetch, const char *user, const char *passwd)
02458   {
02459     Status s = getDatDspPrologue(fetch, user, passwd);
02460     if (s) return s;
02461 
02462     if ((short)id == Dataspace::DefaultDspid) {
02463       dataspace = 0;   //OR: return getDefaultDataspace(dataspace);
02464       return Success;
02465     }
02466 
02467     if (id >= dataspace_cnt)
02468       return Exception::make(IDB_ERROR, "dataspace #%d not found in database "
02469                              "%s", id, name);
02470 
02471     dataspace = dataspaces[id];
02472     return Success;
02473   }
02474 
02475   Status
02476   Database::getDataspace(const char *dspname,
02477                          const Dataspace *&dataspace,
02478                          Bool fetch, const char *user, const char *passwd)
02479   {
02480     if (eyedblib::is_number(dspname))
02481       return getDataspace(atoi(dspname), dataspace, fetch, user, passwd);
02482 
02483     Status s = getDatDspPrologue(fetch, user, passwd);
02484     if (s) return s;
02485 
02486     for (int i = 0; i < dataspace_cnt; i++)
02487       if (!strcmp(dspname, dataspaces[i]->getName())) {
02488         dataspace = dataspaces[i];
02489         return Success;
02490       }
02491 
02492     return Exception::make(IDB_ERROR, "dataspace %s not found in database "
02493                            "%s", dspname, name);
02494   }
02495 
02496 
02497   Status
02498   Database::getDefaultDataspace(const Dataspace *&dataspace)
02499   {
02500     int dspid;
02501     RPCStatus rpc_status = eyedb::getDefaultDataspace(dbh, &dspid);
02502     if (rpc_status)
02503       return StatusMake(rpc_status);
02504 
02505     return getDataspace(dspid, dataspace);
02506   }
02507 
02508   Status
02509   Database::setDefaultDataspace(const Dataspace *dataspace)
02510   {
02511     RPCStatus rpc_status = eyedb::setDefaultDataspace(dbh, dataspace->getId());
02512     if (rpc_status)
02513       return StatusMake(rpc_status);
02514 
02515     return Success;
02516   }
02517 
02518   eyedbsm::Oid *
02519   oidArrayToOids(const OidArray &oid_arr, unsigned int &cnt)
02520   {
02521     cnt = oid_arr.getCount();
02522     if (!cnt) return 0;
02523 
02524     eyedbsm::Oid *oids = new eyedbsm::Oid[cnt];
02525     for (int i = 0; i < cnt; i++)
02526       oids[i] = *oid_arr[i].getOid();
02527 
02528     return oids;
02529   }
02530 
02531   eyedbsm::Oid *
02532   objArrayToOids(const ObjectArray &obj_arr, unsigned int &cnt)
02533   {
02534     cnt = obj_arr.getCount();
02535     if (!cnt) return 0;
02536 
02537     eyedbsm::Oid *oids = new eyedbsm::Oid[cnt];
02538     for (int i = 0; i < cnt; i++) {
02539       oids[i] = *obj_arr[i]->getOid().getOid();
02540     }
02541 
02542     return oids;
02543   }
02544 
02545   Status
02546   Database::moveObjects(const OidArray &oid_arr, const Dataspace *dataspace)
02547   {
02548     unsigned int cnt;
02549     eyedbsm::Oid *oids = oidArrayToOids(oid_arr, cnt);
02550     if (!cnt) return Success;
02551     RPCStatus rpc_status = eyedb::moveObjects(dbh, oids, cnt, dataspace->getId());
02552     delete [] oids;
02553     return StatusMake(rpc_status);
02554   }
02555 
02556   Status
02557   Database::moveObjects(const ObjectArray &obj_arr, const Dataspace *dataspace)
02558   {
02559     unsigned int cnt;
02560     eyedbsm::Oid *oids = objArrayToOids(obj_arr, cnt);
02561     if (!cnt) return Success;
02562     RPCStatus rpc_status = eyedb::moveObjects(dbh, oids, cnt, dataspace->getId());
02563     delete [] oids;
02564     return StatusMake(rpc_status);
02565   }
02566 
02567   Status
02568   Database::getObjectLocations(const OidArray &oid_arr,
02569                                ObjectLocationArray &locarr)
02570   {
02571     unsigned int cnt;
02572     eyedbsm::Oid *oids = oidArrayToOids(oid_arr, cnt);
02573     if (!cnt)
02574       return Success;
02575 
02576     RPCStatus rpc_status = getObjectsLocations(dbh, oids, cnt,
02577                                                (Data *)&locarr);
02578     delete [] oids;
02579     return StatusMake(rpc_status);
02580   }
02581 
02582   Status
02583   Database::getObjectLocations(const ObjectArray &obj_arr,
02584                                ObjectLocationArray &locarr)
02585   {
02586     return Success;
02587   }
02588 
02589   Status
02590   Database::createDatafile(const char *filedir, const char *filename,
02591                            const char *name, unsigned int maxsize,
02592                            unsigned int slotsize, DatType dtype)
02593   {
02594     std::string s;
02595     if (filedir) {
02596       s = std::string(filedir);
02597       if (s.length() > 0 && s[s.length()-1] != '/')
02598         s += "/";
02599       s += filename;
02600     }
02601     else 
02602       s = filename;
02603 
02604     RPCStatus rpc_status =
02605       eyedb::createDatafile(dbh, s.c_str(), name, maxsize, slotsize, dtype);
02606 
02607     return StatusMake(rpc_status);
02608   }
02609 
02610   Status
02611   Database::createDataspace(const char *dspname,
02612                             const Datafile **datafiles,
02613                             unsigned int datafile_cnt)
02614   {
02615     char **datids = Dataspace::makeDatid(datafiles, datafile_cnt);
02616     RPCStatus rpc_status = eyedb::createDataspace(dbh, dspname,
02617                                                   datids, datafile_cnt);
02618     Dataspace::freeDatid(datids, datafile_cnt);
02619     return StatusMake(rpc_status);
02620   }
02621 
02622   Bool
02623   Database::writeBackConvertedObjects() const
02624   {
02625     return IDBBOOL(!(open_flag & _DBSRead));
02626   }
02627 
02628   void Database::addMarkCreated(const Oid &oid)
02629   {
02630     mark_created[oid] = true;
02631   }
02632 
02633   bool Database::isMarkCreated(const Oid &oid) const
02634   {
02635     return mark_created.find(oid) != mark_created.end();
02636   }
02637 
02638   void Database::markCreatedEmpty()
02639   {
02640     mark_created.erase(mark_created.begin(), mark_created.end());
02641   }
02642 
02643 }

Generated on Mon Dec 22 18:15:53 2008 for eyedb by  doxygen 1.5.3