00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00046
00047 namespace eyedb {
00048
00049
00050
00051 LinkedList *Database::dbopen_list;
00052
00053
00054
00055
00056 Bool Database::def_commit_on_close = False;
00057
00058 Bool edb_is_back_end = False;
00059
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
00100
00101
00102
00103
00104
00105
00106 void Database::init(const char *_dbmdb_str)
00107 {
00108
00109
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 ¶ms)
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
00292
00293
00294
00295
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
00322
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
00415
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
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
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
00658 void Database::init(void)
00659 {
00660 dbopen_list = new LinkedList;
00661 }
00662
00663 void Database::_release(void)
00664 {
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
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++;
00727 ObjectPeer::incrRefCount(pdb);
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
00769 OpenFlag oflag = flag;
00770 flag = (OpenFlag)(flag & ~_DBOpenLocal);
00771
00772 while (c.getNext((void *&)db)) {
00773
00774 if (db->getConnection()->getConnHandle() == conn->getConnHandle() &&
00775 (*cmp)(db, user_data) && flag == (db->open_flag & ~_DBOpenLocal)) {
00776
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++;
00782 ObjectPeer::incrRefCount(db);
00783 *pdb = db;
00784 return Success;
00785 }
00786 }
00787 }
00788
00789 db = make_db(user_data, dbmdb_str);
00790
00791
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
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
00848 RPCStatus rpc_status;
00849
00850 conn = ch;
00851 char *rname = 0;
00852 int rdbid = 0;
00853 char *pname = (char *)(name ? name : "");
00854
00855
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
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;
00876 dbh->u.dbh = ldbh;
00877 dbh->flags = flag & ~_DBOpenLocal;
00878 dbh->tr_cnt = 0;
00879 dbh->db = (void *)this;
00880
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
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
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
00923
00924
00925 }
00926
00927
00928 transactionCommit();
00929
00930
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
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;
00968 dbh->u.dbh = ldbh;
00969 dbh->flags = flag & ~_DBOpenLocal;
00970 dbh->sch_oid = *sch_oid->getOid();
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
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
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
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 ¶ms)
01151 {
01152 if (!trs_cnt) {
01153 Status status = transactionBegin_realize(¶ms);
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
01236 return transactionCommit_realize();
01237 }
01238
01239 Status Database::transactionCommit_realize()
01240 {
01241
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
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
01284 return transactionAbort_realize();
01285 }
01286
01287 Status Database::transactionAbort_realize()
01288 {
01289
01290
01291
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;
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;
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
01531 #ifdef CACHE_OBJECTS
01532 if (reload)
01533 uncacheObject(*poid);
01534 else if (curtrs && (*o = (Object *)curtrs->getObject(*poid))) {
01535 ObjectPeer::incrRefCount(*o);
01536
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
01771
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
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
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
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
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"))
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
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
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;
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 }