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