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
00026
00027 using namespace std;
00028
00029 #define NEW_COLLBE_MAN
00030
00031 #define _IDB_KERN_
00032
00033 #include <eyedbconfig.h>
00034
00035
00036
00037
00038 #include <stdlib.h>
00039 #include <limits.h>
00040 #include <assert.h>
00041 #include <pthread.h>
00042 #ifdef HAVE_SYS_STAT_H
00043 #include <sys/stat.h>
00044 #endif
00045 #ifdef HAVE_CRYPT_H
00046 #include <crypt.h>
00047 #endif
00048
00049 #include "eyedb_p.h"
00050 #include "eyedb/DBM_Database.h"
00051 #include <eyedbsm/eyedbsm.h>
00052 #include <eyedbsm/eyedbsm_p.h>
00053 #include "serv_lib.h"
00054 #include "kernel.h"
00055 #include "kernel_p.h"
00056 #include "IteratorBE.h"
00057 #include "CollectionBE.h"
00058 #include "OQLBE.h"
00059 #include "BEQueue.h"
00060 #include "InvOidContext.h"
00061 #include <eyedblib/m_malloc.h>
00062 #include <unistd.h>
00063 #include <fcntl.h>
00064 #include <pwd.h>
00065 #include "Attribute_p.h"
00066 #include "version_p.h"
00067
00068 #include <eyedblib/rpc_lib.h>
00069
00070 #include "eyedb/SessionLog.h"
00071 #include <new>
00072
00073 #define COLLBE_BTREE
00074
00075 #define RCHECK(S) \
00076 if (S) \
00077 { \
00078 IDB_free(db, collbe); \
00079 return rpcStatusMake_se(S); \
00080 }
00081
00082 namespace eyedbsm {
00083 void mutexes_release();
00084 extern Boolean backend;
00085 Status dbClose(const eyedbsm::DbHandle *);
00086 }
00087
00088 namespace eyedb {
00089
00090 struct ConnContext {
00091 SessionLog *sesslog;
00092 ClientSessionLog *clinfo;
00093
00094 std::string challenge;
00095 int uid;
00096 time_t ctime;
00097 rpc_ConnInfo *ci;
00098 };
00099
00100 static ConnContext conn_ctx;
00101
00102 static const char *edb_passwdfile;
00103
00104 #ifdef PASSWD_FILE
00105 static void
00106 get_dbm_passwd(const char *passwdfile);
00107 #endif
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #define LOAD_RM_BUG
00121
00122 #ifdef PASSWD_FILE
00123 static char dbm_passwd[14];
00124 #endif
00125
00126 static const char salt[] = "r8";
00127
00128 static LinkedList st_inv_oid_ctx;
00129 LinkedList *inv_oid_ctx;
00130
00131 static eyedbsm::Oid *
00132 decode_oids(Data data, unsigned int *oid_cnt);
00133
00134 static const char **
00135 decode_datids(Data data, unsigned int *oid_cnt);
00136
00137 static Data
00138 code_locarr(const eyedbsm::ObjectLocation *locarr, const eyedbsm::Oid *oids,
00139 unsigned int cnt, int *size);
00140
00141 static Data
00142 code_datinfo(const eyedbsm::DatafileInfo *info, int *size);
00143
00144 static void
00145 code_value(rpc_ServerData *, Value *);
00146
00147 static void
00148 make_locarr(const eyedbsm::ObjectLocation *se_locarr, const eyedbsm::Oid *oids,
00149 unsigned int oid_cnt, void *locarr);
00150 static void
00151 make_datinfo(const eyedbsm::DatafileInfo *se_datinfo, Data *info);
00152
00153 static void
00154 code_atom_array(rpc_ServerData *, void *, int, int);
00155
00156 static Data
00157 code_index_stats(IndexImpl::Type, const void *, int *);
00158
00159 static void
00160 make_index_stats(const eyedbsm::HIdx::Stats &, Data *);
00161
00162 static void
00163 make_index_stats(const eyedbsm::BIdx::Stats &, Data *);
00164
00165 static Data
00166 code_index_impl(const eyedbsm::HIdx::_Idx &, int *);
00167
00168 static Data
00169 code_index_impl(const eyedbsm::BIdx &, int *);
00170
00171 static void
00172 make_index_impl(const eyedbsm::HIdx::_Idx &, Data *);
00173
00174 static void
00175 make_index_impl(const eyedbsm::BIdx &, Data *);
00176
00177 static RPCStatus
00178 IDB_schemaClassHeadGet(DbHandle *),
00179 IDB_schemaClassCreate(DbHandle *),
00180 IDB_instanceCreate(DbHandle *, short, Data, ObjectHeader *,
00181 eyedbsm::Oid *, void *, Bool),
00182 IDB_instanceRead(DbHandle *dbh, Data idr, Data *pidr,
00183 ObjectHeader *hdr,
00184 LockMode lockmode, const eyedbsm::Oid *oid, void *xdata,
00185 int minsize),
00186 IDB_instanceWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00187 const eyedbsm::Oid *oid, void *xdata),
00188 IDB_instanceDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00189 const eyedbsm::Oid *oid, Bool really = False),
00190 IDB_agregatCreate(DbHandle *dbh, short dspid, Data idr,
00191 ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata),
00192 IDB_agregatWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00193 const eyedbsm::Oid *oid, void *xdata),
00194 IDB_agregatDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00195 const eyedbsm::Oid *oid, Bool really = False),
00196 IDB_classCreate(DbHandle *, short dspid, Data, ObjectHeader *,
00197 eyedbsm::Oid *, void *),
00198 IDB_classWrite(DbHandle *, Data, ObjectHeader *,
00199 const eyedbsm::Oid *, void *),
00200 IDB_classDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00201 const eyedbsm::Oid *oid, unsigned int flags),
00202 IDB_collectionCreate(DbHandle *, short dspid, Data,
00203 ObjectHeader *, eyedbsm::Oid *, void *),
00204 IDB_collectionWrite(DbHandle *, Data, ObjectHeader *,
00205 const eyedbsm::Oid *, void *),
00206 IDB_collectionRead(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00207 LockMode lockmode, const eyedbsm::Oid *oid, void *xdata),
00208 IDB_collectionDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00209 const eyedbsm::Oid *oid),
00210 IDB_protectionCreate(DbHandle *, short dspid, Data,
00211 ObjectHeader *, eyedbsm::Oid *, void *, Bool),
00212 IDB_protectionWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00213 const eyedbsm::Oid *oid, void *xdata),
00214 IDB_protectionDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr,
00215 const eyedbsm::Oid *oid);
00216
00217
00218
00219
00220
00221
00222
00223 static LinkedList *db_list;
00224
00225 void IDB_releaseConn();
00226
00227 void (*garbage_handler)(void);
00228 void (*settimeout)(int);
00229
00230 static void
00231 quit_handler(void *quit_data, int fromcore)
00232 {
00233 Exception::setMode(Exception::StatusMode);
00234
00235 eyedbsm::mutexes_release();
00236 IDB_releaseConn();
00237
00238 LinkedList *list = (LinkedList *)quit_data;
00239 LinkedListCursor c(list);
00240
00241 if (!fromcore) {
00242 Database *db;
00243 void (*handler)(Status, void *) = Exception::getHandler();
00244
00245 Exception::setHandler(0);
00246
00247 while (c.getNext((void *&)db)) {
00248 for (;;) {
00249 Status status = db->transactionAbort();
00250 if (status)
00251 break;
00252 }
00253 }
00254
00255 Exception::setHandler(handler);
00256 }
00257
00258 if (garbage_handler) {
00259 garbage_handler();
00260 eyedb::release();
00261 }
00262 }
00263
00264 #define TRIGGER_MANAGE(DB, TTYPE, HDR, IDR, OID, MCL) \
00265 { \
00266 Status status = IDB_triggerManage(DB, TTYPE, HDR, IDR, OID, MCL); \
00267 \
00268 if (status) \
00269 return rpcStatusMake(status); \
00270 }
00271
00272 static Status
00273 IDB_triggerManage(Database *db, int w, const ObjectHeader *hdr,
00274 Data idr, const eyedbsm::Oid *oid, const Class *cls)
00275 {
00276 if (!db || !cls ||
00277 cls->asCollectionClass() || cls->isSystem())
00278 return Success;
00279
00280 const LinkedList *list;
00281
00282 try {
00283 list = cls->getCompList((Class::CompIdx)w);
00284 }
00285 catch (Exception &e) {
00286 return Exception::make(e.getStatus(), e.getDesc());
00287 }
00288
00289 if (list)
00290 {
00291 Oid obj_oid(oid);
00292 Object *o = 0;
00293 Status status;
00294 Trigger *trigger;
00295
00296
00297
00298
00299
00300
00301 if (idr && obj_oid.isValid())
00302 {
00303 LinkedListCursor c(list);
00304 while (list->getNextObject(&c, (void *&)trigger))
00305 if (!trigger->getLight())
00306 {
00307 status = db->makeObject(&obj_oid, hdr, idr, &o, True);
00308 if (status)
00309 return status;
00310
00311 break;
00312 }
00313 }
00314
00315 LinkedListCursor c(list);
00316 while (list->getNextObject(&c, (void *&)trigger))
00317 {
00318 status = trigger->apply(obj_oid, o);
00319 if (o && (trigger->getType() & 1) && idr != o->getIDR())
00320 memcpy(idr, o->getIDR(), hdr->size);
00321
00322 if (status)
00323 {
00324 if (o) o->release();
00325 return status;
00326 }
00327 }
00328 if (o) o->release();
00329 }
00330
00331 return Success;
00332 }
00333
00334 static Status IDB_makeDatabase(ConnHandle *, const char *,
00335 const char *, int, int, DbHandle *,
00336 rpcDB_LocalDBContext *, const eyedbsm::Oid *,
00337 unsigned int version, Database *&);
00338
00339 #define IS_DATA(X) ((X) && (X)->fd >= 0)
00340
00341 static void lock_data(Data *pidr, void *xdata)
00342 {
00343 rpc_ServerData *data = (rpc_ServerData *)xdata;
00344
00345 if (IS_DATA(data))
00346 {
00347 Data temp = (Data)malloc(data->size);
00348
00349 if (temp)
00350 {
00351 rpc_socketRead(data->fd, temp, data->size);
00352 *pidr = temp;
00353 }
00354 }
00355 }
00356
00357 static void unlock_data(Data idr, void *xdata)
00358 {
00359 rpc_ServerData *data = (rpc_ServerData *)xdata;
00360
00361 if (IS_DATA(data))
00362 free(idr);
00363 }
00364
00365 RPCStatus
00366 IDB_checkAuth(const char *file)
00367 {
00368
00369 const char *p = strrchr(file, '/');
00370 if (p)
00371 p++;
00372 else
00373 p = file;
00374
00375 if (strcmp(p, strrchr(conn_ctx.challenge.c_str(), '.') + 1))
00376 return rpcStatusMake
00377 (Exception::make(IDB_ERROR, "invalid file name: "
00378 "%s", file));
00379
00380 int fd = open(file, O_RDONLY);
00381 if (fd < 0)
00382 return rpcStatusMake
00383 (Exception::make(IDB_ERROR, "cannot open authentification file: "
00384 "%s", file));
00385
00386 char buf[1024];
00387 int n = read(fd, buf, sizeof buf);
00388 if (n <= 0) {
00389 close(fd);
00390 return rpcStatusMake
00391 (Exception::make(IDB_ERROR, "cannot read authentification file: "
00392 "%s", file));
00393 }
00394
00395 buf[n] = 0;
00396
00397
00398 if (strcmp(buf, conn_ctx.challenge.c_str())) {
00399 close(fd);
00400 return rpcStatusMake
00401 (Exception::make(IDB_ERROR, "invalid challenge in authentification file: "
00402 "%s", file));
00403 }
00404
00405 struct stat rstat;
00406 int r = fstat(fd, &rstat);
00407 close(fd);
00408
00409 if (r)
00410 return rpcStatusMake
00411 (Exception::make(IDB_ERROR, "cannot stat authentification file: "
00412 "%s", file));
00413
00414
00415 if (conn_ctx.uid != rstat.st_uid)
00416 return rpcStatusMake
00417 (Exception::make(IDB_ERROR, "invalid uid authentification file: "
00418 "%s", file));
00419
00420
00421 if (rstat.st_ctime < conn_ctx.ctime-1)
00422 return rpcStatusMake
00423 (Exception::make(IDB_ERROR, "invalid creation time for "
00424 "authentification file: "
00425 "%s (%u >= %u)", file, rstat.st_ctime,
00426 conn_ctx.ctime));
00427
00428
00429 if (0664 != (rstat.st_mode & 0777))
00430 return rpcStatusMake
00431 (Exception::make(IDB_ERROR, "invalid mode 0%o for authentification file: "
00432 "%s", rstat.st_mode & 0777, file));
00433
00434 conn_ctx.ci->auth.uid = conn_ctx.uid;
00435 return RPCSuccess;
00436 }
00437
00438 static int
00439 get_rand()
00440 {
00441
00442 #ifdef SUPPORT_DEV_RANDOM
00443 int fd = open("/dev/random", O_RDONLY);
00444 if (fd >= 0) {
00445 unsigned int i = 0;
00446 time_t t0;
00447 time(&t0);
00448 printf("before read\n");
00449 int r = read(fd, &i, sizeof(int));
00450 printf("r = %d %d %d\n", r, i, time(0)-t0);
00451 close(fd);
00452 return i;
00453 }
00454 return 0;
00455 #else
00456 static int n = 1;
00457 struct timeval tv;
00458 gettimeofday(&tv, 0);
00459 srand(tv.tv_usec + (tv.tv_sec % n));
00460 n++;
00461 return rand();
00462 #endif
00463 }
00464
00465 static std::string
00466 gen_random()
00467 {
00468 struct timeval tv;
00469 int r0, r1;
00470 char buf[512];
00471
00472 r0 = get_rand();
00473
00474
00475 bool found = false;
00476 for (int n = 0 ; n < 100; n++) {
00477 r1 = get_rand();
00478 sprintf(buf, "/tmp/%d", r1);
00479 int fd = open(buf, O_RDONLY);
00480 if (fd < 0) {
00481 found = true;
00482 break;
00483 }
00484 close(fd);
00485 }
00486
00487 if (!found)
00488 return "";
00489
00490 gettimeofday(&tv, 0);
00491 sprintf(buf, "%d.%06d.%d.%d", tv.tv_sec, tv.tv_usec, r0, r1);
00492
00493 return buf;
00494 }
00495
00496 RPCStatus
00497 IDB_setConnInfo(const char *_hostname, int uid, const char *username,
00498 const char *progname, int pid, int *sv_pid,
00499 int *sv_uid, int cli_version, char **challenge)
00500 {
00501 char *host = strdup(_hostname);
00502 char *p = strchr(host, ':');
00503 *challenge = "";
00504 if (!p) {
00505 free(host);
00506 return rpcStatusMake
00507 (Exception::make(IDB_ERROR, "invalid hostname, got '%s' "
00508 "expected host:port",
00509 _hostname));
00510 }
00511
00512 *p = 0;
00513 char *port = p + 1;
00514
00515 IDB_LOG(IDB_LOG_CONN,
00516 ("connected host='%s:%s', username='%s', progname='%s', pid=%d\n",
00517 host, port, username, progname, pid));
00518
00519 *sv_pid = rpc_getpid();
00520 *sv_uid = getuid();
00521
00522 if (cli_version != eyedb::getVersionNumber())
00523 return rpcStatusMake
00524 (Exception::make(IDB_ERROR, "incompatible versions: "
00525 "client version is %s, server version is %s",
00526 eyedb::convertVersionNumber(cli_version),
00527 eyedb::getVersion()));
00528
00529 struct passwd *pwd = 0;
00530
00531
00532 if (conn_ctx.ci && conn_ctx.ci->is_localhost &&
00533 (pwd = getpwnam(username))) {
00534 conn_ctx.challenge = gen_random();
00535 conn_ctx.ctime = time(0);
00536 conn_ctx.uid = pwd->pw_uid;
00537 }
00538 else {
00539 conn_ctx.challenge = "";
00540 conn_ctx.ctime = 0;
00541 conn_ctx.uid = -1;
00542 }
00543
00544 *challenge = (char *)conn_ctx.challenge.c_str();
00545
00546 return rpcStatusMake(conn_ctx.sesslog->add(host, port, username,
00547 progname, pid, conn_ctx.clinfo));
00548 }
00549
00550 void
00551 IDB_releaseConn()
00552 {
00553
00554
00555
00556
00557
00558
00559
00560 SessionLog::release();
00561
00562 if (!conn_ctx.clinfo)
00563 return;
00564
00565 conn_ctx.sesslog->suppress(conn_ctx.clinfo);
00566 conn_ctx.clinfo = 0;
00567 }
00568
00569 static RPCStatus
00570 IDB_checkAuthDbm(const char *&dbmdb)
00571 {
00572 #if 1
00573 std::string dbmdb_s;
00574 if (!strcmp(dbmdb, DBM_Database::defaultDBMDB)) {
00575 dbmdb = strdup(Database::getDefaultServerDBMDB());
00576 }
00577 const std::vector<string> &granted_dbm = Database::getGrantedDBMDB();
00578 int size = granted_dbm.size();
00579 for (int n = 0; n < size; n++) {
00580 if (!strcmp(granted_dbm[n].c_str(), dbmdb))
00581 return RPCSuccess;
00582 }
00583 #else
00584 if (!strcmp(dbmdb, Database::getDefaultDBMDB()))
00585 return RPCSuccess;
00586 #endif
00587
00588
00589
00590 return rpcStatusMake(IDB_ERROR,
00591 "security violation: cannot use "
00592 "'%s' EYEDBDBM database.", dbmdb);
00593 }
00594
00595 static RPCStatus
00596 IDB_dbmOpen(ConnHandle *ch, const char *dbmdb,
00597 Bool rw_mode, DBM_Database **dbm)
00598 {
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 if (*dbm = DBM_Database::getDBM_Database(dbmdb))
00614 {
00615 if (!rw_mode || ((*dbm)->getOpenFlag() & _DBRW))
00616 return RPCSuccess;
00617
00618
00619
00620 Status s = (*dbm)->close();
00621 if (s) return rpcStatusMake(s);
00622 (void)DBM_Database::setDBM_Database(dbmdb, (Database *)0);
00623 }
00624
00625 int rdbid;
00626 char *rname;
00627 RPCStatus rpc_status;
00628 DbHandle *dbh;
00629 int pid;
00630
00631 if (rpc_status = IDB_checkAuthDbm(dbmdb))
00632 return rpc_status;
00633
00634 rpc_status = IDB_dbOpen(ch, dbmdb, (char *)0, (char *)0,
00635 DBM_Database::getDbName(),
00636 DBM_Database::getDbid(),
00637 ((rw_mode ? _DBRW : (_DBSRead)) |
00638 _DBOpenLocal),
00639 0, 0,
00640 &pid, NULL, 0, &rname,
00641 &rdbid, 0, &dbh);
00642
00643 if (rpc_status == RPCSuccess)
00644 *dbm = DBM_Database::setDBM_Database(dbmdb, (Database *)dbh->db);
00645
00646 return rpc_status;
00647 }
00648
00649 static RPCStatus get_file_mask_group(mode_t &file_mask, const char *&file_group)
00650 {
00651 file_mask = 0;
00652 const char *file_mask_str = ServerConfig::getSValue("default_file_mask");
00653 if (file_mask_str && strcmp(file_mask_str, "0")) {
00654 unsigned int fmask = 0;
00655 sscanf(file_mask_str, "%o", &fmask);
00656 if (!fmask) {
00657 return rpcStatusMake(IDB_ERROR, "invalid file mode: %s", file_mask_str);
00658 }
00659 file_mask = fmask;
00660 }
00661
00662 file_group = ServerConfig::getSValue("default_file_group");
00663 return RPCSuccess;
00664 }
00665
00666 RPCStatus
00667 IDB_dbCreate_realize(ConnHandle *ch, DBM_Database *dbm, int dbid,
00668 const char *dbmdb, const char *userauth,
00669 const char *passwdauth, const char *dbname,
00670 const char *dbfile, Bool makeTemp,
00671 const eyedbsm::DbCreateDescription *sedbdesc)
00672 {
00673 eyedbsm::Status se_status;
00674
00675 ((eyedbsm::DbCreateDescription *)sedbdesc)->dbid = dbid;
00676
00677 std::string dbs;
00678 if (*dbfile != '/') {
00679 dbs = string(ServerConfig::getSValue("databasedir")) + "/" + dbfile;
00680 dbfile = dbs.c_str();
00681 }
00682
00683 mode_t file_mask;
00684 const char *file_group;
00685 RPCStatus rpc_status = get_file_mask_group(file_mask, file_group);
00686 if (rpc_status)
00687 return rpc_status;
00688
00689 se_status = eyedbsm::dbCreate(dbfile, eyedb::getVersionNumber(),
00690 sedbdesc, file_mask, file_group);
00691
00692 if (!se_status) {
00693 RPCStatus rpc_status;
00694 int pid;
00695 DbHandle *dbh = 0;
00696 Status status;
00697
00698 if (dbm && makeTemp) {
00699 status = dbm->updateEntry(dbid,
00700 DBM_Database::makeTempName(dbid).c_str(),
00701 dbname, dbfile);
00702
00703 if (status)
00704 return rpcStatusMake(status);
00705 }
00706
00707 if (strcmp(dbname, DBM_Database::getDbName()) &&
00708 (rpc_status = IDB_userDBAccessSet(ch, dbmdb, (char *)0, (char *)0,
00709 dbname, userauth,
00710 AdminDBAccessMode)) !=
00711 RPCSuccess) {
00712
00713 return rpc_status;
00714 }
00715
00716 int rdbid;
00717 char *rname;
00718 int xflags = _DBRW|_DBOpenLocal;
00719 if ((rpc_status = IDB_dbOpen(ch, dbmdb, userauth, passwdauth, dbname, dbid,
00720 xflags, 0, 0, &pid, NULL,
00721 0, &rname, &rdbid, 0, &dbh)) !=
00722 RPCSuccess && rpc_status->err == IDB_INVALID_SCHEMA)
00723 {
00724 if ((rpc_status = IDB_transactionBegin(dbh, 0, True))
00725 == RPCSuccess)
00726 {
00727 rpc_status = IDB_schemaClassCreate(dbh);
00728 IDB_transactionCommit(dbh, True);
00729 }
00730
00731 if (dbm && !rpc_status)
00732 {
00733 Oid schoid(dbh->sch.oid);
00734 dbm->setSchema(dbname, schoid);
00735 }
00736
00737 }
00738
00739 if (dbh && !IDB_dbClose(dbh) && conn_ctx.clinfo)
00740 conn_ctx.clinfo->suppressDatabase(dbname, userauth, xflags);
00741
00742 return rpc_status;
00743 }
00744 else {
00745 if (dbm)
00746 dbm->removeEntry(makeTemp ? DBM_Database::makeTempName(dbid).c_str() : std::string(dbname).c_str());
00747 return rpcStatusMake_se(se_status);
00748 }
00749 }
00750
00751 RPCStatus
00752 IDB_dbmCreate(ConnHandle *ch, const char *dbmdb,
00753 const char *passwdauth, const DbCreateDescription *dbdesc)
00754 {
00755 if (!access(dbmdb, F_OK))
00756 return rpcStatusMake(IDB_ERROR, "DBM_Database database '%s' already exists", dbmdb);
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 RPCStatus rpc_status;
00778 #ifdef PASSWD_FILE
00779 if (strcmp(crypt(passwdauth, salt), dbm_passwd))
00780 return rpcStatusMake(Exception::make(IDB_AUTHENTICATION_FAILED,
00781 "not a valid password to create a DBM database"));
00782 #else
00783 rpc_status = IDB_checkAuthDbm(dbmdb);
00784 if (rpc_status)
00785 return rpc_status;
00786 #endif
00787
00788 rpc_status = IDB_dbCreate_realize(ch, 0, DBM_Database::getDbid(), dbmdb,
00789 (char *)0, (char *)0, DBM_Database::getDbName(), dbmdb, False, &dbdesc->sedbdesc);
00790
00791
00792
00793
00794
00795
00796
00797 return rpc_status;
00798 }
00799
00800 RPCStatus
00801 IDB_dbmUpdate(ConnHandle *ch, const char *dbmdb,
00802 const char *username, const char *passwd)
00803 {
00804 DBM_Database *dbm;
00805 RPCStatus rpc_status;
00806 Status status;
00807
00808 rpc_status = IDB_dbmOpen(ch, dbmdb, True, &dbm);
00809
00810 if (rpc_status != RPCSuccess)
00811 return rpc_status;
00812
00813 status = dbm->createEntry(DBM_Database::getDbid(),
00814 DBM_Database::getDbName(), dbmdb);
00815
00816 if (status)
00817 return rpcStatusMake(status);
00818
00819 int user_type;
00820 if (!strcmp(passwd, strict_unix_user)) {
00821 passwd = "";
00822 user_type = StrictUnixUser;
00823 } else
00824 user_type = EyeDBUser;
00825
00826 rpc_status = IDB_userAdd(ch, dbmdb, (char *)0, (char *)0, username, passwd,
00827 user_type);
00828
00829 if (rpc_status != RPCSuccess)
00830 return rpc_status;
00831
00832 rpc_status = IDB_userSysAccessSet(ch, dbmdb, (char *)0, (char *)0,
00833 username, SuperUserSysAccessMode);
00834 if (rpc_status != RPCSuccess)
00835 return rpc_status;
00836
00837 return RPCSuccess;
00838 }
00839
00840
00841
00842 static RPCStatus
00843 IDB_checkSysAuth(ConnHandle *ch, const char *dbmdb,
00844 const char *&userauth, const char *&passwdauth,
00845 SysAccessMode sysmode, Bool rw_mode,
00846 DBM_Database **pdbm, const char *msg, Bool * = 0);
00847
00848 RPCStatus
00849 IDB_dbCreate(ConnHandle *ch, const char *dbmdb,
00850 const char *userauth, const char *passwdauth,
00851 const char *dbname, const DbCreateDescription *dbdesc)
00852 {
00853 DBM_Database *dbm;
00854 RPCStatus rpc_status;
00855
00856 std::string msg = std::string("creating database '") + dbname + "'";
00857 if ((rpc_status = IDB_checkSysAuth(ch, dbmdb, userauth, passwdauth,
00858 DBCreateSysAccessMode, True, &dbm,
00859 msg.c_str())) !=
00860 RPCSuccess)
00861 return rpc_status;
00862
00863
00864 const char *xdbfile;
00865 Status s = dbm->getDbFile(&dbname, 0, xdbfile);
00866 if (s) return rpcStatusMake(s);
00867
00868 if (xdbfile)
00869 return rpcStatusMake(IDB_ERROR, "database '%s' already exists", dbname);
00870
00871 int newid;
00872 Bool makeTemp;
00873 if (dbdesc->sedbdesc.dbid)
00874 {
00875 newid = dbdesc->sedbdesc.dbid;
00876 makeTemp = False;
00877 Status status = dbm->createEntry(newid, dbname, dbdesc->dbfile);
00878 if (status)
00879 return rpcStatusMake(status);
00880 }
00881 else
00882 {
00883 if (s = dbm->getNewDbid(newid))
00884 return rpcStatusMake(s);
00885 makeTemp = True;
00886 }
00887
00888 rpc_status = IDB_dbCreate_realize(ch, dbm, newid, dbmdb,
00889 userauth, passwdauth, dbname,
00890 dbdesc->dbfile, makeTemp,
00891 &dbdesc->sedbdesc);
00892 if (rpc_status)
00893 return rpc_status;
00894
00895 return RPCSuccess;
00896 }
00897
00898 RPCStatus
00899 IDB_checkDBAuth(ConnHandle *ch, const char *dbmdb,
00900 const char *dbname, const char *&userauth,
00901 const char *&passwdauth, DBAccessMode dbmode,
00902 Bool rw_mode, int *puid, DBM_Database **pdbm,
00903 const char *msg);
00904
00905 RPCStatus
00906 IDB_dbDelete(ConnHandle *ch, const char *dbmdb, const char *userauth,
00907 const char *passwdauth, const char *dbname)
00908 {
00909 if (!strcmp(dbname, DBM_Database::getDbName()))
00910 return rpcStatusMake_se(eyedbsm::dbDelete(dbmdb));
00911
00912 DBM_Database *dbm;
00913 RPCStatus rpc_status = IDB_dbmOpen(ch, dbmdb, True, &dbm);
00914
00915 if (rpc_status != RPCSuccess)
00916 return rpc_status;
00917
00918 const char *dbfile;
00919 Status s = dbm->getDbFile(&dbname, 0, dbfile);
00920 if (s) return rpcStatusMake(s);
00921
00922 if (!dbfile)
00923 return rpcStatusMake(IDB_ERROR, "database '%s' does not exists", dbname);
00924 if ((rpc_status = IDB_checkDBAuth(ch, dbmdb, dbname, userauth, passwdauth,
00925 AdminDBAccessMode, False, NULL, NULL,
00926 "deleting database")) !=
00927 RPCSuccess)
00928 return rpc_status;
00929
00930 eyedbsm::Status se_status = eyedbsm::dbDelete(dbfile);
00931
00932 if (se_status == eyedbsm::Success)
00933 {
00934 Status status = dbm->removeEntry(dbname);
00935 if (status)
00936 return rpcStatusMake(status);
00937 }
00938
00939 return rpcStatusMake_se(se_status);
00940 }
00941
00942 static RPCStatus
00943 IDB_getDbFile(ConnHandle *ch, const char **pdbname, const char *dbmdb,
00944 const char **dbfile, int *dbid, Bool rw_mode,
00945 DBM_Database **pdbm = 0)
00946 {
00947 RPCStatus rpc_status = IDB_checkAuthDbm(dbmdb);
00948 if (rpc_status)
00949 return rpc_status;
00950
00951 if (strcmp(*pdbname, DBM_Database::getDbName())) {
00952 DBM_Database *dbm;
00953
00954 rpc_status = IDB_dbmOpen(ch, dbmdb, rw_mode, &dbm);
00955
00956 if (rpc_status != RPCSuccess)
00957 return rpc_status;
00958
00959 if (pdbm)
00960 *pdbm = dbm;
00961
00962
00963 Status s = dbm->getDbFile(pdbname, dbid, *dbfile);
00964
00965 if (s)
00966 return rpcStatusMake(s);
00967
00968 if (!*dbfile) {
00969 if ((*pdbname)[0])
00970 return rpcStatusMake(IDB_ERROR,
00971 "cannot open database '%s'", *pdbname);
00972 else
00973 return rpcStatusMake(IDB_ERROR,
00974 "cannot open database dbid #%d", *dbid);
00975 }
00976 }
00977 else {
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 *dbfile = dbmdb;
00995
00996 if (dbid)
00997 *dbid = DBM_Database::getDbid();
00998
00999 if (pdbm) {
01000
01001 RPCStatus rpc_status;
01002 DBM_Database *dbm;
01003
01004 rpc_status = IDB_dbmOpen(ch, dbmdb, rw_mode, &dbm);
01005 if (rpc_status != RPCSuccess)
01006 return rpc_status;
01007 *pdbm = dbm;
01008 }
01009 }
01010
01011 return RPCSuccess;
01012 }
01013
01014 RPCStatus
01015 IDB_dbMoveCopy(ConnHandle *ch, const char *dbmdb,
01016 const char *userauth, const char *passwdauth,
01017 const char *dbname,
01018 const char *newdbname, const DbCreateDescription *dbdesc,
01019 Bool copy)
01020 {
01021 const char *dbfile;
01022 int dbid;
01023
01024 DBM_Database *dbm;
01025 RPCStatus rpc_status = IDB_getDbFile(ch, &dbname, dbmdb, &dbfile, &dbid,
01026 True, &dbm);
01027 if (rpc_status)
01028 return rpc_status;
01029
01030 const char *xdbfile;
01031 Status s = dbm->getDbFile(&newdbname, 0, xdbfile);
01032 if (s)
01033 return rpcStatusMake(s);
01034 if (copy && xdbfile)
01035 return rpcStatusMake(IDB_ERROR,
01036 "database '%s' already exists", newdbname);
01037
01038 eyedbsm::DbMoveDescription mvcpdesc;
01039 strcpy(mvcpdesc.dbfile, dbdesc->dbfile);
01040 mvcpdesc.dcr = dbdesc->sedbdesc;
01041 eyedbsm::Status se_status;
01042
01043 if (copy)
01044 se_status = eyedbsm::dbCopy(dbfile, &mvcpdesc);
01045 else
01046 se_status = eyedbsm::dbMove(dbfile, &mvcpdesc);
01047
01048 if (se_status)
01049 return rpcStatusMake_se(se_status);
01050
01051 eyedbsm::DbRelocateDescription rldesc;
01052 rldesc.ndat = mvcpdesc.dcr.ndat;
01053
01054 for (int i = 0; i < rldesc.ndat; i++)
01055 strcpy(rldesc.file[i], mvcpdesc.dcr.dat[i].file);
01056
01057 Status status;
01058
01059 if (!copy)
01060 {
01061 status = dbm->removeEntry(dbname);
01062 if (status)
01063 return rpcStatusMake(status);
01064 }
01065
01066 status = dbm->createEntry(dbid, newdbname, mvcpdesc.dbfile);
01067
01068 return rpcStatusMake(status);
01069 }
01070
01071 RPCStatus
01072 IDB_dbMove(ConnHandle *ch, const char *dbmdb,
01073 const char *userauth, const char *passwdauth, const char *dbname,
01074 const DbCreateDescription *dbdesc)
01075 {
01076 if (!strcmp(dbmdb, DBM_Database::getDbName()))
01077 return rpcStatusMake(Exception::make(IDB_ERROR, "cannot move %s database, use the unix tool 'mv' and update your configuration file",
01078 DBM_Database::getDbName()));
01079 return IDB_dbMoveCopy(ch, dbmdb, userauth, passwdauth, dbname, dbname, dbdesc, False);
01080 }
01081
01082 RPCStatus
01083 IDB_dbCopy(ConnHandle *ch, const char *dbmdb,
01084 const char *userauth, const char *passwdauth, const char *dbname,
01085 const char *newdbname, Bool newdbid,
01086 const DbCreateDescription *dbdesc)
01087 {
01088 return IDB_dbMoveCopy(ch, dbmdb, userauth, passwdauth, dbname, newdbname,
01089 dbdesc, True);
01090 }
01091
01092 RPCStatus
01093 IDB_dbRename(ConnHandle *ch, const char *dbmdb,
01094 const char *userauth, const char *passwdauth,
01095 const char *dbname, const char *newdbname)
01096 {
01097 if (!strcmp(dbname, DBM_Database::getDbName()))
01098 return rpcStatusMake(IDB_DATABASE_RENAME_ERROR, "cannot rename a DBM_Database database");
01099
01100 DBM_Database *dbm;
01101 RPCStatus rpc_status;
01102
01103 rpc_status = IDB_dbmOpen(ch, dbmdb, True, &dbm);
01104
01105 if (rpc_status != RPCSuccess)
01106 return rpc_status;
01107
01108 int dbid;
01109 const char *dbfile;
01110 Status s = dbm->getDbFile(&dbname, &dbid, dbfile);
01111 if (s) return rpcStatusMake(s);
01112
01113 if (!dbfile)
01114 return rpcStatusMake(IDB_DATABASE_RENAME_ERROR, "cannot open database '%s'", dbname);
01115
01116 if ((rpc_status = IDB_checkDBAuth(ch, dbmdb, dbname, userauth, passwdauth,
01117 AdminDBAccessMode, True, NULL, NULL,
01118 "renaming database")) !=
01119 RPCSuccess)
01120 return rpc_status;
01121
01122 const char *ndbfile;
01123 s = dbm->getDbFile(&newdbname, 0, ndbfile);
01124 if (s) return rpcStatusMake(s);
01125
01126 if (ndbfile)
01127 return rpcStatusMake(IDB_DATABASE_RENAME_ERROR,
01128 "database '%s' already exists",
01129 newdbname);
01130 return rpcStatusMake(dbm->updateEntry(dbid, dbname, newdbname, dbfile));
01131 }
01132
01133
01134
01135 static SessionLog *sesslogTempl;
01136
01137 void setConnInfo(rpc_ConnInfo *ci)
01138 {
01139 conn_ctx.ci = ci;
01140 conn_ctx.sesslog = new SessionLog(*sesslogTempl);
01141
01142 }
01143
01144
01145
01146 static const char *
01147 getUserAuth(const char *username, Bool &need_passwd,
01148 Bool &superuser)
01149 {
01150 int i;
01151 rpc_TcpIp *tcpip;
01152 need_passwd = True;
01153 superuser = False;
01154
01155 if (conn_ctx.ci && conn_ctx.ci->auth.uid >= 0) {
01156 int uid = (conn_ctx.ci ? conn_ctx.ci->auth.uid : getuid());
01157 passwd *pwd = getpwuid(uid);
01158 const char *authusername = (pwd ? pwd->pw_name : "");
01159 if (!*username || !strcmp(username, authusername)) {
01160 need_passwd = False;
01161 #ifdef STUART_SUGGESTION
01162 if (uid == getuid())
01163 superuser = True;
01164 #endif
01165 return strdup(authusername);
01166 }
01167
01168 return username;
01169 }
01170
01171 if (true) {
01172 const char *chuser = 0;
01173 tcpip = &conn_ctx.ci->tcpip;
01174
01175 for (i = 0; i < tcpip->user_cnt; i++) {
01176 if (!*username) {
01177 if (tcpip->users[i].mode == rpc_User::DEF)
01178 chuser = tcpip->users[i].user;
01179 }
01180 else if (!strcmp(username, tcpip->users[i].user)) {
01181
01182 if (tcpip->users[i].mode == rpc_User::ON ||
01183 tcpip->users[i].mode == rpc_User::DEF)
01184 chuser = username;
01185 else if (tcpip->users[i].mode == rpc_User::NOT)
01186 chuser = 0;
01187 }
01188 else if (tcpip->users[i].mode == rpc_User::ALL ||
01189 tcpip->users[i].mode == rpc_User::NOT)
01190 chuser = username;
01191 }
01192
01193 return chuser;
01194 }
01195
01196 return username;
01197 }
01198
01199 static RPCStatus
01200 IDB_checkAuth(const char *&userauth, Bool &need_passwd, Bool &superuser)
01201 {
01202 const char *u;
01203 if (!(u = getUserAuth(userauth, need_passwd, superuser))) {
01204 if (*userauth)
01205 return rpcStatusMake(IDB_INSUFFICIENT_PRIVILEGES,
01206 "access denied for user '%s'",
01207 userauth);
01208
01209 return rpcStatusMake(IDB_INSUFFICIENT_PRIVILEGES,
01210 "access denied for unspecified user");
01211 }
01212
01213 userauth = u;
01214 return RPCSuccess;
01215 }
01216
01217 static RPCStatus
01218 IDB_checkSysAuth(ConnHandle *ch, const char *dbmdb,
01219 const char *&userauth, const char *&passwdauth,
01220 SysAccessMode sysmode, Bool rw_mode,
01221 DBM_Database **pdbm, const char *msg, Bool *justCheck)
01222 {
01223 if (pdbm)
01224 *pdbm = 0;
01225
01226 DBM_Database *dbm;
01227 RPCStatus rpc_status;
01228 Status status;
01229 SysUserAccess *sysaccess;
01230
01231 if ((rpc_status = IDB_dbmOpen(ch, dbmdb, rw_mode, &dbm)) != RPCSuccess)
01232 return rpc_status;
01233 if (pdbm)
01234 *pdbm = dbm;
01235
01236 if (!userauth || !passwdauth)
01237 return RPCSuccess;
01238
01239 Bool need_passwd, superuser;
01240 if (rpc_status = IDB_checkAuth(userauth, need_passwd, superuser))
01241 return rpc_status;
01242
01243 #ifdef STUART_SUGGESTION
01244 if (superuser)
01245 return RPCSuccess;
01246 #endif
01247
01248 if (status = dbm->get_sys_user_access(userauth, &sysaccess,
01249 (justCheck ? True : False),
01250 msg))
01251 return rpcStatusMake(status);
01252
01253 if (justCheck && !sysaccess) {
01254 *justCheck = False;
01255 return RPCSuccess;
01256 }
01257
01258 dbm->transactionBegin();
01259
01260
01261
01262 if (!need_passwd && (sysaccess->user()->type() == EyeDBUser))
01263 need_passwd = True;
01264
01265 if (need_passwd) {
01266 if (sysaccess->user()->type() == StrictUnixUser) {
01267 sysaccess->release();
01268 dbm->transactionCommit();
01269 return rpcStatusMake(IDB_AUTHENTICATION_FAILED,
01270 "user '%s' can be used only in a "
01271 "strict unix authentication mode",
01272 userauth);
01273 }
01274
01275 const char *pwd = sysaccess->user()->passwd().c_str();
01276 if (pwd && strcmp(pwd, crypt(passwdauth, salt))) {
01277 if (justCheck) {
01278 *justCheck = False;
01279 status = Success;
01280 }
01281 else
01282 status = Exception::make(IDB_AUTHENTICATION_FAILED,
01283 "user '%s': %s: invalid password",
01284 userauth, msg);
01285 sysaccess->release();
01286 dbm->transactionCommit();
01287 return rpcStatusMake(status);
01288 }
01289 }
01290
01291 if ((sysmode & sysaccess->mode()) != sysmode) {
01292 if (justCheck) {
01293 *justCheck = False;
01294 status = Success;
01295 }
01296 else
01297 status = Exception::make(IDB_INSUFFICIENT_PRIVILEGES,
01298 "user '%s': %s", userauth, msg);
01299 sysaccess->release();
01300 dbm->transactionCommit();
01301 return rpcStatusMake(status);
01302 }
01303
01304 if (justCheck)
01305 *justCheck = True;
01306
01307 sysaccess->release();
01308 dbm->transactionCommit();
01309 return RPCSuccess;
01310 }
01311
01312 #define dbmupdate_str "*I*D*B*D*B*M*"
01313
01314 RPCStatus
01315 IDB_checkDBAuth(ConnHandle *ch, const char *dbmdb,
01316 const char *dbname, const char *&userauth,
01317 const char *&passwdauth, DBAccessMode dbmode,
01318 Bool rw_mode, int *puid, DBM_Database **pdbm,
01319 const char *msg)
01320 {
01321 if (!pdbm && !strcmp(dbname, DBM_Database::getDbName()) &&
01322 userauth && !strcmp(userauth, dbmupdate_str))
01323 return RPCSuccess;
01324
01325 if (puid)
01326 *puid = 0;
01327
01328 if (!userauth && !pdbm)
01329 return RPCSuccess;
01330
01331 if (pdbm)
01332 *pdbm = 0;
01333
01334 DBM_Database *dbm;
01335 RPCStatus rpc_status;
01336 Status status;
01337 DBUserAccess *dbaccess;
01338 DBAccessMode defaccess;
01339
01340 if ((rpc_status = IDB_dbmOpen(ch, dbmdb, rw_mode, &dbm)) != RPCSuccess)
01341 return rpc_status;
01342
01343 if (pdbm)
01344 *pdbm = dbm;
01345
01346 if (!userauth || !passwdauth)
01347 return RPCSuccess;
01348
01349 Bool need_passwd, superuser;
01350 if (rpc_status = IDB_checkAuth(userauth, need_passwd, superuser))
01351 return rpc_status;
01352
01353 #ifdef STUART_SUGGESTION
01354 if (superuser)
01355 return RPCSuccess;
01356 #endif
01357
01358 if (status = dbm->transactionBegin())
01359 return rpcStatusMake(status);
01360
01361 Bool justCheck = False;
01362 if (rpc_status = IDB_checkSysAuth(ch, dbmdb, userauth, passwdauth,
01363 SuperUserSysAccessMode, False, 0, msg,
01364 &justCheck))
01365 {
01366 dbm->transactionCommit();
01367 return rpc_status;
01368 }
01369
01370 if (justCheck)
01371 {
01372 dbm->transactionCommit();
01373 return RPCSuccess;
01374 }
01375
01376 UserEntry *user;
01377
01378 if (status = dbm->get_db_user_access(dbname, userauth, &user,
01379 &dbaccess, &defaccess))
01380 {
01381 dbm->transactionCommit();
01382 return rpcStatusMake(status);
01383 }
01384
01385
01386
01387
01388 if (!need_passwd && (user->type() == EyeDBUser))
01389 need_passwd = True;
01390
01391 if (need_passwd)
01392 {
01393 if (user->type() == StrictUnixUser)
01394 {
01395 if (dbaccess)
01396 dbaccess->release();
01397 user->release();
01398 dbm->transactionCommit();
01399 return rpcStatusMake(IDB_AUTHENTICATION_FAILED,
01400 "user '%s' can be used only in a "
01401 "strict unix authentication mode",
01402 userauth);
01403 }
01404
01405 if (user->passwd().c_str() &&
01406 strcmp(user->passwd().c_str(), crypt(passwdauth, salt)))
01407 {
01408 if (dbaccess)
01409 dbaccess->release();
01410 user->release();
01411 status = Exception::make(IDB_AUTHENTICATION_FAILED,
01412 "user '%s': %s: invalid password",
01413 userauth, msg);
01414 dbm->transactionCommit();
01415 return rpcStatusMake(status);
01416 }
01417 }
01418
01419 if (puid &&
01420 ((dbaccess &&
01421 (dbaccess->mode() & AdminDBAccessMode) != AdminDBAccessMode) ||
01422 !dbaccess))
01423 *puid = user->uid();
01424
01425 user->release();
01426
01427 if ((dbmode & defaccess) == dbmode)
01428 {
01429 if (dbaccess)
01430 dbaccess->release();
01431 dbm->transactionCommit();
01432 return RPCSuccess;
01433 }
01434
01435 if (!dbaccess || (dbmode & dbaccess->mode()) != dbmode)
01436 {
01437 if (dbaccess)
01438 dbaccess->release();
01439 status = Exception::make(IDB_INSUFFICIENT_PRIVILEGES,
01440 "user '%s': %s", userauth, msg);
01441 dbm->transactionCommit();
01442 return rpcStatusMake(status);
01443 }
01444
01445 if (dbaccess)
01446 dbaccess->release();
01447 dbm->transactionCommit();
01448 return RPCSuccess;
01449 }
01450
01451 static Status
01452 checkUserName(const char *username, int user_type)
01453 {
01454 if (!*username)
01455 return Exception::make(IDB_ERROR, "a username cannot be the empty string");
01456
01457 char c;
01458 const char *p = username;
01459 while (c = *p++)
01460 if (!((c >= 'a' && c <= 'z') ||
01461 (c >= 'A' && c <= 'Z') ||
01462 (c >= '0' && c <= '9') ||
01463 c == '_' || c == '.' || c == '-'))
01464 return Exception::make(IDB_ERROR,
01465 "a username must be under the form: "
01466 "[a-zA-Z0-9_\\.\\-]+");
01467
01468 if ((user_type == UnixUser || user_type == StrictUnixUser) &&
01469 !getpwnam(username))
01470 return Exception::make(IDB_ERROR, "username '%s' is an unknown "
01471 "unix user", username);
01472
01473 return Success;
01474 }
01475
01476 RPCStatus
01477 IDB_userAdd(ConnHandle *ch, const char *dbmdb,
01478 const char *userauth, const char *passwdauth,
01479 const char *username, const char *passwd, int user_type)
01480 {
01481 RPCStatus rpc_status;
01482 Status status;
01483 DBM_Database *dbm;
01484
01485 if ((rpc_status = IDB_checkSysAuth(ch, dbmdb, userauth, passwdauth,
01486 AddUserSysAccessMode, True, &dbm,
01487 "adding user")) !=
01488 RPCSuccess)
01489 return rpc_status;
01490
01491 if (status = checkUserName(username, user_type))
01492 return rpcStatusMake(status);
01493
01494
01495 std::string pwd = (*passwd ? crypt(passwd, salt) : "");
01496 status = dbm->add_user(username, pwd.c_str(), (UserType)user_type);
01497
01498 return rpcStatusMake(status);
01499 }
01500
01501 RPCStatus
01502 IDB_userDelete(ConnHandle *ch, const char *dbmdb,
01503 const char *userauth, const char *passwdauth,
01504 const char *username)
01505 {
01506 RPCStatus rpc_status;
01507 Status status;
01508 DBM_Database *dbm;
01509
01510 if ((rpc_status = IDB_checkSysAuth(ch, dbmdb, userauth, passwdauth,
01511 DeleteUserSysAccessMode, True, &dbm,
01512 "deleting user")) !=
01513 RPCSuccess)
01514 return rpc_status;
01515
01516 status = dbm->delete_user(username);
01517
01518 return rpcStatusMake(status);
01519 }
01520
01521 RPCStatus
01522 IDB_userPasswdSet(ConnHandle *ch, const char *dbmdb,
01523 const char *userauth, const char *passwdauth,
01524 const char *username, const char *passwd)
01525 {
01526 RPCStatus rpc_status;
01527 Status status;
01528 DBM_Database *dbm;
01529
01530 if ((rpc_status = IDB_checkSysAuth(ch, dbmdb, userauth, passwdauth,
01531 SetUserPasswdSysAccessMode, True,
01532 &dbm,"setting passwd")) !=
01533 RPCSuccess)
01534 return rpc_status;
01535
01536
01537 const char *pwd = (*passwd ? crypt(passwd, salt) : 0);
01538 status = dbm->user_passwd_set(username, pwd);
01539
01540 return rpcStatusMake(status);
01541 }
01542
01543 RPCStatus
01544 IDB_passwdSet(ConnHandle *ch, const char *dbmdb,
01545 const char *username, const char *passwd,
01546 const char *newpasswd)
01547 {
01548 DBM_Database *dbm;
01549 RPCStatus rpc_status;
01550 Status s;
01551 UserEntry *user;
01552
01553 if ((rpc_status = IDB_dbmOpen(ch, dbmdb, True, &dbm)) != RPCSuccess)
01554 return rpc_status;
01555
01556 s = dbm->getUser(username, user);
01557 if (s) return rpcStatusMake(s);
01558
01559 if (!user)
01560 return rpcStatusMake(Exception::make(IDB_SET_PASSWD_ERROR,
01561 "user '%s' not found",
01562 username));
01563
01564 if (user->passwd().c_str() && strcmp(user->passwd().c_str(), crypt(passwd, salt)))
01565 {
01566 user->release();
01567 s = Exception::make(IDB_AUTHENTICATION_FAILED,
01568 "user '%s': %s", username,
01569 "setting passwd");
01570 return rpcStatusMake(s);
01571 }
01572
01573 user->release();
01574
01575 s = dbm->user_passwd_set(username, crypt(newpasswd, salt));
01576 return rpcStatusMake(s);
01577 }
01578
01579 RPCStatus
01580 IDB_userDBAccessSet(ConnHandle *ch, const char *dbmdb,
01581 const char *userauth, const char *passwdauth,
01582 const char *dbname, const char *username, int mode)
01583 {
01584 RPCStatus rpc_status;
01585 Status status;
01586 DBM_Database *dbm;
01587
01588 if ((rpc_status = IDB_checkDBAuth(ch, dbmdb, dbname, userauth, passwdauth,
01589 AdminDBAccessMode, True, NULL, &dbm,
01590 "setting user db access")) !=
01591 RPCSuccess) {
01592 return rpc_status;
01593 }
01594
01595 status = dbm->user_db_access_set(dbname, username, (DBAccessMode)mode);
01596
01597 return rpcStatusMake(status);
01598 }
01599
01600 RPCStatus
01601 IDB_userSysAccessSet(ConnHandle *ch, const char *dbmdb,
01602 const char *userauth, const char *passwdauth,
01603 const char *username, int mode)
01604 {
01605 RPCStatus rpc_status;
01606 Status status;
01607 DBM_Database *dbm;
01608
01609 if ((rpc_status = IDB_checkSysAuth(ch, dbmdb,userauth, passwdauth,
01610 SuperUserSysAccessMode, True, &dbm,
01611 "setting sys user access")) !=
01612 RPCSuccess)
01613 return rpc_status;
01614
01615 status = dbm->user_sys_access_set(username, (SysAccessMode)mode);
01616
01617 return rpcStatusMake(status);
01618 }
01619
01620 RPCStatus
01621 IDB_defaultDBAccessSet(ConnHandle *ch, const char *dbmdb,
01622 const char *userauth, const char *passwdauth,
01623 const char *dbname, int mode)
01624 {
01625 RPCStatus rpc_status;
01626 Status status;
01627 DBM_Database *dbm;
01628
01629 if ((rpc_status = IDB_checkDBAuth(ch, dbmdb, dbname, userauth, passwdauth,
01630 AdminDBAccessMode, True, NULL, &dbm,
01631 "setting database access")) !=
01632 RPCSuccess)
01633 return rpc_status;
01634
01635 status = dbm->default_db_access_set(dbname, (DBAccessMode)mode);
01636
01637 return rpcStatusMake(status);
01638 }
01639
01640 extern DbHandle *
01641 database_getDbHandle(Database *);
01642
01643 RPCStatus
01644 IDB_dbOpen_make(ConnHandle *ch, const char *dbmdb,
01645 const char *userauth, const char *passwdauth,
01646 const char *dbname, int dbid, int flag,
01647 int oh_maph, unsigned oh_mapwide,
01648 int *pid, int *puid, char **rname,
01649 int *rdbid, unsigned int *pversion, DbHandle **pdbh)
01650 {
01651 Database *db;
01652 Connection *conn = ConnectionPeer::newIdbConnection(ch);
01653 Status status;
01654 RPCStatus rpc_status;
01655
01656
01657
01658
01659
01660
01661
01662 OpenHints hints;
01663 hints.maph = (MapHints)oh_maph;
01664 hints.mapwide = oh_mapwide;
01665
01666 if (*dbname)
01667 status = Database::open(conn, dbname, dbmdb, userauth, passwdauth,
01668 (Database::OpenFlag)flag, &hints, &db);
01669 else
01670 status = Database::open(conn, dbid, dbmdb, userauth, passwdauth,
01671 (Database::OpenFlag)flag, &hints, &db);
01672
01673 if (status == Success)
01674 {
01675 *rname = (char *)db->getName();
01676 *rdbid = db->getDbid();
01677 *pdbh = database_getDbHandle(db);
01678 if (pversion)
01679 *pversion = db->getVersionNumber();
01680 *puid = db->getUid();
01681
01682
01683
01684
01685 }
01686 else
01687 *rname = "";
01688
01689 return rpcStatusMake(status);
01690 }
01691
01692 RPCStatus
01693 IDB_dbOpen(ConnHandle *ch, const char *dbmdb,
01694 const char *userauth, const char *passwdauth,
01695 const char *dbname,
01696 int dbid, int flags, int oh_maph, unsigned int oh_mapwide,
01697 int *pid, int *puid, void *db, char **rname,
01698 int *rdbid, unsigned int *pversion, DbHandle **pdbh)
01699 {
01700 eyedbsm::Status status;
01701 eyedbsm::DbHandle *sedbh;
01702 int se_flags;
01703 RPCStatus rpc_status;
01704 int flags_o = flags;
01705
01706
01707
01708
01709
01710
01711
01712
01713 *rname = "";
01714 *rdbid = 0;
01715
01716 flags &= ~(_DBOpenLocal);
01717
01718 if ((flags & _DBSRead) == _DBSRead) {
01719
01720 se_flags = eyedbsm::VOLREAD|eyedbsm::NO_SHM_ACCESS;
01721 }
01722 else if ((flags & _DBRW) == _DBRW || (flags & _DBRead) == _DBRead) {
01723 se_flags = eyedbsm::VOLRW;
01724 }
01725 else {
01726 return rpcStatusMake(IDB_INVALID_DBOPEN_FLAG,
01727 "opening flag '%u' is invalid", flags);
01728 }
01729
01730 const char *dbfile;
01731
01732 rpc_status = IDB_getDbFile(ch, &dbname, dbmdb, &dbfile, &dbid, False);
01733 if (rpc_status != RPCSuccess)
01734 return rpc_status;
01735
01736
01737 std::string msg = std::string("opening database '") + dbname + "' in " +
01738 Database::getStringFlag((Database::OpenFlag)flags_o) + " mode";
01739 DBAccessMode dbmode;
01740
01741 if (flags & _DBAdmin)
01742 dbmode = AdminDBAccessMode;
01743 else if (flags == _DBRead || flags == _DBSRead)
01744 dbmode = ReadDBAccessMode;
01745 else
01746 dbmode = ReadWriteDBAccessMode;
01747
01748
01749 if (eyedbsm::backend)
01750 {
01751 if ((rpc_status = IDB_checkDBAuth(ch, dbmdb, dbname, userauth,
01752 passwdauth, dbmode, False,
01753 puid, 0, msg.c_str())) !=
01754 RPCSuccess)
01755 return rpc_status;
01756 }
01757
01758
01759
01760 unsigned int version;
01761 if (!pversion)
01762 pversion = &version;
01763
01764 *pversion = eyedb::getVersionNumber();
01765 eyedbsm::OpenHints hints;
01766 hints.maph = (eyedbsm::MapHints)oh_maph;
01767 hints.mapwide = oh_mapwide;
01768
01769 status = eyedbsm::dbOpen(dbfile, se_flags|eyedbsm::LOCAL, (oh_maph ? &hints : 0),
01770 (puid ? *puid : 0), pversion, &sedbh);
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 if (status)
01782 return rpcStatusMake_se(status);
01783
01784
01785
01786
01787
01788
01789
01790
01791 *rdbid = dbid;
01792 *rname = (char *)dbname;
01793 *pdbh = rpc_new(DbHandle);
01794 memset(*pdbh, 0, sizeof(DbHandle));
01795 (*pdbh)->sedbh = sedbh;
01796 (*pdbh)->ch = ch;
01797
01798
01799 rpc_status = IDB_schemaClassHeadGet(*pdbh);
01800
01801
01802 if (rpc_status == RPCSuccess)
01803 {
01804 if (db)
01805 (*pdbh)->db = db;
01806 else
01807 {
01808 rpcDB_LocalDBContext ldbctx;
01809 ldbctx.rdbhid = 0;
01810 ldbctx.xid = sedbh->xid;
01811 Status status = IDB_makeDatabase(ch, dbmdb, dbname, dbid,
01812 flags_o, *pdbh, &ldbctx,
01813 &(*pdbh)->sch.oid,
01814 *pversion,
01815 (Database *&)(*pdbh)->db);
01816 if (status)
01817 return rpcStatusMake(status);
01818 }
01819
01820
01821 if (!db_list)
01822 {
01823 db_list = new LinkedList();
01824 rpc_setQuitHandler(quit_handler, db_list);
01825 }
01826
01827 db_list->insertObjectLast((*pdbh)->db);
01828 if (conn_ctx.clinfo)
01829 conn_ctx.clinfo->addDatabase
01830 (dbname,
01831
01832 userauth,
01833
01834 flags_o);
01835 }
01836
01837
01838 return rpc_status;
01839 }
01840
01841 extern void oqml_reinit(Database *db);
01842
01843 RPCStatus
01844 IDB_dbClose_make(DbHandle *dbh)
01845 {
01846 oqml_reinit((Database *)dbh->db);
01847 RPCStatus rpc_status = rpcStatusMake(((Database *)(dbh->db))->close());
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 return rpc_status;
01860 }
01861
01862 RPCStatus
01863 IDB_dbClose(DbHandle *dbh)
01864 {
01865 oqml_reinit((Database *)dbh->db);
01866 RPCStatus s = rpcStatusMake_se(eyedbsm::dbClose(dbh->sedbh));
01867 if (!s && dbh->db) {
01868 if (conn_ctx.clinfo)
01869 conn_ctx.clinfo->suppressDatabase(((Database *)dbh->db)->getName(),
01870 ((Database *)dbh->db)->getUser(),
01871 ((Database *)dbh->db)->getOpenFlag());
01872 db_list->deleteObject(dbh->db);
01873 dbh->db = 0;
01874 }
01875
01876 return s;
01877
01878 }
01879
01880 void
01881 IDB_getLocalInfo(DbHandle *dbh, rpcDB_LocalDBContext *ldbctx,
01882 eyedbsm::Oid *sch_oid)
01883 {
01884 ldbctx->rdbhid = 0;
01885 ldbctx->xid = dbh->sedbh->xid;
01886
01887 *sch_oid = dbh->sch.oid;
01888 }
01889
01890 RPCStatus
01891 IDB_dbCloseLocal(DbHandle *dbh)
01892 {
01893 oqml_reinit((Database *)dbh->db);
01894
01895
01896
01897
01898 return rpcStatusMake_se(eyedbsm::dbClose((eyedbsm::DbHandle *)dbh->sedbh));
01899 }
01900
01901 RPCStatus
01902 IDB_dbInfo(ConnHandle *ch, const char *dbmdb,
01903 const char *userauth, const char *passwdauth, const char *dbname,
01904 int *rdbid, DbCreateDescription *dbdesc)
01905 {
01906 RPCStatus rpc_status;
01907 const char *dbfile;
01908
01909 rpc_status = IDB_getDbFile(ch, &dbname, dbmdb, &dbfile, rdbid, False);
01910 if (rpc_status != RPCSuccess)
01911 return rpc_status;
01912
01913 strcpy(dbdesc->dbfile, dbfile);
01914 return rpcStatusMake_se(eyedbsm::dbInfo(dbdesc->dbfile, &dbdesc->sedbdesc));
01915 }
01916
01917 static Bool backend_interrupt = False;
01918
01919 void
01920 setBackendInterrupt(Bool to)
01921 {
01922 backend_interrupt = to;
01923 }
01924
01925 Bool
01926 isBackendInterrupted()
01927 {
01928 return backend_interrupt;
01929 }
01930
01931 RPCStatus
01932 IDB_backendInterrupt(ConnHandle *, int)
01933 {
01934 setBackendInterrupt(True);
01935 eyedbsm::backendInterrupt();
01936 return RPCSuccess;
01937 }
01938
01939 RPCStatus
01940 IDB_backendInterruptReset()
01941 {
01942 setBackendInterrupt(False);
01943 eyedbsm::backendInterruptReset();
01944 return RPCSuccess;
01945 }
01946
01947
01948
01949
01950
01951 RPCStatus
01952 IDB_transactionBegin(DbHandle *dbh,
01953 const TransactionParams *params,
01954 Bool local_call)
01955 {
01956 Database *db = (Database *)dbh->db;
01957
01958 IDB_LOG(IDB_LOG_TRANSACTION,
01959 ("transaction begin(db=%p, dbh=%p, tr_cnt=%d, "
01960 "local_call=%d, BE=%d, dbname=%s)\n",
01961 db, dbh, dbh->tr_cnt, local_call,
01962 (db ? db->isBackEnd() : -1), (db ? db->getName() : "NIL")));
01963
01964 if (!local_call && db && db->isBackEnd())
01965 {
01966 if (params)
01967 return rpcStatusMake(db->transactionBegin(*params));
01968 return rpcStatusMake(db->transactionBegin());
01969 }
01970
01971 eyedbsm::Status status = eyedbsm::transactionBegin(dbh->sedbh,
01972 (const eyedbsm::TransactionParams *)params);
01973
01974 if (!status)
01975 dbh->tr_cnt++;
01976
01977 return rpcStatusMake_se(status);
01978 }
01979
01980 RPCStatus
01981 IDB_objectDeletedManage(DbHandle *dbh, Bool commit)
01982 {
01983 Database *db = (Database *)dbh->db;
01984
01985 if (!db)
01986 return RPCSuccess;
01987
01988 RPCStatus rpc_status;
01989 LinkedListCursor c(db->getMarkDeleted());
01990 Oid *oid;
01991 int error = 0;
01992
01993 while (c.getNext((void *&)oid)) {
01994 if (commit && !error) {
01995 rpc_status =
01996 IDB_objectSizeModify(dbh, IDB_OBJ_HEAD_SIZE, oid->getOid());
01997 if (rpc_status)
01998 error++;
01999 }
02000 delete oid;
02001 }
02002
02003 db->getMarkDeleted().empty();
02004 db->markCreatedEmpty();
02005
02006 if (error)
02007 return rpc_status;
02008
02009 return RPCSuccess;
02010 }
02011
02012 RPCStatus
02013 IDB_transactionCommit(DbHandle *dbh, Bool local_call)
02014 {
02015 Database *db = (Database *)dbh->db;
02016 RPCStatus rpc_status;
02017
02018 IDB_LOG(IDB_LOG_TRANSACTION,
02019 ("transaction commit(db=%p, dbh=%p, tr_cnt=%d, "
02020 "local_call=%d, BE=%d, dbname=%s)\n",
02021 db, dbh, dbh->tr_cnt, local_call,
02022 (db ? db->isBackEnd() : -1), (db ? db->getName() : "NIL")));
02023
02024 if (!local_call && db && db->isBackEnd())
02025 return rpcStatusMake(db->transactionCommit());
02026
02027 if (rpc_status = IDB_objectDeletedManage(dbh, True))
02028 return rpc_status;
02029
02030 eyedbsm::Status status = eyedbsm::transactionCommit(dbh->sedbh);
02031
02032 if (!status)
02033 dbh->tr_cnt--;
02034
02035 if (!status && db && db->getSchema())
02036 db->getSchema()->revert(False);
02037
02038 return rpcStatusMake_se(status);
02039 }
02040
02041 RPCStatus
02042 IDB_transactionAbort(DbHandle *dbh, Bool local_call)
02043 {
02044 RPCStatus rpc_status;
02045 Database *db = (Database *)dbh->db;
02046
02047 IDB_LOG(IDB_LOG_TRANSACTION,
02048 ("transaction abort(db=%p, dbh=%p, tr_cnt=%d, "
02049 "local_call=%d, BE=%d, dbname=%s)\n",
02050 db, dbh, dbh->tr_cnt, local_call,
02051 (db ? db->isBackEnd() : -1), (db ? db->getName() : "NIL")));
02052
02053 if (!local_call && db && db->isBackEnd())
02054 return rpcStatusMake(db->transactionAbort());
02055
02056 if (rpc_status = IDB_objectDeletedManage(dbh, False))
02057 return rpc_status;
02058
02059 eyedbsm::Status status = eyedbsm::transactionAbort(dbh->sedbh);
02060
02061 if (!status)
02062 dbh->tr_cnt--;
02063
02064 if (!status && db && db->getSchema())
02065 db->getSchema()->revert(True);
02066
02067 return rpcStatusMake_se(status);
02068 }
02069
02070 RPCStatus
02071 IDB_transactionParamsSet(DbHandle *dbh,
02072 const TransactionParams *params)
02073 {
02074 eyedbsm::Status status = eyedbsm::transactionParamsSet(dbh->sedbh,
02075 (const eyedbsm::TransactionParams *)params);
02076
02077 return rpcStatusMake_se(status);
02078 }
02079
02080 RPCStatus
02081 IDB_transactionParamsGet(DbHandle *dbh,
02082 TransactionParams *params)
02083 {
02084 eyedbsm::Status status = eyedbsm::transactionParamsGet(dbh->sedbh,
02085 (eyedbsm::TransactionParams *)params);
02086
02087 return rpcStatusMake_se(status);
02088 }
02089
02090 #define CHECK_WRITE(DB) \
02091 if ((DB) && !((DB)->getOpenFlag() & _DBRW)) \
02092 return rpcStatusMake(IDB_ERROR, "database is not opened for writing")
02093
02094 static RPCStatus
02095 getDspid(Database *db, const Class *cls, short &dspid)
02096 {
02097 if (dspid != Dataspace::DefaultDspid)
02098 return RPCSuccess;
02099
02100 const Dataspace *dataspace;
02101
02102 if (cls) {
02103 Status s = cls->getDefaultInstanceDataspace(dataspace);
02104 if (s)
02105 return rpcStatusMake(s);
02106
02107 if (dataspace) {
02108 dspid = dataspace->getId();
02109 return RPCSuccess;
02110 }
02111 }
02112
02113 Status s = db->getDefaultDataspace(dataspace);
02114 if (s)
02115 return rpcStatusMake(s);
02116 dspid = (dataspace ? dataspace->getId() : 0);
02117 return RPCSuccess;
02118 }
02119
02120
02121 RPCStatus
02122 IDB_objectCreate(DbHandle *dbh, short dspid, const Data idr,
02123 eyedbsm::Oid *oid, void *xdata, Data *inv_data, void *xinv_data)
02124 {
02125 ObjectHeader hdr;
02126 Offset offset = 0;
02127 RPCStatus rpc_status;
02128 Database *db = (Database *)dbh->db;
02129
02130 CHECK_WRITE(db);
02131
02132 lock_data((Data *)&idr, xdata);
02133
02134 Bool new_ctx = InvOidContext::getContext();
02135
02136 if (!object_header_decode(idr, &offset, &hdr))
02137 {
02138 unlock_data(idr, xdata);
02139 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02140 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectCreate: invalid object_header");
02141 }
02142
02143 if (hdr.type == _Schema_Type)
02144 {
02145 unlock_data(idr, xdata);
02146 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02147 return rpcStatusMake(IDB_CANNOT_CREATE_SCHEMA, "objectCreate: cannot create a schema");
02148 }
02149
02150 const Class *cls = db->getSchema()->getClass(hdr.oid_cl);
02151
02152 rpc_status = getDspid(db, cls, dspid);
02153 if (rpc_status)
02154 return rpc_status;
02155
02156 TRIGGER_MANAGE(db, Class::TrigCreateBefore_C, &hdr, idr, oid, cls);
02157
02158 Oid moid(hdr.oid_cl);
02159 const Oid &mprot_oid = ((Database *)dbh->db)->getMprotOid();
02160
02161 if (mprot_oid.isValid() && moid.compare(mprot_oid))
02162 rpc_status = IDB_protectionCreate(dbh, dspid, idr, &hdr, oid, xdata, True);
02163 else if (eyedb_is_type(hdr, _Class_Type))
02164 rpc_status = IDB_classCreate(dbh, dspid, idr, &hdr, oid, xdata);
02165 else if (eyedb_is_type(hdr, _Struct_Type) ||
02166 eyedb_is_type(hdr, _Union_Type))
02167 rpc_status = IDB_agregatCreate(dbh, dspid, idr, &hdr, oid, xdata);
02168 else if (eyedb_is_type(hdr, _Collection_Type))
02169 rpc_status = IDB_collectionCreate(dbh, dspid, idr, &hdr, oid, xdata);
02170 else
02171 rpc_status = IDB_instanceCreate(dbh, dspid, idr, &hdr, oid, xdata, True);
02172
02173 if (!rpc_status)
02174 TRIGGER_MANAGE(db, Class::TrigCreateAfter_C, &hdr, idr, oid, cls);
02175
02176 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02177
02178 unlock_data(idr, xdata);
02179 return rpc_status;
02180 }
02181
02182 RPCStatus
02183 IDB_objectDelete(DbHandle *dbh, const eyedbsm::Oid *oid, unsigned int flags,
02184 Data *inv_data, void *xinv_data)
02185 {
02186 RPCStatus rpc_status;
02187 ObjectHeader hdr;
02188 Data idr;
02189 Database *db = (Database *)dbh->db;
02190 Oid toid(oid);
02191
02192 IDB_LOG(IDB_LOG_OBJ_REMOVE, ("removing object %s\n", toid.toString()));
02193
02194 Bool new_ctx = InvOidContext::getContext();
02195
02196 rpc_status = IDB_objectHeaderRead(dbh, oid, &hdr);
02197
02198 if (rpc_status != RPCSuccess)
02199 {
02200 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02201 return rpc_status;
02202 }
02203
02204 if (hdr.xinfo & IDB_XINFO_REMOVED)
02205 {
02206 IDB_LOG(IDB_LOG_OBJ_REMOVE, ("object %s already removed\n",
02207 toid.toString()));
02208 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02209 return RPCSuccess;
02210 }
02211
02212 idr = (unsigned char *)malloc(hdr.size);
02213 object_header_code_head(idr, &hdr);
02214
02215 rpc_status = IDB_objectRead(dbh, idr, 0, 0, oid, DefaultLock, 0);
02216
02217 if (rpc_status != RPCSuccess)
02218 {
02219 free(idr);
02220 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02221 return rpc_status;
02222 }
02223
02224 const Class *cls = db->getSchema()->getClass(hdr.oid_cl);
02225 TRIGGER_MANAGE(db, Class::TrigRemoveBefore_C, &hdr, idr, oid, cls);
02226
02227 Oid moid(hdr.oid_cl);
02228 const Oid &mprot_oid = ((Database *)dbh->db)->getMprotOid();
02229
02230 if (mprot_oid.isValid() && moid.compare(mprot_oid))
02231 rpc_status = IDB_protectionDelete(dbh, idr, &hdr, oid);
02232 else if (eyedb_is_type(hdr, _Class_Type))
02233 rpc_status = IDB_classDelete(dbh, idr, &hdr, oid, flags);
02234 else if (eyedb_is_type(hdr, _Struct_Type) ||
02235 eyedb_is_type(hdr, _Union_Type))
02236 rpc_status = IDB_agregatDelete(dbh, idr, &hdr, oid);
02237 else if (eyedb_is_type(hdr, _Collection_Type))
02238 rpc_status = IDB_collectionDelete(dbh, idr, &hdr, oid);
02239 else
02240 rpc_status = IDB_instanceDelete(dbh, idr, &hdr, oid);
02241
02242 if (!rpc_status)
02243 TRIGGER_MANAGE(db, Class::TrigRemoveAfter_C, &hdr, idr, oid, cls);
02244
02245 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02246 free(idr);
02247 if (!rpc_status)
02248 IDB_LOG(IDB_LOG_OBJ_REMOVE, ("object %s is now removed\n", toid.toString()));
02249 return rpc_status;
02250 }
02251
02252 static int
02253 IDB_getObjectSize(const Class *cls, Size *psize, Size *vsize,
02254 ObjectHeader *hdr)
02255 {
02256 return ((cls && cls->getIDRObjectSize(psize, vsize) &&
02257 !cls->asCollectionClass()) ?
02258 cls->getIDRObjectSize() : hdr->size);
02259 }
02260
02261 static RPCStatus
02262 IDB_convertPrologue(Database *db, const Oid &oidcl, const Class *&cls,
02263 ClassConversion::Context *&conv_ctx)
02264 {
02265 conv_ctx = 0;
02266 if (!cls && oidcl.isValid() && !db->isOpeningState()) {
02267 Status status = ClassConversion::getClass_(db, oidcl, cls,
02268 conv_ctx);
02269 if (status) return rpcStatusMake(status);
02270
02271
02272
02273 return RPCSuccess;
02274 }
02275
02276 return RPCSuccess;
02277 }
02278
02279 static RPCStatus
02280 IDB_convertEpilogue(DbHandle *dbh, Database *db,
02281 const Class *cls,
02282 const ClassConversion::Context *conv_ctx,
02283 Data idr, ObjectHeader *xhdr, Size idr_psize,
02284 const eyedbsm::Oid *oid)
02285 {
02286 Size osize = xhdr->size;
02287
02288 xhdr->oid_cl = *cls->getOid().getOid();
02289 Size hdr_size = xhdr->size;
02290 xhdr->size = (xhdr->xinfo & IDB_XINFO_REMOVED) ? IDB_OBJ_HEAD_SIZE :
02291 idr_psize;
02292
02293 Offset offset = 0;
02294 Size size = xhdr->size;
02295 object_header_code(&idr, &offset, &size, xhdr);
02296
02297 if (xhdr->xinfo & IDB_XINFO_REMOVED)
02298 return RPCSuccess;
02299
02300 Status status = ClassConversion::convert(db, conv_ctx, idr, hdr_size);
02301 if (status) return rpcStatusMake(status);
02302
02303 if (!db->writeBackConvertedObjects())
02304 return RPCSuccess;
02305
02306
02307
02308
02309
02310
02311 IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("write object %s back\n", Oid(oid).toString()));
02312 eyedbsm::Status se_status;
02313 if (idr_psize != osize)
02314 {
02315 IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("... and change size from %d to %d!\n", osize, idr_psize));
02316 se_status = eyedbsm::objectSizeModify(dbh->sedbh, idr_psize, eyedbsm::False, oid);
02317 if (se_status)
02318 return rpcStatusMake_se(se_status);
02319 }
02320
02321 se_status = eyedbsm::objectWrite(dbh->sedbh, 0, xhdr->size, idr, oid);
02322
02323 if (se_status)
02324 return rpcStatusMake_se(se_status);
02325
02326 return RPCSuccess;
02327 }
02328
02329 RPCStatus
02330 IDB_objectReadLocal(DbHandle *dbh, Data idr, Data *pidr,
02331 short *pdspid, const eyedbsm::Oid *oid, ObjectHeader *phdr,
02332 LockMode lockmode, void **pcls)
02333 {
02334 Status status;
02335 RPCStatus rpc_status;
02336 ObjectHeader hdr;
02337 ObjectHeader *xhdr = (phdr ? phdr : &hdr);
02338 #define hdr xxxxx
02339 Database *db = (Database *)dbh->db;
02340 eyedbsm::Status se_status;
02341
02342 Offset offset = 0;
02343
02344 if (idr)
02345 object_header_decode(idr, &offset, xhdr);
02346 else
02347 xhdr->magic = 0;
02348
02349 char buf[IDB_OBJ_HEAD_SIZE];
02350
02351 if (!xhdr->magic) {
02352 Offset offset = 0;
02353 se_status =
02354 eyedbsm::objectRead(dbh->sedbh, 0, IDB_OBJ_HEAD_SIZE, buf,
02355 (eyedbsm::LockMode)lockmode, pdspid, 0, oid);
02356
02357 if (se_status)
02358 return rpcStatusMake_se(se_status);
02359
02360 if (!object_header_decode((Data)buf, &offset, xhdr))
02361 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectRead: invalid object_header");
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 }
02373
02374 const Class *cls = db->getSchema()->getClass(xhdr->oid_cl);
02375 ClassConversion::Context *conv_ctx;
02376 rpc_status = IDB_convertPrologue(db, xhdr->oid_cl, cls, conv_ctx);
02377 if (rpc_status) return rpc_status;
02378
02379 if (pcls)
02380 *(const Class **)pcls = cls;
02381
02382 Bool trig_man = IDBBOOL(!db->isOpeningState() && !db->getSchema()->getClass(*oid));
02383 if (trig_man)
02384 TRIGGER_MANAGE(db, Class::TrigLoadBefore_C, xhdr, 0, oid, cls);
02385
02386 Size idr_psize = 0;
02387 Size idr_vsize = 0;
02388 int objsize = IDB_getObjectSize(cls, &idr_psize, &idr_vsize, xhdr);
02389
02390 if (!idr) {
02391 Size objsize_x;
02392
02393 if (conv_ctx) {
02394 Size size = ClassConversion::computeSize(conv_ctx, xhdr->size);
02395 objsize_x = (size < objsize ? objsize : size);
02396 }
02397 else
02398 objsize_x = objsize;
02399
02400 idr = *pidr = (unsigned char *)malloc(objsize_x);
02401 assert(idr);
02402 memcpy(idr, buf, IDB_OBJ_HEAD_SIZE);
02403 }
02404
02405 if (xhdr->size > IDB_OBJ_HEAD_SIZE && !(xhdr->xinfo & IDB_XINFO_REMOVED))
02406 rpc_status =
02407 rpcStatusMake_se(eyedbsm::objectRead(dbh->sedbh, IDB_OBJ_HEAD_SIZE,
02408 xhdr->size - IDB_OBJ_HEAD_SIZE,
02409 idr + IDB_OBJ_HEAD_SIZE,
02410 (eyedbsm::LockMode)lockmode, 0, 0, oid));
02411 else
02412 rpc_status = RPCSuccess;
02413
02414 if (conv_ctx)
02415 rpc_status = IDB_convertEpilogue(dbh, db, cls, conv_ctx, idr, xhdr,
02416 idr_psize, oid);
02417
02418 if (!rpc_status)
02419 {
02420 if (trig_man)
02421 TRIGGER_MANAGE(db, Class::TrigLoadAfter_C, xhdr, idr, oid, cls);
02422
02423 if (phdr)
02424 {
02425 if (objsize > xhdr->size)
02426 {
02427 memset(idr + xhdr->size, 0, objsize - xhdr->size);
02428 xhdr->size = objsize;
02429 }
02430 }
02431 }
02432
02433 #undef hdr
02434 return rpc_status;
02435 }
02436
02437 RPCStatus
02438 IDB_objectRead(DbHandle *dbh, Data idr, Data *pidr, short *pdspid,
02439 const eyedbsm::Oid *oid, LockMode lockmode, void *xdata)
02440 {
02441 Status status;
02442 RPCStatus rpc_status;
02443 Offset offset;
02444 ObjectHeader hdr;
02445 rpc_ServerData *data = (rpc_ServerData *)xdata;
02446 Database *db = (Database *)dbh->db;
02447
02448 if (data) {
02449 data->status = rpc_BuffUsed;
02450 data->size = 0;
02451 }
02452
02453 offset = 0;
02454 if (idr)
02455 object_header_decode(idr, &offset, &hdr);
02456 else
02457 hdr.magic = 0;
02458
02459 if (!hdr.magic)
02460 {
02461 char buf[IDB_OBJ_HEAD_SIZE];
02462 Offset offset = 0;
02463 eyedbsm::Status se_status =
02464 eyedbsm::objectRead(dbh->sedbh, 0, IDB_OBJ_HEAD_SIZE, buf,
02465 (eyedbsm::LockMode)lockmode, pdspid, 0, oid);
02466
02467 if (se_status)
02468 return rpcStatusMake_se(se_status);
02469
02470 if (!object_header_decode((Data)buf, &offset, &hdr))
02471 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectRead: invalid object_header");
02472 }
02473
02474 const Class *cls = db->getSchema()->getClass(hdr.oid_cl);
02475 ClassConversion::Context *conv_ctx = 0;
02476 if (!cls) {
02477 rpc_status = IDB_convertPrologue(db, hdr.oid_cl, cls, conv_ctx);
02478 if (rpc_status) return rpc_status;
02479 }
02480
02481 TRIGGER_MANAGE(db, Class::TrigLoadBefore_C, &hdr, 0, oid, cls);
02482
02483 Size idr_psize = 0;
02484 int objsize = IDB_getObjectSize(cls, &idr_psize, 0, &hdr);
02485 Size minsize = (!conv_ctx ? idr_psize :
02486 ClassConversion::computeSize(conv_ctx, hdr.size));
02487
02488 rpc_status = IDB_instanceRead(dbh, idr, pidr, &hdr, lockmode, oid, xdata,
02489 minsize);
02490 if (!rpc_status && conv_ctx)
02491 rpc_status = IDB_convertEpilogue(dbh, db, cls, conv_ctx,
02492 (data ? (Data)data->data : idr),
02493 &hdr, idr_psize, oid);
02494
02495 if (!rpc_status)
02496 TRIGGER_MANAGE(db, Class::TrigLoadAfter_C, &hdr,
02497 (data ? (Data)data->data : idr), oid, cls);
02498
02499 return rpc_status;
02500 }
02501
02502 RPCStatus
02503 IDB_objectWrite(DbHandle *dbh, const Data idr, const eyedbsm::Oid *oid,
02504 void *xdata, Data *inv_data, void *xinv_data)
02505 {
02506 ObjectHeader hdr;
02507 Offset offset = 0;
02508 RPCStatus rpc_status;
02509 Database *db = (Database *)dbh->db;
02510
02511 CHECK_WRITE(db);
02512
02513 Oid toid(oid);
02514
02515 lock_data((Data *)&idr, xdata);
02516
02517 Bool new_ctx = InvOidContext::getContext();
02518
02519 IDB_LOG(IDB_LOG_OBJ_UPDATE, ("writing %s object\n", toid.toString()));
02520 if (!object_header_decode(idr, &offset, &hdr))
02521 {
02522 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02523 unlock_data(idr, xdata);
02524 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectWrite: invalid object_header");
02525 }
02526
02527 if (hdr.xinfo & IDB_XINFO_REMOVED)
02528 {
02529 IDB_LOG(IDB_LOG_OBJ_UPDATE, ("object %s already removed\n", toid.toString()));
02530 unlock_data(idr, xdata);
02531 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02532 return RPCSuccess;
02533 }
02534
02535 if (hdr.type == _Schema_Type)
02536 {
02537 unlock_data(idr, xdata);
02538 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02539 return rpcStatusMake(IDB_CANNOT_UPDATE_SCHEMA, "objectWrite: cannot update a schema");
02540 }
02541
02542 const Class *cls = db->getSchema()->getClass(hdr.oid_cl);
02543 TRIGGER_MANAGE(db, Class::TrigUpdateBefore_C, &hdr, idr, oid,
02544 cls);
02545
02546 Oid moid(hdr.oid_cl);
02547 const Oid &mprot_oid = ((Database *)dbh->db)->getMprotOid();
02548
02549 if (mprot_oid.isValid() && moid.compare(mprot_oid))
02550 rpc_status = IDB_protectionWrite(dbh, idr, &hdr, oid, xdata);
02551 else if (eyedb_is_type(hdr, _Class_Type))
02552 rpc_status = IDB_classWrite(dbh, idr, &hdr, oid, xdata);
02553 else if (eyedb_is_type(hdr, _Struct_Type) ||
02554 eyedb_is_type(hdr, _Union_Type))
02555 rpc_status = IDB_agregatWrite(dbh, idr, &hdr, oid, xdata);
02556 else if (eyedb_is_type(hdr, _Collection_Type))
02557 rpc_status = IDB_collectionWrite(dbh, idr, &hdr, oid, xdata);
02558 else
02559 rpc_status = IDB_instanceWrite(dbh, idr, &hdr, oid, xdata);
02560
02561 if (!rpc_status)
02562 TRIGGER_MANAGE(db, Class::TrigUpdateAfter_C, &hdr, idr, oid, cls);
02563
02564 InvOidContext::releaseContext(new_ctx, inv_data, xinv_data);
02565 unlock_data(idr, xdata);
02566 if (!rpc_status)
02567 IDB_LOG(IDB_LOG_OBJ_UPDATE, ("object %s wrote\n", toid.toString()));
02568 return rpc_status;
02569 }
02570
02571 RPCStatus
02572 IDB_objectHeaderRead(DbHandle *dbh, const eyedbsm::Oid *oid, ObjectHeader *hdr)
02573 {
02574 eyedbsm::Status status;
02575 char buf[IDB_OBJ_HEAD_SIZE];
02576 Offset offset = 0;
02577
02578 status = eyedbsm::objectRead(dbh->sedbh, 0, IDB_OBJ_HEAD_SIZE, buf, eyedbsm::DefaultLock, 0, 0, oid);
02579
02580 if (status == eyedbsm::Success) {
02581 if (!object_header_decode((Data)buf, &offset, hdr))
02582 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectHeaderRead: invalid object_header");
02583 }
02584
02585 return rpcStatusMake_se(status);
02586 }
02587
02588 RPCStatus
02589 IDB_objectHeaderWrite(DbHandle *dbh, const eyedbsm::Oid *oid, const ObjectHeader *hdr)
02590 {
02591 CHECK_WRITE((Database *)dbh->db);
02592
02593 eyedbsm::Status status;
02594 char *buf = NULL;
02595 Offset offset = 0;
02596 Size alloc_size = 0;
02597
02598 if (!object_header_code((Data *)&buf, &offset, &alloc_size, hdr))
02599 {
02600 free(buf);
02601 return rpcStatusMake(IDB_INVALID_OBJECT_HEADER, "objectHeaderRead: invalid object_header");
02602 }
02603
02604 status = eyedbsm::objectWrite(dbh->sedbh, 0, IDB_OBJ_HEAD_SIZE, buf, oid);
02605
02606 free(buf);
02607 return rpcStatusMake_se(status);
02608 }
02609
02610 RPCStatus
02611 IDB_objectSizeModify(DbHandle *dbh, unsigned int size, const eyedbsm::Oid *oid)
02612 {
02613 CHECK_WRITE((Database *)dbh->db);
02614
02615 ObjectHeader hdr;
02616 eyedbsm::Status status;
02617 eyedbsm::DbHandle *sedbh = dbh->sedbh;
02618
02619 if ((status = eyedbsm::objectSizeModify(sedbh, size, eyedbsm::True, oid)) ==
02620 eyedbsm::Success) {
02621 #ifdef E_XDR
02622 eyedblib::int32 size_x = h2x_32(size);
02623 #else
02624 eyedblib::int32 size_x = size;
02625 #endif
02626 status = eyedbsm::objectWrite(sedbh, IDB_OBJ_HEAD_SIZE_INDEX,
02627 IDB_OBJ_HEAD_SIZE_SIZE, &size_x, oid);
02628 }
02629 return rpcStatusMake_se(status);
02630 }
02631
02632 RPCStatus
02633 IDB_objectCheck(DbHandle *dbh, const eyedbsm::Oid *oid, int *type,
02634 eyedbsm::Oid *cls_oid)
02635 {
02636 ObjectHeader hdr;
02637 RPCStatus rpc_status = IDB_objectHeaderRead(dbh, oid, &hdr);
02638
02639 if (rpc_status != RPCSuccess)
02640 {
02641 *type = 0;
02642 return rpc_status;
02643 }
02644
02645
02646
02647 #if 0
02648 if (ObjectPeer::isRemoved(hdr))
02649 {
02650 Oid xoid(oid);
02651 return rpcStatusMake(Exception::make(IDB_ERROR,
02652 "object '%s' does not exist "
02653 "anymore",
02654 xoid.getString()));
02655 }
02656 #endif
02657
02658 *type = hdr.type;
02659
02660 Database *db = (Database *)dbh->db;
02661 Oid cloid(hdr.oid_cl);
02662
02663 if (cloid.isValid() && !db->getSchema()->getClass(cloid)) {
02664
02665 ClassConversion::Context *conv_ctx = 0;
02666 const Class *cls = 0;
02667 RPCStatus rpc_status;
02668 rpc_status = IDB_convertPrologue(db, hdr.oid_cl, cls, conv_ctx);
02669 if (rpc_status) return rpc_status;
02670 if (!cls)
02671 return rpcStatusMake
02672 (Exception::make(IDB_ERROR, "internal conversion error: "
02673 "cannot find old class %s",
02674 Oid(hdr.oid_cl).toString()));
02675 Size idr_psize = 0;
02676 int objsize = IDB_getObjectSize(cls, &idr_psize, 0, &hdr);
02677 Size minsize = (!conv_ctx ? idr_psize :
02678 ClassConversion::computeSize(conv_ctx, hdr.size));
02679
02680 Data idr = 0;
02681 rpc_status = IDB_instanceRead(dbh, 0, &idr, &hdr, LockS, oid, 0,
02682 minsize);
02683 if (rpc_status) {
02684 free(idr);
02685 return rpc_status;
02686 }
02687
02688 rpc_status = IDB_convertEpilogue(dbh, db, cls, conv_ctx, idr, &hdr,
02689 idr_psize, oid);
02690
02691 free(idr);
02692 *cls_oid = *cls->getOid().getOid();
02693 return rpc_status;
02694 }
02695
02696 *cls_oid = hdr.oid_cl;
02697 return RPCSuccess;
02698 }
02699
02700 RPCStatus
02701 IDB_objectCheckAccess(DbHandle *dbh, Bool write, const eyedbsm::Oid *oid,
02702 Bool *access)
02703 {
02704 eyedbsm::Status se_status;
02705 eyedbsm::Boolean xaccess;
02706 se_status = eyedbsm::objectCheckAccess(dbh->sedbh, write ? eyedbsm::True : eyedbsm::False,
02707 oid, &xaccess);
02708 if (se_status)
02709 {
02710
02711 return rpcStatusMake_se(se_status);
02712 }
02713
02714 *access = (xaccess ? True : False);
02715 return RPCSuccess;
02716 }
02717
02718 RPCStatus
02719 IDB_oidMake(DbHandle *dbh, ObjectHeader *hdr, short dspid, unsigned int size,
02720 eyedbsm::Oid *oid)
02721 {
02722 CHECK_WRITE((Database *)dbh->db);
02723
02724 RPCStatus rpc_status;
02725
02726 Database *db = (Database *)dbh->db;
02727 const Class *cls = db->getSchema()->getClass(hdr->oid_cl);
02728 rpc_status = getDspid(db, cls, dspid);
02729 if (rpc_status)
02730 return rpc_status;
02731
02732
02733
02734
02735 rpc_status = rpcStatusMake_se(eyedbsm::objectCreate(dbh->sedbh,
02736 eyedbsm::ObjectZero,
02737 size, dspid, oid));
02738
02739 if (rpc_status)
02740 return rpc_status;
02741
02742 db->addMarkCreated(Oid(*oid));
02743
02744 unsigned char temp[IDB_OBJ_HEAD_SIZE];
02745
02746 Offset offset = 0;
02747 Size alloc_size = sizeof(temp);
02748 Data idr = temp;
02749 object_header_code(&idr, &offset, &alloc_size, hdr);
02750
02751 rpc_status = rpcStatusMake_se
02752 (eyedbsm::objectWrite(dbh->sedbh, 0, IDB_OBJ_HEAD_SIZE, temp, oid));
02753
02754 return rpc_status;
02755 }
02756
02757
02758
02759 RPCStatus
02760 IDB_dataCreate(DbHandle *dbh, short dspid, unsigned int size, const Data idr,
02761 eyedbsm::Oid *oid, void *xdata)
02762 {
02763 CHECK_WRITE((Database *)dbh->db);
02764 eyedbsm::Status status;
02765
02766 lock_data((Data *)&idr, xdata);
02767
02768 status = eyedbsm::objectCreate(dbh->sedbh, idr, size, dspid, oid);
02769 if (!status)
02770 ((Database *)dbh->db)->addMarkCreated(Oid(*oid));
02771
02772 unlock_data(idr, xdata);
02773 return rpcStatusMake_se(status);
02774 }
02775
02776 RPCStatus
02777 IDB_dataDelete(DbHandle *dbh, const eyedbsm::Oid *oid)
02778 {
02779 CHECK_WRITE((Database *)dbh->db);
02780 return rpcStatusMake_se(eyedbsm::objectDelete(dbh->sedbh, oid));
02781 }
02782
02783 RPCStatus
02784 IDB_dataRead(DbHandle *dbh, int offset, unsigned int size, Data idr, short *pdspid, const eyedbsm::Oid *oid, void *xdata)
02785 {
02786 eyedbsm::Status status;
02787 rpc_ServerData *data = (rpc_ServerData *)xdata;
02788
02789 if (data)
02790 {
02791 if (size <= data->buff_size)
02792 data->status = rpc_BuffUsed;
02793 else
02794 {
02795 data->status = rpc_TempDataUsed;
02796 data->data = malloc(size);
02797 }
02798
02799 status = eyedbsm::objectRead(dbh->sedbh, offset, size, data->data, eyedbsm::DefaultLock,
02800 pdspid, 0, oid);
02801
02802 if (status == eyedbsm::Success)
02803 data->size = size;
02804 else
02805 data->size = 0;
02806 }
02807 else
02808 status = eyedbsm::objectRead(dbh->sedbh, offset, size, idr, eyedbsm::DefaultLock, pdspid, 0, oid);
02809
02810 return rpcStatusMake_se(status);
02811 }
02812
02813 RPCStatus
02814 IDB_dataWrite(DbHandle *dbh, int offset, unsigned int size, const Data idr, const eyedbsm::Oid *oid, void *xdata)
02815 {
02816 CHECK_WRITE((Database *)dbh->db);
02817
02818 eyedbsm::Status status;
02819 lock_data((Data *)&idr, xdata);
02820
02821 status = eyedbsm::objectWrite(dbh->sedbh, offset, size, idr, oid);
02822
02823 unlock_data(idr, xdata);
02824 return rpcStatusMake_se(status);
02825 }
02826
02827 RPCStatus
02828 IDB_dataSizeGet(DbHandle *dbh, const eyedbsm::Oid *oid, unsigned int *psize)
02829 {
02830 return rpcStatusMake_se(eyedbsm::objectSizeGet(dbh->sedbh, psize, eyedbsm::DefaultLock, oid));
02831 }
02832
02833 RPCStatus
02834 IDB_dataSizeModify(DbHandle *dbh, unsigned int size, const eyedbsm::Oid *oid)
02835 {
02836 return rpcStatusMake_se(eyedbsm::objectSizeModify(dbh->sedbh, size, eyedbsm::True,
02837 oid));
02838 }
02839
02840
02841 static RPCStatus
02842 IDB_VDgetAttribute(Database *db, const eyedbsm::Oid *oid_cl, int num,
02843 const char *fname, Attribute **pitem)
02844 {
02845 Class *cls = db->getSchema()->getClass(oid_cl);
02846
02847 if (!cls)
02848 return rpcStatusMake(IDB_FATAL_ERROR,
02849 "class '%s' not found in %s()",
02850 OidGetString(oid_cl), fname);
02851
02852 if (!cls->asAgregatClass())
02853 return rpcStatusMake(IDB_FATAL_ERROR,
02854 "class '%s' is not a agregat_class in %s()",
02855 cls->getName(), fname);
02856
02857 unsigned int count;
02858 const Attribute **items = ((AgregatClass *)cls)->getAttributes(count);
02859 if (num < 0 || num >= count)
02860 return rpcStatusMake(IDB_FATAL_ERROR, "invalid item number `%d' in for class '%s' in %s()",
02861 num, cls->getName(), fname);
02862
02863 *pitem = (Attribute *)items[num];
02864 return RPCSuccess;
02865 }
02866
02867 static RPCStatus
02868 IDB_VDmakeIDR(DbHandle *dbh, Attribute *item, const eyedbsm::Oid *oid,
02869 Data *pidr, int *count, int &offset)
02870 {
02871 eyedbsm::Status se_status;
02872 unsigned int size;
02873
02874 se_status = eyedbsm::objectSizeGet(dbh->sedbh, &size, eyedbsm::DefaultLock, oid);
02875
02876 if (se_status)
02877 return rpcStatusMake_se(se_status);
02878
02879 if (!size)
02880 {
02881 *pidr = 0;
02882 return RPCSuccess;
02883 }
02884
02885 *pidr = (unsigned char *)malloc(size);
02886 se_status = eyedbsm::objectRead(dbh->sedbh, 0, size, *pidr, eyedbsm::DefaultLock, 0, 0, oid);
02887
02888 if (se_status)
02889 {
02890 free(*pidr);
02891 return rpcStatusMake_se(se_status);
02892 }
02893
02894 Size idr_item_psize, idr_psize, idr_inisize;
02895 Offset off;
02896 item->getPersistentIDR(off, idr_item_psize, idr_psize, idr_inisize);
02897
02898 offset = (int)off;
02899 *count = size/idr_item_psize;
02900
02901 return RPCSuccess;
02902 }
02903
02904 RPCStatus IDB_VDcheckSize(Attribute *item, int count, unsigned int size,
02905 int &offset)
02906 {
02907 Size idr_item_psize, idr_psize, idr_inisize;
02908 Offset off;
02909 item->getPersistentIDR(off, idr_item_psize, idr_psize, idr_inisize);
02910
02911 offset = (int)off;
02912 return RPCSuccess;
02913 }
02914
02915 RPCStatus
02916 IDB_VDdataCreate(DbHandle *dbh, short dspid, const eyedbsm::Oid *actual_oid_cl,
02917 const eyedbsm::Oid *oid_cl, int num,
02918 int count, int size, const Data idr,
02919 const eyedbsm::Oid *agr_oid, eyedbsm::Oid *data_oid,
02920 const Data idx_data, int idx_size, void *xdata,
02921 void *xidx_data)
02922 {
02923 Database *db = (Database *)dbh->db;
02924 Status status;
02925 RPCStatus rpc_status;
02926 Attribute *item;
02927
02928 rpc_status = IDB_VDgetAttribute(db, oid_cl, num, "VDdataCreate", &item);
02929
02930 if (rpc_status)
02931 return rpc_status;
02932
02933 int offset;
02934 rpc_status = IDB_VDcheckSize(item, count, size, offset);
02935
02936 if (rpc_status)
02937 return rpc_status;
02938
02939 lock_data((Data *)&idr, xdata);
02940 lock_data((Data *)&idx_data, xidx_data);
02941
02942 rpc_status = IDB_dataCreate(dbh, dspid, size, idr, data_oid, 0);
02943
02944 if (rpc_status) {
02945 unlock_data(idx_data, xidx_data);
02946 unlock_data(idr, xdata);
02947 return rpc_status;
02948 }
02949
02950 Oid _agr_oid(agr_oid);
02951 Oid moid(actual_oid_cl);
02952 AttrIdxContext idx_ctx(idx_data, idx_size);
02953
02954 status = item->createIndexEntry(db, idr, &_agr_oid, &moid, -offset,
02955 count, size, 0, False, idx_ctx);
02956
02957 if (status) {
02958 idx_ctx.realizeIdxOP(False);
02959 unlock_data(idr, xdata);
02960 unlock_data(idx_data, xidx_data);
02961 return rpcStatusMake(status);
02962 }
02963
02964 status = idx_ctx.realizeIdxOP(True);
02965 unlock_data(idr, xdata);
02966 unlock_data(idx_data, xidx_data);
02967 return rpcStatusMake(status);
02968 }
02969
02970 RPCStatus
02971 IDB_VDdataWrite(DbHandle *dbh, const eyedbsm::Oid *actual_oid_cl,
02972 const eyedbsm::Oid *oid_cl, int num,
02973 int count, unsigned int size, const Data idr, const eyedbsm::Oid *agr_oid,
02974 const eyedbsm::Oid *data_oid,
02975 const Data idx_data, int idx_size, void *xdata,
02976 void *xidx_data)
02977 {
02978 Database *db = (Database *)dbh->db;
02979 RPCStatus rpc_status;
02980 Status status;
02981 Attribute *item;
02982
02983 rpc_status = IDB_VDgetAttribute(db, oid_cl, num, "VDdataWrite", &item);
02984
02985 if (rpc_status)
02986 return rpc_status;
02987
02988 int offset;
02989 rpc_status = IDB_VDcheckSize(item, count, size, offset);
02990
02991 if (rpc_status)
02992 return rpc_status;
02993
02994 lock_data((Data *)&idr, xdata);
02995 lock_data((Data *)&idx_data, xidx_data);
02996
02997 Oid _data_oid(data_oid);
02998 Oid _agr_oid(agr_oid);
02999
03000 Oid moid(actual_oid_cl);
03001 AttrIdxContext idx_ctx(idx_data, idx_size);
03002
03003 status = item->updateIndexEntry(db, idr, &_agr_oid, &moid, -offset,
03004 &_data_oid, count, 0, False, idx_ctx);
03005
03006 if (status) {
03007 idx_ctx.realizeIdxOP(False);
03008 unlock_data(idr, xdata);
03009 unlock_data(idx_data, xidx_data);
03010 return rpcStatusMake(status);
03011 }
03012
03013 status = idx_ctx.realizeIdxOP(True);
03014 if (status) {
03015 unlock_data(idr, xdata);
03016 unlock_data(idx_data, xidx_data);
03017 return rpcStatusMake(status);
03018 }
03019
03020 rpc_status = IDB_dataWrite(dbh, 0, size, idr, data_oid, 0);
03021
03022 unlock_data(idr, xdata);
03023 unlock_data(idx_data, xidx_data);
03024
03025 return rpc_status;
03026 }
03027
03028 RPCStatus
03029 IDB_VDdataDelete(DbHandle *dbh, const eyedbsm::Oid *actual_oid_cl,
03030 const eyedbsm::Oid *oid_cl, int num,
03031 const eyedbsm::Oid *agr_oid, const eyedbsm::Oid *data_oid,
03032 const Data idx_data, int idx_size, void *xidx_data)
03033 {
03034 Database *db = (Database *)dbh->db;
03035 RPCStatus rpc_status;
03036 Status status;
03037 Attribute *item;
03038 int count;
03039
03040 rpc_status = IDB_VDgetAttribute(db, oid_cl, num, "VDdataDelete", &item);
03041
03042 if (rpc_status)
03043 return rpc_status;
03044
03045 Data idr;
03046 int offset;
03047 rpc_status = IDB_VDmakeIDR(dbh, item, data_oid, &idr, &count, offset);
03048
03049 if (rpc_status)
03050 return rpc_status;
03051
03052 lock_data((Data *)&idx_data, xidx_data);
03053
03054 Oid _data_oid(data_oid);
03055 Oid _agr_oid(agr_oid);
03056 Oid moid(actual_oid_cl);
03057 AttrIdxContext idx_ctx(idx_data, idx_size);
03058
03059 status = item->removeIndexEntry(db, idr, &_agr_oid, &moid, -offset,
03060 &_data_oid, count, 0, False, idx_ctx);
03061
03062
03063 if (status) {
03064 idx_ctx.realizeIdxOP(False);
03065 free(idr);
03066 unlock_data(idx_data, xidx_data);
03067 return rpcStatusMake(status);
03068 }
03069
03070 status = idx_ctx.realizeIdxOP(True);
03071 if (status) {
03072 free(idr);
03073 unlock_data(idx_data, xidx_data);
03074 return rpcStatusMake(status);
03075 }
03076
03077 free(idr);
03078 unlock_data(idx_data, xidx_data);
03079
03080 if (status)
03081 return rpcStatusMake(status);
03082
03083 return IDB_dataDelete(dbh, data_oid);
03084 }
03085
03086 RPCStatus
03087 IDB_schemaComplete(DbHandle *dbh, const char *schname)
03088 {
03089 CHECK_WRITE((Database *)dbh->db);
03090
03091 Status status;
03092 RPCStatus rpc_status;
03093 Database *db = (Database *)dbh->db;
03094 Schema *sch = db->getSchema();
03095
03096 if (status = sch->deferredCollRegisterRealize(dbh))
03097 return rpcStatusMake(status);
03098
03099 if (!*schname)
03100 return rpcStatusMake(IDB_ERROR, "schema name must be set");
03101
03102 sch->setName(schname);
03103
03104 if (sch->getOid().isValid())
03105 {
03106 char name[IDB_SCH_NAME_SIZE];
03107 unsigned char *data = (unsigned char *)name;
03108 Offset start = 0;
03109 Size size = sizeof name;
03110 string_code(&data, &start, &size, schname);
03111
03112 eyedbsm::Status se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_SCH_NAME_INDEX,
03113 IDB_SCH_NAME_SIZE,
03114 name, sch->getOid().getOid());
03115 if (se_status)
03116 return rpcStatusMake_se(se_status);
03117 }
03118
03119 return rpcStatusMake(sch->complete(True, True));
03120 }
03121
03122
03123 RPCStatus
03124 IDB_attributeIndexCreate(DbHandle *dbh, const eyedbsm::Oid *cloid, int num,
03125 int mode, eyedbsm::Oid *multi_idx_oid,
03126 Data idx_ctx_data, Size size, void *xdata)
03127 {
03128 #if 1
03129 assert(0);
03130 return RPCSuccess;
03131 #else
03132 Database *db = (Database *)dbh->db;
03133 Class *cl = db->getSchema()->getClass(*cloid);
03134 Attribute *attr = (Attribute *)cl->asAgregatClass()->getAttribute(num);
03135
03136 if (!attr)
03137 return rpcStatusMake(IDB_ERROR, "cannot find attribute #%d "
03138 "in class %s\n", num, cl->getName());
03139
03140 lock_data((Data *)&idx_ctx_data, xdata);
03141
03142 AttrIdxContext idx_ctx(idx_ctx_data, size);
03143 Oid idx_oid(multi_idx_oid);
03144 Status s = attr->createIndex_realize(db, mode, cl, idx_ctx,
03145 idx_oid);
03146
03147 if (s)
03148 {
03149 unlock_data(idx_ctx_data, xdata);
03150 return rpcStatusMake(s);
03151 }
03152
03153 unlock_data(idx_ctx_data, xdata);
03154 return RPCSuccess;
03155 #endif
03156 }
03157
03158 RPCStatus
03159 IDB_attributeIndexRemove(DbHandle *dbh, const eyedbsm::Oid *cloid, int num,
03160 int mode, Data idx_ctx_data, Size size,
03161 void *xdata)
03162 {
03163 #if 1
03164 assert(0);
03165 return RPCSuccess;
03166 #else
03167 Database *db = (Database *)dbh->db;
03168 Class *cl = db->getSchema()->getClass(*cloid);
03169 Attribute *attr = (Attribute *)cl->asAgregatClass()->getAttribute(num);
03170 if (!attr)
03171 return rpcStatusMake(IDB_ERROR, "cannot find attribute #%d in class %s\n",
03172 num, cl->getName());
03173 lock_data((Data *)&idx_ctx_data, xdata);
03174
03175 AttrIdxContext idx_ctx(idx_ctx_data, size);
03176
03177 Status s =
03178 (attr->destroyIndex(db, idx_ctx,
03179 (Attribute::AttributeIndexMode)mode));
03180
03181 unlock_data(idx_ctx_data, xdata);
03182 return rpcStatusMake(s);
03183 #endif
03184 }
03185
03186 char *attrcomp_delete_ud = "eyedb:attr_comp_delete:reentrant";
03187
03188 RPCStatus
03189 IDB_attrCompPrologue(Database *db, const eyedbsm::Oid * objoid,
03190 const Class *&cls,
03191 AttributeComponent *&attr_comp,
03192 const Attribute *&attr, Bool check,
03193 AttrIdxContext *idx_ctx = 0,
03194 AttributeComponent **oattr_comp = 0)
03195 {
03196 Oid oid(*objoid);
03197 Status s;
03198
03199 if (oattr_comp) {
03200 s = db->loadObject(oid, (Object *&)*oattr_comp);
03201 if (s) return rpcStatusMake(s);
03202 }
03203
03204 s = db->reloadObject(oid, (Object *&)attr_comp);
03205 if (s) return rpcStatusMake(s);
03206
03207 if (attr_comp->isRemoved())
03208 return rpcStatusMake(IDB_ERROR, "attribute component %s is removed",
03209 oid.toString());
03210
03211 s = Attribute::checkAttrPath(db->getSchema(), cls, attr,
03212 attr_comp->getAttrpath().c_str(), idx_ctx);
03213 if (s) return rpcStatusMake(s);
03214
03215 if (!attr->isIndirect() && !attr->isBasicOrEnum() &&
03216 !attr->getClass()->asCollectionClass())
03217 return rpcStatusMake(Exception::make
03218 (IDB_ERROR,
03219 "attribute path '%s' is not indirect neither "
03220 "basic literal", attr_comp->getAttrpath().c_str()));
03221
03222
03223
03224
03225
03226 if (!check)
03227 return RPCSuccess;
03228
03229
03230
03231 if (attr_comp->asIndex() &&
03232 attr_comp->asIndex()->getImplHintsCount() > IDB_IDX_MAGIC_HINTS &&
03233 attr_comp->asIndex()->getImplHints(IDB_IDX_MAGIC_HINTS) ==
03234 IDB_IDX_MAGIC_HINTS_VALUE) {
03235 return RPCSuccess;
03236 }
03237
03238 AttributeComponent *cattr_comp;
03239 s = attr_comp->find(db, cls->getParent(), cattr_comp);
03240 if (s) return rpcStatusMake(s);
03241
03242
03243 if (cattr_comp && cattr_comp->getPropagate()) {
03244 return rpcStatusMake
03245 (Exception::make(IDB_ERROR,
03246 "cannot delete component %s because "
03247 "of propagation property: "
03248 "must delete component "
03249 "of parent class first",
03250 attr_comp->getName().c_str()));
03251 }
03252
03253 return RPCSuccess;
03254 }
03255
03256 RPCStatus
03257 IDB_attrCompCheckInClass(AttributeComponent *comp, const Class *cls,
03258 Bool &found)
03259 {
03260 AttributeComponent *xcomp;
03261 Status s = cls->getAttrComp(comp->getName().c_str(), xcomp);
03262 if (s) return rpcStatusMake(s);
03263
03264 if (xcomp) {
03265
03266
03267
03268
03269 found = True;
03270 return RPCSuccess;
03271 }
03272
03273
03274
03275
03276
03277
03278
03279 found = False;
03280 return RPCSuccess;
03281 }
03282
03283 RPCStatus
03284 IDB_attrCompPropagate(Database *db, const Class *cls,
03285 AttributeComponent *attr_comp, Bool create)
03286 {
03287
03288 if (!attr_comp->getPropagate())
03289 return RPCSuccess;
03290
03291
03292 Class **subclasses;
03293 unsigned int subclass_cnt;
03294 Status s = cls->getSubClasses(subclasses, subclass_cnt);
03295 if (s) return rpcStatusMake(s);
03296
03297 for (int i = 0; i < subclass_cnt; i++) {
03298 if (!subclasses[i]->getParent()->compare(cls)) continue;
03299 AttributeComponent *cattr_comp;
03300 if (create) {
03301 cattr_comp = attr_comp->xclone(db, subclasses[i]);
03302 s = cattr_comp->store();
03303 }
03304 else {
03305 s = attr_comp->find(db, subclasses[i], cattr_comp);
03306 if (s) return rpcStatusMake(s);
03307 if (!cattr_comp)
03308 return rpcStatusMake
03309 (Exception::make(IDB_ERROR, "attribute component propagation "
03310 "removing internal error: component %s does "
03311 "not exist in class %s",
03312 attr_comp->getName().c_str(),
03313 subclasses[i]->getName()));
03314
03315 assert(cattr_comp);
03316 cattr_comp->setUserData(attrcomp_delete_ud, (void *)1);
03317 s = cattr_comp->remove();
03318 }
03319 if (s) return rpcStatusMake(s);
03320 }
03321
03322 return RPCSuccess;
03323 }
03324
03325 RPCStatus
03326 IDB_attrCompPropagate(Database *db, Class *cls, Bool skipIfFound)
03327 {
03328 Class *parent;
03329 Status status = cls->getParent(db, parent);
03330 if (status) return rpcStatusMake(status);
03331 if (!parent)
03332 return RPCSuccess;
03333
03334 const LinkedList *complist;
03335 status = parent->getAttrCompList(complist);
03336 if (status) return rpcStatusMake(status);
03337 LinkedListCursor c(complist);
03338 AttributeComponent *comp;
03339 while (c.getNext((void *&)comp)) {
03340 if (comp->getPropagate()) {
03341 comp = comp->xclone(db, cls);
03342
03343 if (skipIfFound) {
03344 Bool found;
03345 RPCStatus rpc_status = IDB_attrCompCheckInClass(comp, cls, found);
03346 if (rpc_status) return rpc_status;
03347
03348 if (found) {
03349 comp->release();
03350 continue;
03351 }
03352 }
03353
03354 status = comp->store();
03355 if (status) {
03356 comp->release();
03357 return rpcStatusMake(status);
03358 }
03359 }
03360 }
03361
03362 return RPCSuccess;
03363 }
03364
03365 extern eyedbsm::Status
03366 hash_key(const void *key, unsigned int len, void *hash_data, unsigned int &x);
03367
03368
03369
03370
03371 extern char index_backend[];
03372
03373 RPCStatus
03374 IDB_indexCreate(DbHandle * dbh, bool index_move, const eyedbsm::Oid * objoid)
03375 {
03376 Database *db = (Database *)dbh->db;
03377 AttrIdxContext idx_ctx;
03378 AttributeComponent *oattr_comp, *attr_comp;
03379 const Attribute *attr;
03380
03381 const Class *cls;
03382 RPCStatus rpc_status = IDB_attrCompPrologue(db, objoid, cls,
03383 attr_comp, attr, False,
03384 &idx_ctx, &oattr_comp);
03385 if (rpc_status) return rpc_status;
03386 ObjectReleaser _(attr_comp);
03387 Index *idx = attr_comp->asIndex();
03388
03389 #ifdef REIMPL_TRACE
03390 printf("INDEX_CREATE(%s, %s, oid=%s, idxoid=%s, dspid=%d)\n",
03391 attr_comp->getAttrpath(), cls->getName(), Oid(objoid).toString(),
03392 idx->getIdxOid().toString(),
03393 idx->getDspid());
03394 #endif
03395
03396 if (!idx->getIdxOid().isValid()) {
03397 Status s = attr->addComponent(db, idx);
03398 if (s) return rpcStatusMake(s);
03399 s = attr->updateIndexEntries(db, idx_ctx);
03400 if (s) return rpcStatusMake(s);
03401 return IDB_attrCompPropagate(db, cls, idx, True);
03402 }
03403
03404 Oid newoid;
03405 eyedbsm::Status s;
03406
03407 #ifdef REIMPL_TRACE
03408 printf("Server: INDEX reimplementation process\n");
03409 #endif
03410 eyedbsm::Idx *seidx = 0;
03411 s = eyedbsm::Idx::make(dbh->sedbh, *idx->getIdxOid().getOid(), seidx);
03412 if (s)
03413 return rpcStatusMake_se(s);
03414
03415 Bool swap = False;
03416
03417 if (index_move) {
03418
03419 if (idx->asBTreeIndex()) {
03420 s = seidx->asBIdx()->move(idx->getDspid(), *newoid.getOid());
03421 }
03422 else if (idx->asHashIndex()) {
03423 HashIndex *hidx = idx->asHashIndex();
03424 BEMethod_C *mth = hidx->getHashMethod();
03425 s = seidx->asHIdx()->move(idx->getDspid(), *newoid.getOid(), (mth ? hash_key : 0), mth);
03426 }
03427 }
03428 else if (idx->asHashIndex()) {
03429 printf("Index reimplementing...\n");
03430 if (seidx->asBIdx())
03431 swap = True;
03432 HashIndex *hidx = idx->asHashIndex();
03433 int impl_hints_cnt = eyedbsm::HIdxImplHintsCount;
03434 int impl_hints[eyedbsm::HIdxImplHintsCount];
03435 int cnt = hidx->getImplHintsCount();
03436 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
03437 for (int i = 0; i < cnt; i++)
03438 impl_hints[i] = hidx->getImplHints(i);
03439 #ifdef REIMPL_TRACE
03440 printf("Server: reimplementing HASH INDEX %s new keycount = %d\n",
03441 Oid(seidx->oid()).toString(), hidx->getKeyCount());
03442 #endif
03443 BEMethod_C *mth = hidx->getHashMethod();
03444 s = seidx->reimplementToHash(*newoid.getOid(), hidx->getKeyCount(), 0,
03445 hidx->getDspid(),
03446 impl_hints, impl_hints_cnt,
03447 (mth ? hash_key : 0), mth);
03448 }
03449 else {
03450 if (seidx->asHIdx())
03451 swap = True;
03452 BTreeIndex *bidx = idx->asBTreeIndex();
03453 #ifdef REIMPL_TRACE
03454 printf("Server: reimplementing BTREE INDEX %s\n", Oid(seidx->oid()).toString());
03455 #endif
03456 s = seidx->reimplementToBTree(*newoid.getOid(), bidx->getDegree(), bidx->getDspid());
03457 }
03458
03459 delete seidx;
03460
03461 if (!s) {
03462 Status status = idx->report(dbh->sedbh, newoid);
03463 if (status) return rpcStatusMake(status);
03464 }
03465
03466 if (!s) {
03467 void *ud = idx->setUserData(index_backend, AnyUserData);
03468 idx->setIdxOid(newoid);
03469 idx->idx = 0;
03470 if (swap) {
03471 Status st = attr->addComponent(db, idx);
03472 if (st) return rpcStatusMake(st);
03473 }
03474
03475 rpc_status = rpcStatusMake(idx->store());
03476 idx->setUserData(index_backend, ud);
03477 return rpc_status;
03478 }
03479
03480 return rpcStatusMake_se(s);
03481 }
03482
03483 RPCStatus
03484 IDB_indexRemove(DbHandle * dbh, const eyedbsm::Oid * objoid, int reentrant)
03485 {
03486 Database *db = (Database *)dbh->db;
03487 AttributeComponent *attr_comp;
03488 const Attribute *attr;
03489
03490 const Class *cls;
03491 RPCStatus rpc_status = IDB_attrCompPrologue(db, objoid, cls,
03492 attr_comp, attr,
03493 IDBBOOL(!reentrant));
03494 if (rpc_status) return rpc_status;
03495
03496
03497
03498
03499
03500
03501 ObjectReleaser _(attr_comp);
03502
03503 Status s = attr->rmvComponent(db, attr_comp);
03504 if (s) return rpcStatusMake(s);
03505
03506 s = attr->destroyIndex(db, (Index *)attr_comp);
03507 if (s) return rpcStatusMake(s);
03508
03509 return IDB_attrCompPropagate(db, cls, attr_comp, False);
03510
03511 }
03512
03513 RPCStatus
03514 IDB_constraintCreate(DbHandle * dbh, const eyedbsm::Oid * objoid)
03515 {
03516 Database *db = (Database *)dbh->db;
03517 AttrIdxContext idx_ctx;
03518 AttributeComponent *attr_comp;
03519 const Attribute *attr;
03520
03521 const Class *cls;
03522 RPCStatus rpc_status = IDB_attrCompPrologue(db, objoid, cls,
03523 attr_comp,
03524 attr, False);
03525 if (rpc_status) return rpc_status;
03526
03527
03528
03529
03530 ObjectReleaser _(attr_comp);
03531
03532 if (attr_comp->asCollAttrImpl()) {
03533 if (!attr->getClass()->asCollectionClass() || attr->isIndirect())
03534 return rpcStatusMake(IDB_ERROR,
03535 "attribute path %s: "
03536 "a collection implementation can be tied "
03537 "only to a literal collection attribute",
03538 attr_comp->getAttrpath().c_str());
03539 }
03540
03541 Status s = attr->addComponent(db, attr_comp);
03542 if (s) return rpcStatusMake(s);
03543
03544 return IDB_attrCompPropagate(db, cls, attr_comp, True);
03545 }
03546
03547 RPCStatus
03548 IDB_constraintDelete(DbHandle * dbh, const eyedbsm::Oid * objoid, int reentrant)
03549 {
03550 Database *db = (Database *)dbh->db;
03551 AttrIdxContext idx_ctx;
03552 AttributeComponent *attr_comp;
03553 const Attribute *attr;
03554
03555 const Class *cls;
03556 RPCStatus rpc_status = IDB_attrCompPrologue(db, objoid, cls,
03557 attr_comp,
03558 attr, IDBBOOL(!reentrant));
03559 if (rpc_status) return rpc_status;
03560
03561
03562
03563
03564
03565
03566 ObjectReleaser _(attr_comp);
03567 Status s = attr->rmvComponent(db, attr_comp);
03568 if (s) return rpcStatusMake(s);
03569
03570 return IDB_attrCompPropagate(db, cls, attr_comp, False);
03571 }
03572
03573
03574 static RPCStatus
03575 IDB_indexPrologue(DbHandle *dbh, const eyedbsm::Oid * _idxoid, Index *&idx)
03576 {
03577 Database *db = (Database *)dbh->db;
03578 Oid idxoid(_idxoid);
03579 Status s = db->loadObject(idxoid, (Object *&)idx);
03580 if (s) return rpcStatusMake(s);
03581
03582 if (idx->getIdxOid().isValid()) {
03583 s = Attribute::openMultiIndexRealize(db, idx);
03584 if (s) return rpcStatusMake(s);
03585 if (!idx->idx)
03586 return rpcStatusMake(IDB_ERROR, "invalid null index %s",
03587 idxoid.toString());
03588 }
03589
03590 return RPCSuccess;
03591 }
03592
03593 RPCStatus
03594 IDB_indexGetCount(DbHandle * dbh, const eyedbsm::Oid * idxoid, int * cnt)
03595 {
03596 Index *idx;
03597 RPCStatus rpc_status = IDB_indexPrologue(dbh, idxoid, idx);
03598 if (rpc_status) return rpc_status;
03599
03600 if (!idx->getIdxOid().isValid()) {
03601 *cnt = 0;
03602 return RPCSuccess;
03603 }
03604
03605 *cnt = idx->idx->getCount();
03606 return RPCSuccess;
03607 }
03608
03609 RPCStatus
03610 IDB_indexGetStats(DbHandle * dbh, const eyedbsm::Oid * idxoid,
03611 Data *rstats, void *xdata)
03612 {
03613 rpc_ServerData *data = (rpc_ServerData *)xdata;
03614
03615 if (data) {
03616 data->status = rpc_BuffUsed;
03617 data->size = 0;
03618 }
03619
03620 Index *idx;
03621 RPCStatus rpc_status = IDB_indexPrologue(dbh, idxoid, idx);
03622 if (rpc_status) return rpc_status;
03623
03624 if (!idx->getIdxOid().isValid())
03625 return RPCSuccess;
03626
03627 if (idx->asHashIndex()) {
03628 eyedbsm::HIdx::Stats stats;
03629 eyedbsm::Status s = idx->asHashIndex()->idx->asHIdx()->getStats(stats);
03630 if (s) return rpcStatusMake_se(s);
03631 if (data) {
03632 data->status = rpc_TempDataUsed;
03633 data->data = code_index_stats(IndexImpl::Hash, &stats,
03634 &data->size);
03635 }
03636 else
03637 make_index_stats(stats, rstats);
03638 }
03639 else {
03640 eyedbsm::BIdx::Stats stats;
03641 eyedbsm::Status s = idx->asBTreeIndex()->idx->asBIdx()->getStats(stats);
03642 if (s) return rpcStatusMake_se(s);
03643 if (data) {
03644 data->status = rpc_TempDataUsed;
03645 data->data = code_index_stats(IndexImpl::BTree, &stats,
03646 &data->size);
03647 }
03648 else
03649 make_index_stats(stats, rstats);
03650 }
03651
03652 return RPCSuccess;
03653 }
03654
03655 RPCStatus
03656 IDB_indexSimulStats(DbHandle * dbh, const eyedbsm::Oid * idxoid,
03657 const Data impl, void *xidata,
03658 Data *rstats, void * xrdata)
03659 {
03660 rpc_ServerData *rdata = (rpc_ServerData *)xrdata;
03661
03662 if (rdata) {
03663 rdata->status = rpc_BuffUsed;
03664 rdata->size = 0;
03665 }
03666
03667 Index *idx;
03668 Database *db = (Database *)dbh->db;
03669 RPCStatus rpc_status = IDB_indexPrologue(dbh, idxoid, idx);
03670 if (rpc_status) return rpc_status;
03671
03672 if (!idx->getIdxOid().isValid()) {
03673 if (rstats)
03674 *(IndexStats **)rstats = 0;
03675 return RPCSuccess;
03676 }
03677
03678 lock_data((Data *)&impl, xidata);
03679 IndexImpl *idximpl;
03680 Offset offset = 0;
03681 Status status = IndexImpl::decode(db, impl, offset, idximpl);
03682 if (status) {
03683 unlock_data(impl, xidata);
03684 return rpcStatusMake(status);
03685 }
03686
03687 if (idx->asHashIndex()) {
03688 eyedbsm::HIdx hidx(dbh->sedbh, idx->getIdxOid().getOid(),
03689 hash_key, idximpl->getHashMethod());
03690 eyedbsm::Status s = hidx.status();
03691 unsigned int impl_hints_cnt;
03692 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
03693 eyedbsm::HIdx::Stats stats;
03694 s = hidx.simulate(stats, idximpl->getKeycount(), 0,
03695 impl_hints, impl_hints_cnt,
03696 (idximpl->getHashMethod() ? hash_key : 0),
03697 idximpl->getHashMethod());
03698 if (s) {
03699 unlock_data(impl, xidata);
03700 return rpcStatusMake_se(s);
03701 }
03702 if (rdata) {
03703 rdata->status = rpc_TempDataUsed;
03704 rdata->data = code_index_stats(IndexImpl::Hash, &stats,
03705 &rdata->size);
03706 }
03707 else
03708 make_index_stats(stats, rstats);
03709 }
03710
03711 unlock_data(impl, xidata);
03712 return RPCSuccess;
03713 }
03714
03715 RPCStatus
03716 IDB_collectionGetImplStats(DbHandle * dbh, int idxtype,
03717 const eyedbsm::Oid * idxoid,
03718 Data * rstats, void *xrdata)
03719 {
03720 rpc_ServerData *rdata = (rpc_ServerData *)xrdata;
03721
03722 if (rdata) {
03723 rdata->status = rpc_BuffUsed;
03724 rdata->size = 0;
03725 }
03726
03727 if (idxtype == IndexImpl::Hash) {
03728 eyedbsm::HIdx hidx(dbh->sedbh, idxoid);
03729 eyedbsm::Status s = hidx.status();
03730 if (s) return rpcStatusMake_se(s);
03731 eyedbsm::HIdx::Stats stats;
03732 s = hidx.getStats(stats);
03733 if (s) return rpcStatusMake_se(s);
03734 if (rdata) {
03735 rdata->status = rpc_TempDataUsed;
03736 rdata->data = code_index_stats(IndexImpl::Hash, &stats,
03737 &rdata->size);
03738 }
03739 else
03740 make_index_stats(stats, rstats);
03741 }
03742 else {
03743 eyedbsm::BIdx bidx(dbh->sedbh, *idxoid);
03744 eyedbsm::Status s = bidx.status();
03745 if (s) return rpcStatusMake_se(s);
03746 eyedbsm::BIdx::Stats stats;
03747 s = bidx.getStats(stats);
03748 if (s) return rpcStatusMake_se(s);
03749 if (rdata) {
03750 rdata->status = rpc_TempDataUsed;
03751 rdata->data = code_index_stats(IndexImpl::BTree, &stats,
03752 &rdata->size);
03753 }
03754 else
03755 make_index_stats(stats, rstats);
03756 }
03757
03758 return RPCSuccess;
03759 }
03760
03761 RPCStatus
03762 IDB_collectionSimulImplStats(DbHandle * dbh, int idxtype,
03763 const eyedbsm::Oid * idxoid,
03764 const Data impl, void *xidata,
03765 Data *rstats, void *xrdata)
03766 {
03767 rpc_ServerData *rdata = (rpc_ServerData *)xrdata;
03768
03769 if (rdata) {
03770 rdata->status = rpc_BuffUsed;
03771 rdata->size = 0;
03772 }
03773
03774 Database *db = (Database *)dbh->db;
03775 lock_data((Data *)&impl, xidata);
03776 IndexImpl *idximpl;
03777 Offset offset = 0;
03778
03779 Status status = IndexImpl::decode(db, impl, offset, idximpl);
03780 if (status) {
03781 unlock_data(impl, xidata);
03782 return rpcStatusMake(status);
03783 }
03784
03785 if (idxtype == IndexImpl::Hash) {
03786 eyedbsm::HIdx hidx(dbh->sedbh, idxoid,
03787 hash_key, idximpl->getHashMethod());
03788 eyedbsm::Status s = hidx.status();
03789 unsigned int impl_hints_cnt;
03790 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
03791 eyedbsm::HIdx::Stats stats;
03792 s = hidx.simulate(stats, idximpl->getKeycount(), 0,
03793 impl_hints, impl_hints_cnt,
03794 (idximpl->getHashMethod() ? hash_key : 0),
03795 idximpl->getHashMethod());
03796 if (s) {
03797 unlock_data(impl, xidata);
03798 return rpcStatusMake_se(s);
03799 }
03800
03801 if (rdata) {
03802 rdata->status = rpc_TempDataUsed;
03803 rdata->data = code_index_stats(IndexImpl::Hash,
03804 &stats, &rdata->size);
03805 }
03806 else
03807 make_index_stats(stats, rstats);
03808 }
03809 else {
03810 *(BTreeIndexStats **)rstats = 0;
03811 unlock_data(impl, xidata);
03812 return rpcStatusMake(Exception::make(IDB_ERROR,
03813 "btree simulation is not "
03814 "yet implemented"));
03815 }
03816
03817 unlock_data(impl, xidata);
03818 return RPCSuccess;
03819 }
03820
03821 RPCStatus
03822 IDB_indexGetImplementation(DbHandle * dbh, const eyedbsm::Oid * idxoid, Data * impl, void * ximpl)
03823 {
03824 rpc_ServerData *data = (rpc_ServerData *)ximpl;
03825
03826 if (data) {
03827 data->status = rpc_BuffUsed;
03828 data->size = 0;
03829 }
03830
03831 Index *idx;
03832 RPCStatus rpc_status = IDB_indexPrologue(dbh, idxoid, idx);
03833 if (rpc_status) return rpc_status;
03834
03835 if (!idx->getIdxOid().isValid())
03836 return RPCSuccess;
03837
03838 if (idx->asHashIndex()) {
03839 const eyedbsm::HIdx::_Idx &ix = idx->asHashIndex()->idx->asHIdx()->getIdx();
03840 if (data) {
03841 data->status = rpc_TempDataUsed;
03842 data->data = code_index_impl(ix, &data->size);
03843 }
03844 else
03845 make_index_impl(ix, impl);
03846 }
03847
03848 if (idx->asBTreeIndex()) {
03849 eyedbsm::BIdx *ix = idx->asBTreeIndex()->idx->asBIdx();
03850 if (data) {
03851 data->status = rpc_TempDataUsed;
03852 data->data = code_index_impl(*ix, &data->size);
03853 }
03854 else
03855 make_index_impl(*ix, impl);
03856 }
03857
03858 return RPCSuccess;
03859 }
03860
03861 RPCStatus
03862 IDB_collectionGetImplementation(DbHandle * dbh, int idxtype, const eyedbsm::Oid * idxoid, Data * impl, void * ximpl)
03863 {
03864 rpc_ServerData *data = (rpc_ServerData *)ximpl;
03865
03866 if (data) {
03867 data->status = rpc_BuffUsed;
03868 data->size = 0;
03869 }
03870
03871 eyedbsm::Idx *seidx = 0;
03872 eyedbsm::Status s = eyedbsm::Idx::make(dbh->sedbh, *idxoid, seidx);
03873 if (s)
03874 return rpcStatusMake_se(s);
03875
03876
03877
03878 if (seidx->asHIdx()) {
03879 eyedbsm::HIdx *hidx = seidx->asHIdx();
03880 s = hidx->status();
03881 if (s) {delete seidx; return rpcStatusMake_se(s);}
03882 const eyedbsm::HIdx::_Idx &ix = hidx->getIdx();
03883 if (data) {
03884 data->status = rpc_TempDataUsed;
03885 data->data = code_index_impl(ix, &data->size);
03886 }
03887 else
03888 make_index_impl(ix, impl);
03889 }
03890 else {
03891 eyedbsm::BIdx *bidx = seidx->asBIdx();
03892
03893 s = bidx->status();
03894 if (s) {delete seidx; return rpcStatusMake_se(s);}
03895 if (data) {
03896 data->status = rpc_TempDataUsed;
03897 data->data = code_index_impl(*bidx, &data->size);
03898 }
03899 else
03900 make_index_impl(*bidx, impl);
03901 }
03902
03903 delete seidx;
03904 return RPCSuccess;
03905 }
03906
03907
03908 CollectionBE *
03909 IDB_getCollBE(const char *from, Database *db, DbHandle *dbh,
03910 const eyedbsm::Oid *colloid, Status *status,
03911 Bool locked = False)
03912 {
03913 CollectionBE *collbe;
03914
03915 if (!isOidValid(colloid)) {
03916 *status = Exception::make(IDB_ERROR, "invalid null oid collection");
03917 return 0;
03918 }
03919
03920
03921
03922
03923
03924
03925
03926 Oid _oid(colloid);
03927 if (!(collbe = db->getBEQueue()->getCollection(&_oid, dbh))) {
03928 collbe = new CollectionBE(db, dbh, &_oid, locked);
03929
03930
03931 if (*status = collbe->getStatus()) {
03932 delete collbe;
03933 return 0;
03934 }
03935
03936 if (locked)
03937 db->getBEQueue()->addCollection(collbe, dbh);
03938 }
03939
03940
03941
03942
03943
03944 *status = Success;
03945 return collbe;
03946 }
03947
03948
03949
03950 void
03951 IDB_free(Database *db, CollectionBE *collbe)
03952 {
03953 if (!collbe->isLocked())
03954 delete collbe;
03955 }
03956
03957
03958 static Bool coll_hidx_oid = False;
03959
03960 static RPCStatus
03961 IDB_collectionCreate(DbHandle *dbh, short dspid, Data idr,
03962 ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata)
03963 {
03964 Database *db = (Database *)dbh->db;
03965 Offset offset;
03966
03967 offset = IDB_COLL_OFF_ITEM_SIZE;
03968
03969
03970 eyedblib::int16 item_size;
03971 int16_decode (idr, &offset, &item_size);
03972
03973 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
03974 Class *cls = db->getSchema()->getClass(oid_cl);
03975
03976 eyedblib::int32 items_cnt;
03977 offset = IDB_COLL_OFF_ITEMS_CNT;
03978 int32_decode (idr, &offset, &items_cnt);
03979
03980 IndexImpl *idximpl;
03981 offset = IDB_COLL_OFF_IMPL_BEGIN;
03982 int impl_type;
03983 IndexImpl::decode(db, idr, offset, idximpl, &impl_type);
03984
03985 Oid inv_oid;
03986 eyedblib::int16 inv_item;
03987
03988 offset = IDB_COLL_OFF_INV_OID;
03989 eyedbsm::Oid se_inv_oid;
03990 oid_decode(idr, &offset, &se_inv_oid);
03991 inv_oid.setOid(se_inv_oid);
03992 int16_decode(idr, &offset, &inv_item);
03993
03994 Data idx_data = 0;
03995 eyedblib::int16 idx_data_size = 0;
03996
03997 Bool is_literal = False;
03998 Bool is_pure_literal = False;
03999 if (db->getVersionNumber() >= 20414) {
04000 char x;
04001 char_decode(idr, &offset, &x);
04002 Collection::decodeLiteral(x, is_literal, is_pure_literal);
04003
04004 int16_decode(idr, &offset, &idx_data_size);
04005 idx_data = idr+offset;
04006 }
04007
04008 eyedbsm::Idx *idx1, *idx2;
04009 eyedbsm::Oid idx1_oid, idx2_oid;
04010
04011
04012
04013
04014
04015
04016
04017 if (impl_type == CollImpl::BTreeIndex) {
04018 eyedbsm::BIdx::KeyType ktypes;
04019
04020 ktypes.type = eyedbsm::Idx::tUnsignedChar;
04021 ktypes.count = item_size;
04022 ktypes.offset = 0;
04023
04024 idx1 = new eyedbsm::BIdx(dbh->sedbh, sizeof(eyedblib::int32), &ktypes, dspid,
04025 idximpl->getDegree());
04026 idx1->asBIdx()->open();
04027 }
04028 else if (impl_type == CollImpl::HashIndex) {
04029 eyedbsm::Idx::KeyType ktype;
04030 if (coll_hidx_oid) {
04031 ktype.type = eyedbsm::Idx::tOid;
04032 ktype.count = 1;
04033 }
04034 else {
04035 ktype.type = eyedbsm::Idx::tUnsignedChar;
04036 ktype.count = item_size;
04037 }
04038 ktype.offset = 0;
04039 unsigned int impl_hints_cnt;
04040 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
04041 idx1 = new eyedbsm::HIdx(dbh->sedbh, ktype,
04042 sizeof(eyedblib::int32), dspid, 0, idximpl->getKeycount(),
04043 impl_hints, impl_hints_cnt);
04044 idx1->asHIdx()->open();
04045 }
04046 else if (impl_type == CollImpl::NoIndex) {
04047 return rpcStatusMake(IDB_ERROR, "collection: noindex implementation is not yet supported");
04048 }
04049 else {
04050 return rpcStatusMake(IDB_ERROR, "collection: unknown implementation %d", impl_type);
04051 }
04052
04053 idx1_oid = idx1->oid();
04054
04055
04056
04057
04058
04059
04060 if (idx1->status())
04061 return rpcStatusMake_se(idx1->status());
04062
04063 if (eyedb_is_type(*hdr, _CollList_Type) ||
04064 eyedb_is_type(*hdr, _CollArray_Type)) {
04065
04066 eyedbsm::BIdx::KeyType ktypes;
04067
04068
04069 ktypes.type = eyedbsm::Idx::tInt32;
04070 ktypes.count = 1;
04071 ktypes.offset = 0;
04072
04073
04074 idx2 = new eyedbsm::BIdx(dbh->sedbh, item_size, &ktypes, dspid);
04075 idx2->asBIdx()->open();
04076
04077 idx2_oid = idx2->oid();
04078
04079 if (idx2->status())
04080 return rpcStatusMake(IDB_ERROR, "");
04081 }
04082 else {
04083 idx2 = 0;
04084 idx2_oid = *getInvalidOid();
04085 }
04086
04087 Size alloc_size = hdr->size;
04088
04089 offset = IDB_COLL_OFF_IDX1_OID;
04090 oid_code (&idr, &offset, &alloc_size, &idx1_oid);
04091 offset = IDB_COLL_OFF_IDX2_OID;
04092 oid_code (&idr, &offset, &alloc_size, &idx2_oid);
04093
04094 RPCStatus rpc_status = IDB_instanceCreate(dbh, dspid,
04095 idr, hdr, oid, xdata, True);
04096
04097 if (rpc_status != RPCSuccess)
04098 return rpc_status;
04099
04100 Oid _oid(oid);
04101
04102 CollectionBE *collbe =
04103 new CollectionBE(db, dbh, &_oid, cls,
04104 Oid(idx1_oid), Oid(idx2_oid), idx1, idx2,
04105 items_cnt, True, inv_oid, inv_item, idximpl,
04106 idx_data, idx_data_size, is_literal, is_pure_literal);
04107
04108 db->getBEQueue()->addCollection(collbe, dbh);
04109
04110 return RPCSuccess;
04111 }
04112
04113 static RPCStatus
04114 IDB_collectionCardWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid)
04115 {
04116 CHECK_WRITE((Database *)dbh->db);
04117
04118 Offset offset = IDB_OBJ_HEAD_SIZE;
04119 eyedbsm::Status se_status;
04120
04121 eyedbsm::Oid xoid;
04122
04123 oid_decode(idr, &offset, &xoid);
04124
04125
04126 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_CARD_OID,
04127 sizeof(eyedbsm::Oid), &xoid, oid);
04128 if (se_status)
04129 return rpcStatusMake_se(se_status);
04130
04131 return RPCSuccess;
04132 }
04133
04134 static RPCStatus
04135 IDB_collectionInvWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid)
04136 {
04137 Database *db = (Database *)dbh->db;
04138 CHECK_WRITE(db);
04139
04140 eyedbsm::Status se_status;
04141
04142 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_INV_OID,
04143 sizeof(eyedbsm::Oid)+sizeof(eyedblib::int16),
04144 idr+IDB_OBJ_HEAD_SIZE, oid);
04145 if (se_status)
04146 return rpcStatusMake_se(se_status);
04147
04148 return RPCSuccess;
04149 }
04150
04151 static RPCStatus
04152 IDB_collectionUpdateCount(DbHandle *dbh, CollectionBE *collbe,
04153 const eyedbsm::Oid *oid,
04154 int is_idx2, int change_cnt,
04155 int items_bottom, int items_top)
04156 {
04157 Database *db = (Database *)dbh->db;
04158 CHECK_WRITE(db);
04159 eyedbsm::Status se_status;
04160
04161 if (is_idx2) {
04162 int xitems_top, xitems_bottom;
04163
04164 se_status = eyedbsm::objectRead(dbh->sedbh, IDB_COLL_OFF_ITEMS_BOT,
04165 sizeof(eyedblib::int32), &xitems_bottom, eyedbsm::DefaultLock,
04166 0, 0, oid);
04167
04168 RCHECK(se_status);
04169 se_status = eyedbsm::objectRead(dbh->sedbh, IDB_COLL_OFF_ITEMS_TOP,
04170 sizeof(eyedblib::int32), &xitems_top, eyedbsm::DefaultLock,
04171 0, 0, oid);
04172
04173 RCHECK(se_status);
04174
04175 xitems_top = x2h_32(xitems_top);
04176 xitems_bottom = x2h_32(xitems_bottom);
04177
04178 items_top = (items_top > xitems_top) ? items_top : xitems_top;
04179 items_bottom = (items_bottom < xitems_bottom) ? items_bottom :
04180 xitems_bottom;
04181
04182 if (items_bottom != xitems_bottom) {
04183 #ifdef E_XDR
04184 eyedblib::int32 items_bottom_x = h2x_32(items_bottom);
04185 #else
04186 eyedblib::int32 items_bottom_x = items_bottoms;
04187 #endif
04188 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_ITEMS_BOT,
04189 sizeof(eyedblib::int32), &items_bottom_x, oid);
04190
04191 RCHECK(se_status);
04192 }
04193
04194 if (items_top != xitems_top) {
04195 #ifdef E_XDR
04196 eyedblib::int32 items_top_x = h2x_32(items_top);
04197 #else
04198 eyedblib::int32 items_top_x = items_tops;
04199 #endif
04200 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_ITEMS_TOP,
04201 sizeof(eyedblib::int32), &items_top_x, oid);
04202 RCHECK(se_status);
04203 }
04204 }
04205
04206 if (!change_cnt)
04207 return RPCSuccess;
04208
04209 eyedblib::int32 items_cnt, xitems_cnt;
04210 se_status = eyedbsm::objectRead(dbh->sedbh, IDB_COLL_OFF_ITEMS_CNT,
04211 sizeof(eyedblib::int32), &xitems_cnt, eyedbsm::DefaultLock,
04212 0, 0, oid);
04213
04214 #ifdef E_XDR
04215 eyedblib::int32 xitems_cnt_x = x2h_32(xitems_cnt);
04216 #else
04217 eyedblib::int32 xitems_cnt_x = xitems_cnt;
04218 #endif
04219
04220
04221
04222
04223
04224 items_cnt = xitems_cnt_x + change_cnt;
04225
04226 #ifdef E_XDR
04227 eyedblib::int32 items_cnt_x = x2h_32(items_cnt);
04228 #else
04229 eyedblib::int32 items_cnt_x = items_cnt;
04230 #endif
04231 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_ITEMS_CNT,
04232 sizeof(eyedblib::int32), &items_cnt_x, oid);
04233 RCHECK(se_status);
04234
04235 IDB_free(db, collbe);
04236 return RPCSuccess;
04237 }
04238
04239 #define UPDATE_COUNT() \
04240 IDB_collectionUpdateCount(dbh, collbe, oid, \
04241 is_idx2, change_cnt, items_bottom, \
04242 items_top)
04243
04244 static RPCStatus
04245 IDB_collNameManage(DbHandle *dbh, const eyedbsm::Oid *oid,
04246 Data idr, short code, Offset &offset)
04247 {
04248 if (code & IDB_COLL_NAME_CHANGED) {
04249 char *name;
04250
04251
04252 string_decode(idr, &offset, (char **)&name);
04253 unsigned int size;
04254 eyedbsm::Status se_status = eyedbsm::objectSizeGet(dbh->sedbh, &size, eyedbsm::DefaultLock, oid);
04255 if (se_status) {
04256 return rpcStatusMake_se(se_status);
04257 }
04258
04259 }
04260 return RPCSuccess;
04261 }
04262
04263 static RPCStatus
04264 IDB_collImplManage(DbHandle *dbh, const eyedbsm::Oid *oid,
04265 eyedbsm::Idx *idx1, eyedbsm::Idx *idx2,
04266 Data idr, short code, Offset &offset)
04267 {
04268 Database *db = (Database *)dbh->db;
04269
04270 if (code & IDB_COLL_IMPL_CHANGED) {
04271 IndexImpl *idximpl;
04272 Offset offset_impl = offset;
04273 Status status = IndexImpl::decode(db, idr, offset, idximpl);
04274 if (status)
04275 return rpcStatusMake(status);
04276
04277
04278 eyedbsm::Idx *idxs[2] = {idx1, idx2};
04279 eyedbsm::Status s;
04280 eyedbsm::Oid newoid[2] = {eyedbsm::Oid::nullOid, eyedbsm::Oid::nullOid};
04281
04282 if (idximpl->getType() == IndexImpl::Hash) {
04283 unsigned int impl_hints_cnt;
04284 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
04285
04286 for (int i = 0; i < 2; i++) {
04287 eyedbsm::HIdx *idx = (idxs[i] ? idxs[i]->asHIdx() : 0);
04288 if (idx) {
04289 eyedbsm::Idx::KeyType ktype = idx->getKeyType();
04290 eyedbsm::Boolean change;
04291
04292
04293
04294 if (ktype.type == eyedbsm::Idx::tUnsignedChar &&
04295 ktype.count == sizeof(eyedbsm::Oid)) {
04296 ktype.type = eyedbsm::Idx::tOid;
04297 ktype.count = 1;
04298 change = eyedbsm::True;
04299 }
04300 else
04301 change = eyedbsm::False;
04302
04303 s = idx->reimplementToHash
04304 (newoid[i], idximpl->getKeycount(), 0,
04305 idx->getDefaultDspid(),
04306 impl_hints, impl_hints_cnt,
04307 (idximpl->getHashMethod() ? hash_key : 0),
04308 idximpl->getHashMethod(), (change ? &ktype : 0));
04309
04310 if (s)
04311 return rpcStatusMake_se(s);
04312
04313 }
04314 }
04315 }
04316 else {
04317 for (int i = 0; i < 2; i++) {
04318 eyedbsm::Idx *idx = idxs[i];
04319 if (idx) {
04320 s = idx->reimplementToBTree(newoid[i], idximpl->getDegree(),
04321 idx->getDefaultDspid());
04322
04323 if (s)
04324 return rpcStatusMake_se(s);
04325 }
04326 }
04327 }
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337 eyedbsm::Oid data_oid[2];
04338 Data data = (Data)&data_oid;
04339 Size alloc_size = 2 * sizeof(eyedbsm::Oid);
04340 offset = 0;
04341 oid_code(&data, &offset, &alloc_size, &newoid[0]);
04342 oid_code(&data, &offset, &alloc_size, &newoid[1]);
04343 assert(data == (Data)data_oid);
04344 RPCStatus rpc_status =
04345 IDB_dataWrite(dbh, IDB_COLL_OFF_IDX1_OID, 2 * sizeof(eyedbsm::Oid),
04346 data, oid, 0);
04347 if (rpc_status) return rpc_status;
04348 return IDB_dataWrite(dbh, IDB_COLL_OFF_IMPL_BEGIN, IDB_IMPL_CODE_SIZE,
04349 &idr[offset_impl], oid, 0);
04350 }
04351
04352
04353
04354
04355
04356
04357
04358 return RPCSuccess;
04359 }
04360
04361
04362 static RPCStatus
04363 IDB_collectionWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, void *xdata)
04364 {
04365 if (hdr->xinfo == IDB_XINFO_CARD)
04366 return IDB_collectionCardWrite(dbh, idr, hdr, oid);
04367
04368 if (hdr->xinfo == IDB_XINFO_INV)
04369 return IDB_collectionInvWrite(dbh, idr, hdr, oid);
04370
04371 Database *db = (Database *)dbh->db;
04372
04373 CollectionBE *collbe;
04374 Status status;
04375 collbe = IDB_getCollBE("collectionWrite", db, dbh, oid, &status);
04376
04377 if (!collbe)
04378 return rpcStatusMake(status);
04379
04380 collbe->unlock();
04381
04382 eyedbsm::Idx *idx1, *idx2;
04383 collbe->getIdx(&idx1, &idx2);
04384
04385 eyedbsm::Status se_status;
04386
04387 Offset offset = IDB_OBJ_HEAD_SIZE + sizeof(eyedblib::int32);
04388 eyedblib::int32 oid_cnt;
04389 int32_decode (idr, &offset, &oid_cnt);
04390
04391 int is_idx2 = (eyedb_is_type(*hdr, _CollList_Type) ||
04392 eyedb_is_type(*hdr, _CollArray_Type));
04393
04394 Data temp = collbe->getTempBuff();
04395 eyedblib::int16 item_size = collbe->getItemSize();
04396
04397 int change_cnt = 0;
04398 int items_bottom = 0xffffff;
04399 int items_top = 0;
04400
04401 Oid inv_oid;
04402 const Attribute *inv_item = NULL;
04403 eyedbsm::Idx *idx = 0;
04404 status = collbe->getInvItem(db, inv_item, inv_oid, idx);
04405
04406 if (status)
04407 return rpcStatusMake(status);
04408
04409 int i;
04410 for (i = 0; i < oid_cnt; i++) {
04411 eyedbsm::Boolean found;
04412 eyedblib::int32 ind;
04413 char state;
04414
04415 buffer_decode(idr, &offset, temp, item_size);
04416
04417 int32_decode(idr, &offset, &ind);
04418 char_decode(idr, &offset, &state);
04419 Oid i_oid;
04420 if (collbe->getIsRef())
04421 eyedbsm::x2h_oid(i_oid.getOid(), temp);
04422
04423 if (is_idx2) {
04424 unsigned char *temp1 = (unsigned char *)malloc(collbe->getItemSize());
04425 if (state == CollectionPeer::removed) {
04426 se_status = idx1->remove(temp, &ind, &found);
04427 if (se_status || !found) {
04428 UPDATE_COUNT();
04429 free(temp1);
04430 if (se_status)
04431 return rpcStatusMake_se(se_status);
04432
04433 return rpcStatusMake(IDB_COLLECTION_ERROR,
04434 "item %s not found at %d in %s",
04435 i_oid.toString(), ind,
04436 eyedbsm::getOidString(oid));
04437 }
04438
04439 se_status = idx2->remove(&ind, temp, &found);
04440 if (se_status || !found) {
04441 UPDATE_COUNT();
04442 free(temp1);
04443 if (se_status)
04444 return rpcStatusMake_se(se_status);
04445 return rpcStatusMake(IDB_COLLECTION_ERROR,
04446 "item %s not found at %d in %s",
04447 i_oid.toString(), ind,
04448 eyedbsm::getOidString(oid));
04449 }
04450
04451 if (idx) {
04452
04453
04454 se_status = idx->remove(i_oid.getOid(), inv_oid.getOid(), &found);
04455 if ((eyedblib::log_mask & IDB_LOG_IDX_SUPPRESS) == IDB_LOG_IDX_SUPPRESS) {
04456 IDB_LOG(IDB_LOG_IDX_SUPPRESS,
04457 ("Removing Collection index entry '%s'"
04458 " %s <-> %s\n", inv_item->getName(),
04459 i_oid.toString(), inv_oid.toString()));
04460 }
04461 if (se_status || !found)
04462 return rpcStatusMake_se(se_status);
04463 }
04464
04465 change_cnt--;
04466
04467 if (ind < items_bottom)
04468 items_bottom = ind;
04469
04470 if (ind+1 == items_top)
04471 items_top--;
04472 }
04473 else if (state == CollectionPeer::added) {
04474 se_status = idx1->insert(temp, &ind);
04475 if (se_status) {
04476 UPDATE_COUNT();
04477 free(temp1);
04478 return rpcStatusMake_se(se_status);
04479 }
04480
04481 se_status = idx2->searchAny(&ind, &found, temp1);
04482 if (se_status) {
04483 UPDATE_COUNT();
04484 free(temp1);
04485 return rpcStatusMake_se(se_status);
04486 }
04487
04488 if (found) {
04489 if (se_status = idx1->remove(temp1, &ind)) {
04490 UPDATE_COUNT();
04491 free(temp1);
04492 return rpcStatusMake_se(se_status);
04493 }
04494
04495 if (se_status = idx2->remove(&ind, temp1)) {
04496 UPDATE_COUNT();
04497 free(temp1);
04498 return rpcStatusMake_se(se_status);
04499 }
04500 change_cnt--;
04501 }
04502
04503 se_status = idx2->insert(&ind, temp);
04504 if (se_status) {
04505 UPDATE_COUNT();
04506 free(temp1);
04507 return rpcStatusMake_se(se_status);
04508 }
04509
04510 if (idx) {
04511 se_status = idx->insert(i_oid.getOid(), inv_oid.getOid());
04512 if ((eyedblib::log_mask & IDB_LOG_IDX_CREATE) ==
04513 IDB_LOG_IDX_CREATE) {
04514 IDB_LOG(IDB_LOG_IDX_CREATE,
04515 ("Inserting Collection index entry '%s'"
04516 " %s <-> %s\n",
04517 inv_item->getName(),
04518 i_oid.toString(), inv_oid.toString()));
04519 }
04520
04521 if (se_status)
04522 return rpcStatusMake_se(se_status);
04523 }
04524
04525 if (ind >= items_top)
04526 items_top = ind+1;
04527
04528 change_cnt++;
04529 }
04530
04531 free(temp1);
04532 }
04533 else {
04534 ind = 1;
04535 if (state == CollectionPeer::removed) {
04536 se_status = idx1->remove(temp, &ind, &found);
04537 if (se_status || !found) {
04538 UPDATE_COUNT();
04539 if (se_status)
04540 return rpcStatusMake_se(se_status);
04541 return rpcStatusMake(IDB_COLLECTION_ERROR,
04542 "item %s not found in %s",
04543 i_oid.toString(),
04544 eyedbsm::getOidString(oid));
04545 }
04546
04547 if (idx) {
04548 se_status = idx->remove(i_oid.getOid(), inv_oid.getOid(), &found);
04549 if ((eyedblib::log_mask & IDB_LOG_IDX_SUPPRESS) ==
04550 IDB_LOG_IDX_SUPPRESS) {
04551 IDB_LOG(IDB_LOG_IDX_SUPPRESS,
04552 ("Removing Collection index entry '%s'"
04553 " %s <-> %s\n",
04554 inv_item->getName(),
04555 i_oid.toString(), inv_oid.toString()));
04556 }
04557 if (se_status || !found)
04558 return rpcStatusMake_se(se_status);
04559 }
04560
04561 change_cnt--;
04562 }
04563 else if (state == CollectionPeer::added) {
04564 se_status = idx1->insert(temp, &ind);
04565 if (se_status) {
04566 UPDATE_COUNT();
04567 return rpcStatusMake_se(se_status);
04568 }
04569
04570 if (idx) {
04571 se_status = idx->insert(i_oid.getOid(), inv_oid.getOid());
04572 if ((eyedblib::log_mask & IDB_LOG_IDX_CREATE) == IDB_LOG_IDX_CREATE) {
04573 IDB_LOG(IDB_LOG_IDX_CREATE,
04574 ("Inserting Collection index entry '%s'"
04575 " %s <-> %s\n",
04576 inv_item->getName(),
04577 i_oid.toString(), inv_oid.toString()));
04578 }
04579
04580 if (se_status)
04581 return rpcStatusMake_se(se_status);
04582 }
04583 change_cnt++;
04584 }
04585
04586 }
04587 }
04588
04589 if (inv_item && inv_item->hasInverse() &&
04590 hdr->xinfo != IDB_XINFO_INVALID_INV)
04591 {
04592 offset = IDB_OBJ_HEAD_SIZE + sizeof(eyedblib::int32) + sizeof(eyedblib::int32);
04593 for (i = 0; i < oid_cnt; i++) {
04594 eyedblib::int32 ind;
04595 char state;
04596
04597 #ifdef E_XDR
04598 eyedbsm::Oid toid;
04599 oid_decode(idr, &offset, &toid);
04600 memcpy(temp, &toid, sizeof(toid));
04601 #else
04602 buffer_decode (idr, &offset, temp, item_size);
04603 #endif
04604 int32_decode (idr, &offset, &ind);
04605 char_decode (idr, &offset, &state);
04606
04607 Oid _oid;
04608 memcpy(&_oid, temp, sizeof(Oid));
04609
04610 status = inv_item->inverse_coll_perform
04611 (db, (state == CollectionPeer::removed ?
04612 Attribute::invObjRemove :
04613 Attribute::invObjUpdate),
04614 inv_oid, _oid);
04615
04616 if (status) {
04617 IDB_free(db, collbe);
04618 return rpcStatusMake(status);
04619 }
04620 }
04621 }
04622
04623 RPCStatus rpc_status;
04624 short code;
04625 int16_decode (idr, &offset, &code);
04626 if ((rpc_status = IDB_collImplManage(dbh, oid, idx1, idx2, idr, code, offset)) != 0) {
04627 return rpc_status;
04628 }
04629
04630 if ((rpc_status = IDB_collNameManage(dbh, oid, idr, code, offset)) != 0) {
04631 return rpc_status;
04632 }
04633
04634 return UPDATE_COUNT();
04635 }
04636
04637 RPCStatus
04638 IDB_collectionRead(DbHandle *dbh, Data idr, ObjectHeader *hdr,
04639 LockMode lockmode,
04640 const eyedbsm::Oid *oid, void *xdata)
04641 {
04642 return RPCSuccess;
04643 }
04644
04645 static RPCStatus
04646 IDB_collectionInverseDelete(Database *db, CollectionBE *collbe,
04647 eyedbsm::Idx *idx, const Attribute *inv_item,
04648 const Oid &inv_oid)
04649 {
04650 if (!inv_item)
04651 return RPCSuccess;
04652
04653 Data temp = collbe->getTempBuff();
04654 eyedblib::int16 item_size = collbe->getItemSize();
04655
04656 eyedbsm::IdxCursor *curs;
04657
04658 if (idx->asBIdx())
04659 curs = new eyedbsm::BIdxCursor(idx->asBIdx(), 0, 0, eyedbsm::False, eyedbsm::False);
04660 else
04661 curs = new eyedbsm::HIdxCursor(idx->asHIdx(), 0, 0, eyedbsm::False, eyedbsm::False);
04662
04663 for (;;)
04664 {
04665 eyedbsm::Boolean sefound;
04666 memset(temp, 0, item_size);
04667 eyedbsm::Idx::Key key;
04668 eyedbsm::Status se_status = curs->next(&sefound, temp, &key);
04669 if (!sefound)
04670 break;
04671
04672 if (se_status)
04673 {
04674 IDB_free(db, collbe);
04675 delete curs;
04676 return rpcStatusMake_se(se_status);
04677 }
04678
04679 Oid _oid;
04680 memcpy(&_oid, key.getKey(), sizeof(Oid));
04681 inv_item->inverse_coll_perform(db, Attribute::invObjRemove,
04682 inv_oid, _oid);
04683 }
04684
04685 delete curs;
04686 return RPCSuccess;
04687 }
04688
04689 static RPCStatus
04690 IDB_collectionDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid)
04691 {
04692 Database *db = (Database *)dbh->db;
04693
04694 CollectionBE *collbe;
04695
04696 Status status;
04697
04698 collbe = IDB_getCollBE("collectionDelete", db, dbh, oid, &status);
04699
04700 if (!collbe)
04701 return rpcStatusMake(status);
04702
04703 eyedbsm::Idx *idx1, *idx2;
04704 collbe->getIdx(&idx1, &idx2);
04705
04706 eyedbsm::Status se_status;
04707
04708 Oid inv_oid;
04709 const Attribute *inv_item = NULL;
04710 eyedbsm::Idx *se_idx = 0;
04711 if (hdr->xinfo != IDB_XINFO_INVALID_INV)
04712 {
04713 status = collbe->getInvItem(db, inv_item, inv_oid, se_idx);
04714
04715 if (status)
04716 return rpcStatusMake(status);
04717 }
04718
04719 if (idx1)
04720 {
04721 RPCStatus rpc_status =
04722 IDB_collectionInverseDelete(db, collbe, idx1, inv_item, inv_oid);
04723
04724 if (rpc_status)
04725 {
04726 IDB_free(db, collbe);
04727 return rpc_status;
04728 }
04729
04730 se_status = idx1->destroy();
04731 if (se_status)
04732 {
04733 IDB_free(db, collbe);
04734 return rpcStatusMake_se(se_status);
04735 }
04736 }
04737
04738 if (idx2)
04739 {
04740 se_status = idx2->destroy();
04741 if (se_status)
04742 {
04743 IDB_free(db, collbe);
04744 return rpcStatusMake_se(se_status);
04745 }
04746 }
04747
04748 IDB_free(db, collbe);
04749 return IDB_instanceDelete(dbh, idr, hdr, oid);
04750 }
04751
04752 RPCStatus
04753 IDB_collectionGetByInd(DbHandle *dbh, const eyedbsm::Oid *colloid, int ind, int *found, Data idr, void *xdata)
04754 {
04755
04756
04757
04758
04759
04760 Database *db = (Database *)dbh->db;
04761 CollectionBE *collbe;
04762 Status status;
04763
04764 rpc_ServerData *data = (rpc_ServerData *)xdata;
04765
04766 if (data) {
04767 data->status = rpc_BuffUsed;
04768 data->size = 0;
04769 }
04770
04771 if (!(collbe = IDB_getCollBE("collectionGetByInd", db, dbh, colloid,
04772 &status)))
04773 return rpcStatusMake(status);
04774
04775 int item_size = collbe->getItemSize();
04776
04777 if (data) {
04778 if (item_size <= data->buff_size)
04779 data->status = rpc_BuffUsed;
04780 else {
04781 data->status = rpc_TempDataUsed;
04782 data->data = malloc(item_size);
04783 }
04784
04785 data->size = item_size;
04786 idr = (Data)data->data;
04787 }
04788
04789 *found = 0;
04790
04791 eyedbsm::Idx *idx2;
04792 collbe->getIdx(0, &idx2);
04793 eyedbsm::Boolean sefound;
04794
04795 eyedbsm::Status se_status;
04796
04797 if (!(se_status = idx2->searchAny(&ind, &sefound, idr))) {
04798 if (sefound) {
04799 *found = 1;
04800 }
04801 }
04802 else {
04803 IDB_free(db, collbe);
04804 return rpcStatusMake_se(se_status);
04805 }
04806
04807 IDB_free(db, collbe);
04808 return RPCSuccess;
04809 }
04810
04811 RPCStatus
04812 IDB_collectionGetByValue(DbHandle *dbh, const eyedbsm::Oid *colloid,
04813 Data val, int *found, int *ind)
04814 {
04815
04816
04817
04818
04819
04820 Database *db = (Database *)dbh->db;
04821 *found = 0;
04822
04823 CollectionBE *collbe;
04824
04825 Status status;
04826
04827 if (!(collbe = IDB_getCollBE("collectionGetByValue", db, dbh, colloid, &status)))
04828 return rpcStatusMake(status);
04829
04830 eyedbsm::Idx *idx1;
04831 collbe->getIdx(&idx1, 0);
04832 eyedbsm::Boolean sefound;
04833
04834
04835
04836
04837
04838
04839
04840 #if 0
04841 eyedbsm::Oid toid;
04842
04843
04844
04845
04846
04847
04848 memcpy(&toid, val, sizeof(toid));
04849 Offset offset_0 = 0;
04850 Size alloc_size_0 = sizeof(toid);
04851 oid_code(&val, &offset_0, &alloc_size_0, &toid);
04852 #endif
04853
04854 eyedbsm::Status se_status;
04855 if (!(se_status = idx1->searchAny(val, &sefound, ind))) {
04856 if (sefound)
04857 *found = 1;
04858 }
04859 else {
04860 IDB_free(db, collbe);
04861 return rpcStatusMake_se(se_status);
04862 }
04863
04864 IDB_free(db, collbe);
04865 return RPCSuccess;
04866 }
04867
04868 RPCStatus
04869 IDB_setObjectLock(DbHandle *dbh, const eyedbsm::Oid * oid, int lockmode, int * rlockmode)
04870 {
04871 eyedbsm::LockMode _rlockmode;
04872 eyedbsm::Status se = eyedbsm::objectLock(dbh->sedbh, oid, (eyedbsm::LockMode)lockmode, &_rlockmode);
04873 if (se) return rpcStatusMake_se(se);
04874
04875 if (rlockmode)
04876 *rlockmode = _rlockmode;
04877
04878 return RPCSuccess;
04879 }
04880
04881 RPCStatus
04882 IDB_getObjectLock(DbHandle *dbh, const eyedbsm::Oid * oid, int * lockmode)
04883 {
04884 eyedbsm::LockMode _rlockmode;
04885 eyedbsm::Status se = eyedbsm::objectGetLock(dbh->sedbh, oid, &_rlockmode);
04886 if (se) return rpcStatusMake_se(se);
04887
04888 *lockmode = _rlockmode;
04889
04890 return RPCSuccess;
04891 }
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956 RPCStatus
04957 IDB_queryCollectionCreate(DbHandle *dbh, const eyedbsm::Oid *colloid, int index,
04958 int *qid)
04959 {
04960 Oid xcolloid(colloid);
04961
04962 if (!xcolloid.isValid())
04963 return rpcStatusMake(Exception::make(IDB_ERROR, "invalid null oid for collection query"));
04964
04965 Database *db = (Database *)dbh->db;
04966 CollectionBE *collbe;
04967
04968 Status status;
04969
04970 if (!(collbe = IDB_getCollBE("queryCollectionCreate", db, dbh, colloid, &status)))
04971 return rpcStatusMake(status);
04972
04973 IteratorBE *qbe = new IteratorBE(collbe, (index ? True : False));
04974
04975 if ((status = qbe->getStatus()) == Success)
04976 {
04977 *qid = qbe->getQid();
04978 return RPCSuccess;
04979 }
04980
04981 IDB_free(db, collbe);
04982 return rpcStatusMake(status);
04983 }
04984
04985 RPCStatus
04986 IDB_queryAttributeCreate(DbHandle *dbh, const eyedbsm::Oid *cloid,
04987 int num, int ind, Data start,
04988 Data end, int sexcl, int eexcl, int x_size,
04989 int *qid)
04990 {
04991 Database *db = (Database *)dbh->db;
04992 Class *cl = db->getSchema()->getClass(*cloid);
04993 const Attribute *attr = (Attribute *)((AgregatClass *)cl)->getAttribute(num);
04994
04995 if (attr)
04996 {
04997 IteratorBE *qbe = new IteratorBE((Database *)dbh->db,
04998 attr, ind, start, end,
04999 (Bool)sexcl, (Bool)eexcl,
05000 x_size);
05001 Status status;
05002 if ((status = qbe->getStatus()) == Success)
05003 {
05004 *qid = qbe->getQid();
05005 return RPCSuccess;
05006 }
05007
05008 return rpcStatusMake(status);
05009 }
05010
05011 return rpcStatusMake(IDB_ERROR, "invalid attribute");
05012 }
05013
05014 RPCStatus
05015 IDB_queryDelete(DbHandle *dbh, int qid)
05016 {
05017 Database *db = (Database *)dbh->db;
05018 IteratorBE *qbe;
05019 if (qbe = db->getBEQueue()->getIterator(qid))
05020 {
05021 delete qbe;
05022 db->getBEQueue()->removeIterator(qid);
05023 return RPCSuccess;
05024 }
05025
05026 return rpcStatusMake(IDB_ERROR, "invalid query");
05027 }
05028
05029 int
05030 IDB_getSeTrsCount(DbHandle *dbh)
05031 {
05032 return dbh->sedbh->tr_cnt;
05033 }
05034
05035 RPCStatus
05036 IDB_queryScanNext(DbHandle *dbh, int qid, int wanted, int *found,
05037 void *atom_array, void *xdata)
05038 {
05039 Database *db = (Database *)dbh->db;
05040 IteratorBE *qbe;
05041 IteratorAtom *temp_array;
05042 rpc_ServerData *data = (rpc_ServerData *)xdata;
05043
05044 if (data)
05045 {
05046 #ifdef IDB_VECT
05047 temp_array = idbNewVect(IteratorAtom, wanted);
05048 #else
05049 temp_array = new IteratorAtom[wanted];
05050 #endif
05051 }
05052 else
05053 temp_array = (IteratorAtom *)atom_array;
05054
05055 if (!qid)
05056 {
05057 *found = 0;
05058 if (data)
05059 code_atom_array(data, temp_array, *found, wanted);
05060 return RPCSuccess;
05061 }
05062
05063 if (qbe = db->getBEQueue()->getIterator(qid))
05064 {
05065 Status status;
05066
05067 if ((status = qbe->scanNext(wanted, found, temp_array)) == Success)
05068 {
05069 if (data)
05070 code_atom_array(data, temp_array, *found, wanted);
05071 return RPCSuccess;
05072 }
05073
05074 return rpcStatusMake(status);
05075 }
05076
05077 *found = 0;
05078 return rpcStatusMake(IDB_ERROR, "invalid query");
05079 }
05080
05081
05082
05083 static void
05084 IDB_schCode(OQLBE *oqlbe, void *pschinfo, void *sch_data)
05085 {
05086 rpc_ServerData *data = (rpc_ServerData *)sch_data;
05087
05088 if (data)
05089 {
05090 data->status = rpc_TempDataUsed;
05091 code_sch_info(oqlbe->getSchemaInfo(),
05092 (Data *)&data->data, &data->size);
05093 }
05094 else
05095 *((SchemaInfo **)pschinfo) = oqlbe->getSchemaInfo();
05096 }
05097
05098 RPCStatus
05099 IDB_oqlCreate(DbHandle *dbh, const char *qstr, int *qid,
05100 void *pschinfo, void *qstr_data,
05101 void *sch_data)
05102 {
05103 Database *db = (Database *)dbh->db;
05104 Status status;
05105
05106 lock_data((Data *)&qstr, qstr_data);
05107 OQLBE *oqlbe = new OQLBE(db, dbh, qstr);
05108
05109 if ((status = oqlbe->getStatus()) == Success)
05110 {
05111 *qid = oqlbe->getQid();
05112
05113 IDB_schCode(oqlbe, pschinfo, sch_data);
05114 unlock_data((Data)qstr, qstr_data);
05115
05116 return RPCSuccess;
05117 }
05118
05119 *qid = 0;
05120
05121 IDB_schCode(oqlbe, pschinfo, sch_data);
05122
05123 db->getBEQueue()->removeOQL(oqlbe);
05124 delete oqlbe;
05125
05126 unlock_data((Data)qstr, qstr_data);
05127 return rpcStatusMake(status);
05128 }
05129
05130 RPCStatus
05131 IDB_oqlDelete(DbHandle *dbh, int qid)
05132 {
05133 Database *db = (Database *)dbh->db;
05134 OQLBE *oqlbe;
05135 if (oqlbe = db->getBEQueue()->getOQL(qid))
05136 {
05137 delete oqlbe;
05138 db->getBEQueue()->removeOQL(qid);
05139 return RPCSuccess;
05140 }
05141
05142 return rpcStatusMake(IDB_ERROR, "invalid query");
05143 }
05144
05145 RPCStatus
05146 IDB_oqlGetResult(DbHandle *dbh, int qid, void *value, void *xdata)
05147 {
05148 Database *db = (Database *)dbh->db;
05149 OQLBE *oqlbe;
05150 Value *temp_value;
05151 rpc_ServerData *data = (rpc_ServerData *)xdata;
05152
05153 if (data)
05154 temp_value = new Value();
05155 else
05156 temp_value = (Value *)value;
05157
05158 if (oqlbe = db->getBEQueue()->getOQL(qid))
05159 {
05160 Status status;
05161
05162 if ((status = oqlbe->getResult(temp_value)) == Success)
05163 {
05164 if (data)
05165 code_value(data, temp_value);
05166 return RPCSuccess;
05167 }
05168
05169 if (data) delete temp_value;
05170 return rpcStatusMake(status);
05171 }
05172
05173 if (data) delete temp_value;
05174 return rpcStatusMake(IDB_ERROR, "invalid query");
05175 }
05176
05177
05178
05179 static const char schema_key[] = ".idb.schema";
05180
05181 static RPCStatus
05182 IDB_schemaClassHeadGet(DbHandle *dbh)
05183 {
05184 eyedbsm::DbHandle *sedbh = dbh->sedbh;
05185 eyedbsm::Status status;
05186 RPCStatus rpc_status;
05187 SchemaHead *sch = &dbh->sch;
05188
05189
05190 if ((rpc_status = IDB_transactionBegin(dbh, 0, True)) ==
05191 RPCSuccess)
05192 {
05193 eyedbsm::Oid toid;
05194 status = eyedbsm::rootEntryGet(sedbh, schema_key,
05195 &sch->oid, sizeof(eyedbsm::Oid));
05196
05197 #ifdef E_XDR
05198 eyedbsm::x2h_oid(&sch->oid, &sch->oid);
05199 #endif
05200 if (status == eyedbsm::Success) {
05201 status = eyedbsm::objectRead(sedbh, IDB_SCH_CNT_INDEX, IDB_SCH_CNT_SIZE,
05202 &sch->cnt, eyedbsm::DefaultLock, 0, 0, &sch->oid);
05203 #ifdef E_XDR
05204 sch->cnt = x2h_32(sch->cnt);
05205 #endif
05206 sch->modify = False;
05207 rpc_status = rpcStatusMake_se(status);
05208 }
05209 else
05210 rpc_status = rpcStatusMake(IDB_INVALID_SCHEMA, "no schema associated with database");
05211
05212 IDB_transactionCommit(dbh, True);
05213
05214 return rpc_status;
05215 }
05216
05217 return rpc_status;
05218 }
05219
05220 static RPCStatus
05221 IDB_schemaClassCreate(DbHandle *dbh)
05222 {
05223 CHECK_WRITE((Database *)dbh->db);
05224 eyedbsm::DbHandle *sedbh = dbh->sedbh;
05225 eyedbsm::Status status;
05226 char temp[IDB_OBJ_HEAD_SIZE + IDB_SCH_CNT_SIZE + IDB_SCH_NAME_SIZE];
05227 Data data = (Data)temp;
05228 Size alloc = sizeof temp;
05229 ObjectHeader hdr;
05230 SchemaHead *sch = &dbh->sch;
05231 Offset offset;
05232
05233 memset(temp, 0, sizeof(temp));
05234 status = eyedbsm::rootEntryGet(sedbh, schema_key,
05235 &sch->oid, sizeof(eyedbsm::Oid));
05236
05237 #ifdef E_XDR
05238 eyedbsm::x2h_oid(&sch->oid, &sch->oid);
05239 #endif
05240
05241 if (status == eyedbsm::Success)
05242 return rpcStatusMake(IDB_SCHEMA_ALREADY_CREATED,
05243 "schema already created");
05244
05245
05246 eyedb_clear(hdr);
05247 hdr.magic = IDB_OBJ_HEAD_MAGIC;
05248 hdr.type = _Schema_Type;
05249 hdr.size = sizeof temp;
05250 memset(&hdr.oid_cl, 0, sizeof(eyedbsm::Oid));
05251
05252 offset = 0;
05253 object_header_code(&data, &offset, &alloc, &hdr);
05254 sch->cnt = 0;
05255 int32_code(&data, &offset, &alloc, &sch->cnt);
05256 string_code(&data, &offset, &alloc, "");
05257
05258 assert(offset <= sizeof(temp));
05259
05260 status = eyedbsm::objectCreate(sedbh, temp,
05261 sizeof(temp), Dataspace::DefaultDspid, &sch->oid);
05262
05263 if (status)
05264 return rpcStatusMake_se(status);
05265
05266
05267 #ifdef E_XDR
05268 eyedbsm::Oid toid;
05269 eyedbsm::h2x_oid(&toid, &sch->oid);
05270 #else
05271 toid = sch->oid;
05272 #endif
05273
05274 status = eyedbsm::rootEntrySet(sedbh, schema_key, &toid,
05275 sizeof(eyedbsm::Oid), eyedbsm::True);
05276
05277 if (status)
05278 return rpcStatusMake_se(status);
05279
05280 sch->modify = False;
05281
05282 return RPCSuccess;
05283 }
05284
05285
05286 static RPCStatus
05287 IDB_makeColl(DbHandle *dbh, Data idr, const eyedbsm::Oid *oid,
05288 const char *name, const CollImpl *collimpl,
05289 Offset offset, Bool lock)
05290 {
05291 CHECK_WRITE((Database *)dbh->db);
05292
05293 CollSet *coll = CollectionPeer::collSet(name, collimpl);
05294 Status status;
05295 eyedbsm::Oid colloid;
05296
05297 if ((status = coll->getStatus()) != Success)
05298 {
05299 coll->release();
05300 return rpcStatusMake(status);
05301 }
05302
05303 if (lock)
05304 CollectionPeer::setLock(coll, True);
05305
05306 status = coll->setDatabase((Database *)dbh->db);
05307 if (status)
05308 return rpcStatusMake(status);
05309
05310
05311 status = coll->realize();
05312
05313
05314
05315
05316
05317
05318
05319
05320 if (status != Success)
05321 return rpcStatusMake(status);
05322
05323 colloid = *coll->getOid().getOid();
05324
05325 eyedbsm::Status se_status;
05326
05327 #ifndef E_XDR
05328 se_status = eyedbsm::objectWrite(dbh->sedbh, offset, sizeof(eyedbsm::Oid),
05329 &colloid, oid);
05330
05331 memcpy(idr + offset, &colloid, sizeof(eyedbsm::Oid));
05332 #else
05333 eyedbsm::Oid xoid;
05334 eyedbsm::h2x_oid(&xoid, &colloid);
05335 se_status = eyedbsm::objectWrite(dbh->sedbh, offset, sizeof(eyedbsm::Oid),
05336 &xoid, oid);
05337
05338 memcpy(idr + offset, &xoid, sizeof(eyedbsm::Oid));
05339
05340
05341 #endif
05342
05343 coll->release();
05344 return rpcStatusMake_se(se_status);
05345 }
05346
05347 static RPCStatus
05348 IDB_collClassCreate(DbHandle *dbh, Data idr, const eyedbsm::Oid *oid,
05349 const char *name, const CollImpl *collimpl)
05350 {
05351 RPCStatus rpc_status;
05352 char tok[256];
05353
05354 Offset offset = IDB_CLASS_EXTENT;
05355 Oid extent_oid;
05356 oid_decode(idr, &offset, extent_oid.getOid());
05357 if (!extent_oid.isValid())
05358 {
05359 sprintf(tok, "%s::extent", name);
05360 rpc_status = IDB_makeColl(dbh, idr, oid, tok, collimpl,
05361 IDB_CLASS_EXTENT, True);
05362 if (rpc_status)
05363 return rpc_status;
05364 }
05365
05366 offset = IDB_CLASS_COMPONENTS;
05367 Oid comp_oid;
05368 oid_decode(idr, &offset, comp_oid.getOid());
05369 if (!comp_oid.isValid())
05370 {
05371 sprintf(tok, "%s::component", name);
05372 return IDB_makeColl(dbh, idr, oid, tok, 0, IDB_CLASS_COMPONENTS,
05373 False);
05374 }
05375
05376 return RPCSuccess;
05377 }
05378
05379 RPCStatus
05380 IDB_collClassRegister(DbHandle *dbh, const eyedbsm::Oid *colloid,
05381 const eyedbsm::Oid *oid, Bool insert)
05382 {
05383 Database *db = (Database *)dbh->db;
05384 CHECK_WRITE(db);
05385 CollectionBE *collbe;
05386
05387 Status status;
05388 if (!(collbe = IDB_getCollBE("collClassRegister", db, dbh, colloid, &status, True)))
05389 return rpcStatusMake(status);
05390
05391 eyedbsm::Idx *idx1;
05392 collbe->getIdx(&idx1, 0);
05393
05394 eyedblib::int32 ind = 1;
05395 eyedbsm::Status se_status;
05396
05397 unsigned char data[sizeof(eyedbsm::Oid)];
05398 oid_code(data, (Data)oid);
05399
05400 if (insert)
05401 se_status = idx1->insert(data, &ind);
05402 else {
05403 eyedblib::int32 ind = 1;
05404 eyedbsm::Boolean found = eyedbsm::False;
05405 se_status = idx1->remove(data, &ind, &found);
05406 if (!found)
05407 return rpcStatusMake(IDB_ERROR,
05408 "instance delete: oid %s not found "
05409 "in collection",
05410 getOidString(oid));
05411 }
05412
05413 if (se_status)
05414 return rpcStatusMake_se(se_status);
05415
05416
05417 int items_cnt;
05418 se_status = eyedbsm::objectRead(dbh->sedbh, IDB_COLL_OFF_ITEMS_CNT,
05419 sizeof(eyedblib::int32), &items_cnt, eyedbsm::DefaultLock, 0, 0, colloid);
05420 if (se_status)
05421 return rpcStatusMake_se(se_status);
05422
05423 items_cnt = x2h_32(items_cnt);
05424 items_cnt += (insert ? 1 : -1);
05425
05426 collbe->setItemsCount(items_cnt);
05427
05428 #ifdef E_XDR
05429 eyedblib::int32 items_cnt_x = h2x_32(items_cnt);
05430 #else
05431 eyedblib::int32 items_cnt_x = items_cnt;
05432 #endif
05433
05434 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_COLL_OFF_ITEMS_CNT,
05435 sizeof(eyedblib::int32), &items_cnt_x, colloid);
05436 if (se_status)
05437 return rpcStatusMake_se(se_status);
05438
05439 return RPCSuccess;
05440 }
05441
05442 static RPCStatus
05443 IDB_collClassUpdate(DbHandle *dbh, Data idr, const eyedbsm::Oid *oid,
05444 const char *name, Bool insert)
05445 {
05446 Database *db = (Database *)dbh->db;
05447 eyedbsm::Oid colloid;
05448
05449 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
05450 Schema *sch = db->getSchema();
05451 Class *cl = sch->getClass(oid_cl);
05452
05453 if (!cl) {
05454 sch->deferredCollRegister(name ? name : "class", oid);
05455 return RPCSuccess;
05456 }
05457
05458 Collection *extent;
05459 Status status = cl->getExtent(extent);
05460 if (status)
05461 return rpcStatusMake(status);
05462
05463 if (!extent) {
05464
05465 status = cl->wholeComplete();
05466 if (status)
05467 return rpcStatusMake(status);
05468 status = cl->getExtent(extent);
05469 if (status)
05470 return rpcStatusMake(status);
05471
05472 if (!extent) {
05473
05474 sch->deferredCollRegister(cl->getName(), oid);
05475 return RPCSuccess;
05476 }
05477 }
05478
05479 colloid = *extent->getOid().getOid();
05480
05481 return IDB_collClassRegister(dbh, &colloid, oid, insert);
05482 }
05483
05484 static const int SCH_INC = 128;
05485
05486 static void
05487 DUMP_SCH_OID(DbHandle *dbh, const eyedbsm::Oid *oid, int cnt)
05488 {
05489 for (int i = 0; i < cnt; i++)
05490 {
05491 eyedbsm::Oid zoid;
05492 eyedbsm::objectRead(dbh->sedbh, IDB_SCH_OID_INDEX(i), sizeof(Oid), &zoid,
05493 eyedbsm::DefaultLock, 0, 0, oid);
05494 printf("%s ", Oid(zoid).getString());
05495 }
05496 printf("\n");
05497 }
05498
05499 static RPCStatus
05500 be_class_name_code(DbHandle *dbh, Data *idr, Offset *offset,
05501 Size *alloc_size, const char *name)
05502 {
05503 int len = strlen(name);
05504 if (len >= IDB_CLASS_NAME_LEN)
05505 {
05506 eyedbsm::Oid data_oid;
05507 RPCStatus rpc_status = IDB_dataCreate(dbh, Dataspace::DefaultDspid,
05508 len+1, (Data)name,
05509 &data_oid, 0);
05510 if (rpc_status) return rpc_status;
05511 char c = IDB_NAME_OUT_PLACE;
05512 char_code(idr, offset, alloc_size, &c);
05513 oid_code (idr, offset, alloc_size, &data_oid);
05514 bound_string_code (idr, offset, alloc_size,
05515 IDB_CLASS_NAME_PAD, 0);
05516 return RPCSuccess;
05517 }
05518
05519 char c = IDB_NAME_IN_PLACE;
05520 char_code(idr, offset, alloc_size, &c);
05521 bound_string_code(idr, offset, alloc_size, IDB_CLASS_NAME_LEN,
05522 name);
05523 return RPCSuccess;
05524 }
05525
05526
05527 static RPCStatus
05528 be_class_name_decode(DbHandle *dbh, Data idr, Offset *offset,
05529 char **name)
05530 {
05531 char c;
05532 char_decode(idr, offset, &c);
05533
05534 if (c == IDB_NAME_OUT_PLACE)
05535 {
05536 eyedbsm::Oid data_oid;
05537 RPCStatus rpc_status;
05538
05539 oid_decode (idr, offset, &data_oid);
05540 unsigned int size;
05541 rpc_status = IDB_dataSizeGet(dbh, &data_oid, &size);
05542 if (rpc_status) return rpc_status;
05543 *name = (char *)malloc(size);
05544 rpc_status = IDB_dataRead(dbh, 0, 0, (Data)*name, 0, &data_oid, 0);
05545 if (rpc_status) return rpc_status;
05546 bound_string_decode (idr, offset, IDB_CLASS_NAME_PAD, 0);
05547 return RPCSuccess;
05548 }
05549
05550 char *s;
05551 bound_string_decode(idr, offset, IDB_CLASS_NAME_LEN, &s);
05552 *name = strdup(s);
05553 return RPCSuccess;
05554 }
05555
05556 static RPCStatus
05557 IDB_classCreate(DbHandle *dbh, short dspid, Data idr, ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata)
05558 {
05559 CHECK_WRITE((Database *)dbh->db);
05560 SchemaHead *sch = &dbh->sch;
05561 rpc_ServerData *data = (rpc_ServerData *)xdata;
05562
05563 if (isOidValid(&sch->oid)) {
05564 eyedbsm::DbHandle *sedbh = dbh->sedbh;
05565 eyedbsm::Status se_status;
05566 RPCStatus rpc_status;
05567 eyedblib::int32 cnt;
05568
05569 Bool skipIfFound = IDBBOOL(hdr->xinfo == IDB_XINFO_CLASS_UPDATE);
05570 hdr->xinfo = 0;
05571
05572 rpc_status = IDB_instanceCreate(dbh, dspid, idr, hdr, oid, data, False);
05573 if (rpc_status) return rpc_status;
05574
05575 Database *db = (Database *)dbh->db;
05576 Offset offset = IDB_CLASS_HEAD_SIZE;
05577 char *name;
05578 rpc_status = be_class_name_decode(dbh, idr, &offset, &name);
05579 if (rpc_status) return rpc_status;
05580
05581
05582 offset = IDB_CLASS_IMPL_TYPE;
05583 IndexImpl *idximpl = 0;
05584 int impl_type;
05585 Status status = IndexImpl::decode(db, idr, offset, idximpl, &impl_type);
05586 if (status) return rpcStatusMake(status);
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597 CollImpl *collimpl = new CollImpl((CollImpl::Type)impl_type, idximpl);
05598 rpc_status = IDB_collClassCreate(dbh, idr, oid, name, collimpl);
05599
05600 collimpl->release();
05601
05602 if (rpc_status != RPCSuccess)
05603 return rpc_status;
05604
05605 if ((sch->cnt % SCH_INC) == 0) {
05606 rpc_status =
05607 IDB_objectSizeModify(dbh,
05608 IDB_SCH_OID_SIZE(sch->cnt + SCH_INC),
05609 &sch->oid);
05610 if (rpc_status != RPCSuccess)
05611 return rpc_status;
05612 }
05613
05614 cnt = sch->cnt + 1;
05615 #ifdef E_XDR
05616 int cnt_x = h2x_32(cnt);
05617 #else
05618 int cnt_x = cnt;
05619 #endif
05620 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_CNT_INDEX, IDB_SCH_CNT_SIZE,
05621 (void *)&cnt_x, &sch->oid);
05622
05623 if (se_status)
05624 return rpcStatusMake_se(se_status);
05625
05626 eyedbsm::Oid oid_x;
05627 #ifdef E_XDR
05628 eyedbsm::h2x_oid(&oid_x, oid);
05629 #else
05630 oid_x = *oid;
05631 #endif
05632 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_OID_INDEX(sch->cnt),
05633 sizeof(eyedbsm::Oid),
05634 (void *)&oid_x, &sch->oid);
05635
05636 if (se_status)
05637 return rpcStatusMake_se(se_status);
05638
05639 #ifdef E_XDR
05640 eyedblib::int32 hdr_type = h2x_32(hdr->type);
05641 #else
05642 eyedblib::int32 hdr_type = hdr->type;
05643 #endif
05644 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_TYPE_INDEX(sch->cnt),
05645 sizeof(eyedblib::int32),
05646 (void *)&hdr_type, &sch->oid);
05647
05648 if (se_status)
05649 return rpcStatusMake_se(se_status);
05650
05651 Data tmpdata = 0;
05652 offset = 0;
05653 Size alloc_size = 0;
05654 rpc_status = be_class_name_code(dbh, &tmpdata, &offset, &alloc_size,
05655 name);
05656 if (rpc_status) return rpc_status;
05657
05658 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_CLSNAME_INDEX(sch->cnt),
05659 IDB_CLASS_NAME_TOTAL_LEN,
05660 (void *)tmpdata, &sch->oid);
05661
05662 free(tmpdata);
05663
05664 if (se_status)
05665 return rpcStatusMake_se(se_status);
05666
05667 sch->cnt++;
05668 sch->modify = True;
05669
05670 Object *o;
05671 Oid _oid(oid);
05672 status = db->makeObject(&_oid, hdr, idr, &o);
05673
05674 free(name); name = 0;
05675 if (status) return rpcStatusMake(status);
05676
05677 assert(o->getOid() == Oid(_oid));
05678 if (!(db->getOpenFlag() & _DBOpenLocal) ||
05679 !strcmp(db->getName(), DBM_Database::getDbName())) {
05680 if (status = db->getSchema()->addClass(o->asClass())) {
05681
05682
05683
05684
05685
05686
05687 }
05688 }
05689
05690 rpc_status = IDB_attrCompPropagate(db, o->asClass(), skipIfFound);
05691 if (rpc_status) return rpc_status;
05692
05693 return IDB_collClassUpdate(dbh, idr, oid, "class", True);
05694 }
05695
05696 return RPCSuccess;
05697 }
05698
05699 static RPCStatus
05700 IDB_collClassCheck(DbHandle *dbh, Offset offset, Data idr,
05701 const eyedbsm::Oid *oid)
05702 {
05703 eyedbsm::Oid colloid;
05704 Offset xoffset = offset;
05705
05706 oid_decode(idr, &xoffset, &colloid);
05707
05708 Oid xoid(colloid);
05709
05710 if (!xoid.isValid())
05711 {
05712 eyedbsm::Status status =
05713 eyedbsm::objectRead(dbh->sedbh, offset, sizeof(eyedbsm::Oid), &colloid,
05714 eyedbsm::DefaultLock, 0, 0, oid);
05715
05716 if (status)
05717 return rpcStatusMake_se(status);
05718
05719 Size alloc_size = offset + sizeof(eyedbsm::Oid);
05720 #ifdef E_XDR
05721 buffer_code(&idr, &offset, &alloc_size, (unsigned char *)&colloid,
05722 sizeof(colloid));
05723 #else
05724 oid_code(&idr, &offset, &alloc_size, &colloid);
05725 #endif
05726 }
05727
05728 return RPCSuccess;
05729 }
05730
05731 static void
05732 trace_oids(Class *cls)
05733 {
05734 printf("TRACE %s cls=%p\n", cls->getName(), cls);
05735 unsigned int attr_cnt;
05736 const Attribute **attrs = cls->getAttributes(attr_cnt);
05737 for (int i = 0; i < attr_cnt; i++)
05738 printf("%s -> %s\n", attrs[i]->getName(), attrs[i]->getAttrCompSetOid().toString());
05739 }
05740
05741 static void
05742 IDB_reportAttrCompSetOids(Class *cls, Data idr)
05743 {
05744 unsigned int attr_cnt;
05745 const Attribute **attrs = cls->getAttributes(attr_cnt);
05746 Offset offset = IDB_CLASS_ATTR_START;
05747 for (int i = 0; i < attr_cnt; i++)
05748 attrs[i]->reportAttrCompSetOid(&offset, idr);
05749 }
05750
05751 static RPCStatus
05752 IDB_classWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, void *xdata)
05753 {
05754 Database *db = (Database *)dbh->db;
05755 Class *cl = db->getSchema()->getClass(*oid);
05756 Object *o;
05757 Oid _oid(oid);
05758 Status status;
05759
05760
05761
05762
05763 IDB_reportAttrCompSetOids(cl, idr);
05764 if ((status = db->getSchema()->suppressClass(cl)) != Success)
05765 return rpcStatusMake(status);
05766
05767 status = db->makeObject(&_oid, hdr, idr, &o);
05768
05769
05770
05771 dbh->sch.modify = True;
05772
05773 if (status == Success)
05774 {
05775 if (!(db->getOpenFlag() & _DBOpenLocal) ||
05776 !strcmp(db->getName(), DBM_Database::getDbName()))
05777 {
05778
05779
05780 if ((status = db->getSchema()->addClass((Class *)o))
05781 != Success)
05782 {
05783 return rpcStatusMake(status);
05784
05785 }
05786 }
05787 }
05788
05789 #if 0
05790 status = db->getSchema()->checkDuplicates();
05791 if (status)
05792 return rpcStatusMake(status);
05793 #endif
05794 status = db->getSchema()->clean(db);
05795 if (status)
05796 return rpcStatusMake(status);
05797
05798 RPCStatus rpc_status;
05799
05800 if (rpc_status = IDB_collClassCheck(dbh, IDB_CLASS_EXTENT, idr, oid))
05801 return rpc_status;
05802
05803 if (rpc_status = IDB_collClassCheck(dbh, IDB_CLASS_COMPONENTS, idr, oid))
05804 return rpc_status;
05805
05806 return IDB_instanceWrite(dbh, idr, hdr, oid, xdata);
05807 }
05808
05809 static void
05810 IDB_suppressClassFromSchema(Database *db, const Oid &cloid)
05811 {
05812 Schema *m = db->getSchema();
05813 const LinkedList *list = m->getClassList();
05814 Class **clx = new Class *[list->getCount()];
05815 int clx_cnt = 0;
05816 LinkedListCursor c(list);
05817
05818 Class *cls;
05819 while (c.getNext((void *&)cls))
05820 if (cls->getOid().compare(cloid))
05821 clx[clx_cnt++] = cls;
05822
05823 for (int i = 0; i < clx_cnt; i++)
05824 m->suppressClass(clx[i]);
05825
05826 delete [] clx;
05827 }
05828
05829 struct ClassHead {
05830 eyedbsm::Oid oid;
05831 eyedblib::int32 type;
05832 char clsname[IDB_CLASS_NAME_TOTAL_LEN];
05833
05834 void x2h() {
05835 eyedbsm::x2h_oid(&oid, &oid);
05836 type = x2h_32(type);
05837 }
05838
05839 void h2x() {
05840 eyedbsm::h2x_oid(&oid, &oid);
05841 type = h2x_32(type);
05842 }
05843 };
05844
05845 static RPCStatus
05846 IDB_removeInstances(DbHandle *dbh, Database *db, Class *cl)
05847 {
05848 Collection *extent;
05849 Status s = cl->getExtent(extent, True);
05850 if (s) return rpcStatusMake(s);
05851
05852 if (!extent)
05853 return rpcStatusMake(Exception::make(IDB_ERROR,
05854 "cannot find extent for "
05855 "class %s %s",
05856 cl->getOid().toString(),
05857 cl->getName()));
05858 IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("removing the %d instance(s) of class %s)\n",
05859 extent->getCount(), cl->getName()));
05860
05861
05862
05863 OidArray oid_arr;
05864 s = extent->getElements(oid_arr);
05865 if (s) return rpcStatusMake(s);
05866
05867 int cnt = oid_arr.getCount();
05868
05869 for (int i = 0; i < cnt; i++) {
05870 Data inv_data;
05871 RPCStatus rpc_status = IDB_objectDelete(dbh, oid_arr[i].getOid(),
05872 0, &inv_data, 0);
05873 if (rpc_status) return rpc_status;
05874 }
05875
05876 s = extent->remove();
05877 if (s) return rpcStatusMake(s);
05878
05879 return RPCSuccess;
05880 }
05881
05882 static RPCStatus
05883 IDB_removeAttrCompSet(Database *db, Class *cl)
05884 {
05885 unsigned int attr_cnt;
05886 const Attribute **attrs = cl->getAttributes(attr_cnt);
05887 for (int n = 0; n < attr_cnt; n++) {
05888 if (!cl->compare(attrs[n]->getClassOwner()))
05889 continue;
05890
05891 Oid attr_comp_oid = attrs[n]->getAttrCompSetOid();
05892 if (attr_comp_oid.isValid()) {
05893 Bool removed;
05894 Status s = db->isRemoved(attr_comp_oid, removed);
05895 if (s)
05896 return rpcStatusMake(s);
05897 if (!removed) {
05898 s = db->removeObject(attr_comp_oid);
05899 printf("removing comp set %s %s\n",
05900 attr_comp_oid.getString(), cl->getName());
05901 if (s) return rpcStatusMake(s);
05902 }
05903 }
05904 }
05905
05906 return RPCSuccess;
05907 }
05908
05909 static RPCStatus
05910 IDB_classDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, unsigned int flags)
05911 {
05912 Database *db = (Database *)dbh->db;
05913 CHECK_WRITE(db);
05914 Class *cl = db->getSchema()->getClass(*oid);
05915 SchemaHead *sch = &dbh->sch;
05916
05917 IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("deleting class(%s, %p, %s, flags=%x)\n", Oid(oid).toString(), cl, cl->getName(), flags));
05918 if (!cl)
05919 return rpcStatusMake(IDB_ERROR, "class %s not found",
05920 Oid(*oid).toString());
05921
05922 if (!isOidValid(&sch->oid))
05923 return rpcStatusMake(IDB_ERROR, "schema oid is null");
05924
05925 RPCStatus rpc_status;
05926
05927 if (flags == Class::RemoveInstances) {
05928 rpc_status = IDB_removeInstances(dbh, db, cl);
05929 if (rpc_status) return rpc_status;
05930
05931
05932 Collection *components;
05933 Status s = cl->getComponents(components, True);
05934 if (s)
05935 return rpcStatusMake(s);
05936 Bool isremoved;
05937 s = db->isRemoved(components->getOid(), isremoved);
05938 if (s)
05939 return rpcStatusMake(s);
05940 if (!isremoved && !components->isRemoved()) {
05941 s = components->remove();
05942 if (s)
05943 return rpcStatusMake(s);
05944 }
05945 }
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963 #if 0
05964 rpc_status = IDB_removeAttrCompSet(db, cl);
05965 if (rpc_status) return rpc_status;
05966 #endif
05967
05968 eyedbsm::DbHandle *sedbh = dbh->sedbh;
05969 eyedbsm::Status se_status;
05970 eyedblib::int32 cnt;
05971
05972 se_status = eyedbsm::objectRead(sedbh, IDB_SCH_CNT_INDEX, IDB_SCH_CNT_SIZE,
05973 (void *)&cnt, eyedbsm::DefaultLock, 0, 0, &sch->oid);
05974
05975 cnt = x2h_32(cnt);
05976
05977 ClassHead *clsheads = new ClassHead[cnt];
05978
05979 for (int k = 0; k < cnt; k++) {
05980 se_status = eyedbsm::objectRead(sedbh, IDB_SCH_OID_INDEX(k),
05981 IDB_SCH_INCR_SIZE,
05982 &clsheads[k], eyedbsm::DefaultLock, 0, 0, &sch->oid);
05983
05984 if (se_status) {
05985 assert(0);
05986 delete [] clsheads;
05987 return rpcStatusMake_se(se_status);
05988 }
05989
05990 clsheads[k].x2h();
05991 }
05992
05993 int i, n;
05994 for (i = 0, n = 0; i < cnt; i++) {
05995 if (n != i)
05996 clsheads[n] = clsheads[i];
05997
05998 if (memcmp(&clsheads[i].oid, oid, sizeof(*oid)))
05999 n++;
06000 }
06001
06002 for (int j = n; j < cnt; j++)
06003 memset(&clsheads[j], 0, sizeof(ClassHead));
06004
06005 if (n == i) {
06006 assert(0);
06007 delete [] clsheads;
06008 return rpcStatusMake
06009 (Exception::make(IDB_ERROR, "incoherent schema for class "
06010 "deletion %s", Oid(oid).toString()));
06011 }
06012
06013 assert(n == cnt-1);
06014 cnt--;
06015 sch->cnt--;
06016 #ifdef E_XDR
06017 eyedblib::int32 cnt_x = h2x_32(cnt);
06018 #else
06019 eyedblib::int32 cnt_x = cnt;
06020 #endif
06021 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_CNT_INDEX, IDB_SCH_CNT_SIZE,
06022 (void *)&cnt_x, &sch->oid);
06023
06024 if (se_status) {
06025 assert(0);
06026 delete [] clsheads;
06027 return rpcStatusMake_se(se_status);
06028 }
06029
06030 for (int k = 0; k < cnt+1; k++) {
06031 clsheads[k].h2x();
06032 se_status = eyedbsm::objectWrite(sedbh, IDB_SCH_OID_INDEX(k),
06033 IDB_SCH_INCR_SIZE,
06034 &clsheads[k], &sch->oid);
06035
06036 if (se_status) {
06037 assert(0);
06038 delete [] clsheads;
06039 return rpcStatusMake_se(se_status);
06040 }
06041 }
06042
06043 delete [] clsheads;
06044
06045 IDB_suppressClassFromSchema(db, cl->getOid());
06046 return IDB_instanceDelete(dbh, idr, hdr, oid);
06047 }
06048
06049
06050 static eyedblib::int32
06051 clean_xinfo(Data idr, ObjectHeader *hdr)
06052 {
06053 eyedblib::int32 xinfo;
06054 Offset offset = IDB_OBJ_HEAD_XINFO_INDEX;
06055
06056 int32_decode(idr, &offset, &xinfo);
06057 if ((xinfo & IDB_XINFO_LOCAL_OBJ) == IDB_XINFO_LOCAL_OBJ)
06058 {
06059 Size alloc_size = hdr->size;
06060 eyedblib::int32 xinfo_n = xinfo & ~IDB_XINFO_LOCAL_OBJ;
06061 offset = IDB_OBJ_HEAD_XINFO_INDEX;
06062 int32_code(&idr, &offset, &alloc_size, &xinfo_n);
06063 }
06064
06065 return xinfo;
06066 }
06067
06068 static void
06069 restore_xinfo(Data idr, ObjectHeader *hdr, eyedblib::int32 xinfo)
06070 {
06071 if ((xinfo & IDB_XINFO_LOCAL_OBJ) == IDB_XINFO_LOCAL_OBJ)
06072 {
06073 Size alloc_size = hdr->size;
06074 Offset offset = IDB_OBJ_HEAD_XINFO_INDEX;
06075 int32_code(&idr, &offset, &alloc_size, &xinfo);
06076 }
06077 }
06078
06079 static eyedblib::int64 current_time()
06080 {
06081 struct timeval tv;
06082
06083 gettimeofday(&tv, 0);
06084
06085 return (eyedblib::int64)tv.tv_sec * 1000000 + tv.tv_usec;
06086 }
06087
06088 static RPCStatus
06089 IDB_instanceCreate(DbHandle *dbh, short dspid, Data idr, ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata, Bool coll_update)
06090 {
06091 CHECK_WRITE((Database *)dbh->db);
06092 eyedbsm::Status se_status;
06093 Offset offset;
06094 rpc_ServerData *data = (rpc_ServerData *)xdata;
06095 Size alloc_size = hdr->size;
06096
06097 eyedblib::int32 xinfo = clean_xinfo(idr, hdr);
06098
06099
06100 eyedblib::int64 t = current_time();
06101
06102 offset = IDB_OBJ_HEAD_CTIME_INDEX;
06103 int64_code(&idr, &offset, &alloc_size, &t);
06104 offset = IDB_OBJ_HEAD_MTIME_INDEX;
06105 int64_code(&idr, &offset, &alloc_size, &t);
06106
06107 if (isOidValid(oid))
06108 se_status = eyedbsm::objectWrite(dbh->sedbh, 0, hdr->size, idr, oid);
06109 else {
06110 se_status = eyedbsm::objectCreate(dbh->sedbh, idr, hdr->size, dspid, oid);
06111 if (!se_status)
06112 ((Database *)dbh->db)->addMarkCreated(Oid(*oid));
06113 }
06114
06115 restore_xinfo(idr, hdr, xinfo);
06116
06117
06118
06119
06120 if (!se_status && coll_update)
06121 return IDB_collClassUpdate(dbh, idr, oid, 0, True);
06122
06123 return rpcStatusMake_se(se_status);
06124 }
06125
06126 static RPCStatus
06127 IDB_instanceWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, void *xdata)
06128 {
06129 CHECK_WRITE((Database *)dbh->db);
06130 eyedbsm::Status status;
06131 eyedblib::int32 k;
06132 Offset offset;
06133 rpc_ServerData *data = (rpc_ServerData *)xdata;
06134 Size alloc_size = hdr->size;
06135
06136 eyedblib::int32 xinfo = clean_xinfo(idr, hdr);
06137
06138 (void)eyedbsm::objectRead(dbh->sedbh, IDB_OBJ_HEAD_CTIME_INDEX, sizeof(int),
06139 &k, eyedbsm::DefaultLock, 0, 0, oid);
06140 #ifdef E_XDR
06141 k = x2h_32(k);
06142 #endif
06143 offset = IDB_OBJ_HEAD_CTIME_INDEX;
06144 int32_code(&idr, &offset, &alloc_size, &k);
06145
06146
06147 eyedblib::int64 t = current_time();
06148
06149 offset = IDB_OBJ_HEAD_MTIME_INDEX;
06150 int64_code(&idr, &offset, &alloc_size, &t);
06151
06152 status = eyedbsm::objectWrite(dbh->sedbh, 0, hdr->size, idr, oid);
06153
06154 restore_xinfo(idr, hdr, xinfo);
06155 return rpcStatusMake_se(status);
06156 }
06157
06158 static RPCStatus
06159 IDB_instanceRead(DbHandle *dbh, Data idr, Data *pidr,
06160 ObjectHeader *hdr, LockMode lockmode, const eyedbsm::Oid *oid,
06161 void *xdata, int minsize)
06162 {
06163 eyedbsm::Status status;
06164 rpc_ServerData *data = (rpc_ServerData *)xdata;
06165 unsigned int size;
06166
06167 #ifdef LOAD_RM_BUG
06168 if (hdr->xinfo & IDB_XINFO_REMOVED)
06169 size = hdr->size = IDB_OBJ_HEAD_SIZE;
06170 #endif
06171 else if (hdr->size < minsize)
06172 size = minsize;
06173 else
06174 size = hdr->size;
06175
06176 if (data)
06177 {
06178 if (size <= data->buff_size)
06179 data->status = rpc_BuffUsed;
06180 else
06181 {
06182 data->status = rpc_TempDataUsed;
06183 data->data = malloc(size);
06184 }
06185
06186 data->size = size;
06187 status = eyedbsm::objectRead(dbh->sedbh, 0, hdr->size, data->data,
06188 (eyedbsm::LockMode)lockmode, 0, 0, oid);
06189 }
06190 else
06191 {
06192 if (pidr)
06193 idr = *pidr = (Data)malloc(size);
06194
06195 status = eyedbsm::objectRead(dbh->sedbh, 0, hdr->size, idr,
06196 (eyedbsm::LockMode)lockmode, 0, 0, oid);
06197 }
06198
06199
06200 return rpcStatusMake_se(status);
06201 }
06202
06203 static RPCStatus
06204 IDB_instanceDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, Bool really)
06205 {
06206 Database *db = (Database *)dbh->db;
06207 CHECK_WRITE(db);
06208 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
06209 Class *cl = db->getSchema()->getClass(oid_cl);
06210 eyedbsm::Status se_status;
06211 Oid toid(oid);
06212
06213 RPCStatus rpc_status = IDB_collClassUpdate(dbh, idr, oid, 0, False);
06214 if (rpc_status)
06215 return rpc_status;
06216
06217 #define DELETED_KEEP
06218
06219
06220
06221
06222
06223
06224
06225
06226
06227
06228
06229
06230
06231
06232
06233
06234
06235
06236
06237
06238
06239
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297 #ifdef DELETED_KEEP
06298 int info;
06299 se_status = eyedbsm::objectRead(dbh->sedbh, IDB_OBJ_HEAD_XINFO_INDEX,
06300 sizeof(int), &info, eyedbsm::DefaultLock, 0, 0, oid);
06301 if (se_status)
06302 return rpcStatusMake_se(se_status);
06303
06304 info |= IDB_XINFO_REMOVED;
06305
06306 #ifdef E_XDR
06307 eyedblib::int32 info_x = h2x_32(info);
06308 #else
06309 eyedblib::int32 info_x = info;
06310 #endif
06311 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_OBJ_HEAD_XINFO_INDEX,
06312 sizeof(int), &info_x, oid);
06313
06314 eyedblib::int64 t = current_time();
06315
06316 #ifdef E_XDR
06317 eyedblib::int64 t_x = h2x_64(t);
06318 #else
06319 eyedblib::int64 t_x = t;
06320 #endif
06321 se_status = eyedbsm::objectWrite(dbh->sedbh, IDB_OBJ_HEAD_MTIME_INDEX,
06322 sizeof(eyedblib::int64), &t_x, oid);
06323 if (se_status)
06324 return rpcStatusMake_se(se_status);
06325
06326
06327 if (really)
06328 return rpcStatusMake_se(eyedbsm::objectDelete(dbh->sedbh, oid));
06329
06330 if (db->isMarkCreated(Oid(oid))) {
06331 se_status = eyedbsm::objectDelete(dbh->sedbh, oid);
06332 return rpcStatusMake_se(se_status);
06333 }
06334
06335 db->getMarkDeleted().insertObject(new Oid(oid));
06336 return RPCSuccess;
06337 #else
06338 se_status = eyedbsm::objectDelete(dbh->sedbh, oid);
06339 #endif
06340 return rpcStatusMake_se(se_status);
06341 }
06342
06343 #if 1
06344 #define IDX_MANAGE(DB, MCL, HDR, IDR, OID, OP)
06345 #else
06346 #define IDX_MANAGE(DB, MCL, HDR, IDR, OID, OP) \
06347 do { \
06348 if (!strcmp((MCL)->getName(), "hashindex") || \
06349 !strcmp((MCL)->getName(), "btreeindex")) \
06350 { \
06351 Status status; \
06352 Object *o; \
06353 Size objsz, psize, vsize; \
06354 objsz = (MCL)->getIDRObjectSize(&psize, &vsize); \
06355 Data nidr = (Data)malloc(objsz); \
06356 memcpy(nidr, idr, psize); \
06357 memset(nidr+psize, 0, vsize); \
06358 if (status = (DB)->makeObject(OID, HDR, nidr, &o)) \
06359 { \
06360 free(nidr); \
06361 return rpcStatusMake(status); \
06362 } \
06363 status = ((Index *)o)->##OP(DB); \
06364 o->release(); \
06365 free(nidr); \
06366 if (status) \
06367 return rpcStatusMake(status); \
06368 } \
06369 } while(0)
06370 #endif
06371
06372
06373 static RPCStatus
06374 IDB_agregatCreate(DbHandle *dbh, short dspid, Data idr, ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata)
06375 {
06376 RPCStatus rpc_status = IDB_instanceCreate(dbh, dspid, idr, hdr, oid, xdata, True);
06377
06378 if (rpc_status != RPCSuccess)
06379 return rpc_status;
06380
06381 Database *db = (Database *)dbh->db;
06382 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
06383 Class *cl = db->getSchema()->getClass(oid_cl);
06384
06385 if (!cl)
06386 {
06387 rpc_status = IDB_agregatDelete(dbh, idr, hdr, oid, True);
06388 if (rpc_status) {
06389
06390 IDB_instanceDelete(dbh, idr, hdr, oid, True);
06391 }
06392 return rpcStatusMake(IDB_ERROR, "creating agregat");
06393 }
06394
06395 Oid _oid(oid);
06396 Status status;
06397
06398 AttrIdxContext idx_ctx;
06399 status = cl->asAgregatClass()->createIndexEntries_realize(db, idr, &_oid,
06400 idx_ctx);
06401 if (status)
06402 {
06403 rpc_status = IDB_agregatDelete(dbh, idr, hdr, oid, True);
06404 if (rpc_status) {
06405
06406 IDB_instanceDelete(dbh, idr, hdr, oid, True);
06407 }
06408 return rpcStatusMake(status);
06409 }
06410
06411 status = cl->asAgregatClass()->createInverses_realize(db, idr, &_oid);
06412
06413 if (status)
06414 {
06415 rpc_status = IDB_agregatDelete(dbh, idr, hdr, oid, True);
06416 if (rpc_status) {
06417
06418 IDB_instanceDelete(dbh, idr, hdr, oid, True);
06419 }
06420 }
06421
06422 if (!status)
06423 IDX_MANAGE(db, cl, hdr, idr, &_oid, create_index);
06424
06425 return rpcStatusMake(status);
06426 }
06427
06428 static RPCStatus
06429 IDB_agregatWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, void *xdata)
06430 {
06431 Database *db = (Database *)dbh->db;
06432 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
06433 Class *cl = db->getSchema()->getClass(oid_cl);
06434 RPCStatus rpc_status;
06435
06436 Oid _oid(oid);
06437 AttrIdxContext idx_ctx;
06438 Status status = ((AgregatClass *)cl)->updateIndexEntries_realize(db, idr, &_oid, idx_ctx);
06439
06440 if (status)
06441 return rpcStatusMake(status);
06442
06443 status = ((AgregatClass *)cl)->updateInverses_realize(db, idr, &_oid);
06444
06445 if (status)
06446 return rpcStatusMake(status);
06447
06448 if (!status)
06449 IDX_MANAGE(db, cl, hdr, idr, &_oid, update_index);
06450
06451 return IDB_instanceWrite(dbh, idr, hdr, oid, xdata);
06452 }
06453
06454 static RPCStatus
06455 IDB_agregatDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, Bool really)
06456 {
06457 Database *db = (Database *)dbh->db;
06458
06459 eyedbsm::Oid oid_cl = ClassOidDecode(idr);
06460 Class *cl = db->getSchema()->getClass(oid_cl);
06461 Oid _oid(oid);
06462 AttrIdxContext idx_ctx;
06463 Status status = cl->asAgregatClass()->removeIndexEntries_realize(db, idr, &_oid, idx_ctx);
06464
06465 if (status)
06466 return rpcStatusMake(status);
06467
06468 status = cl->asAgregatClass()->removeInverses_realize(db, idr, &_oid);
06469
06470 if (status)
06471 return rpcStatusMake(status);
06472
06473 if (!status)
06474 IDX_MANAGE(db, cl, hdr, idr, &_oid, delete_index);
06475
06476 return IDB_instanceDelete(dbh, idr, hdr, oid, really);
06477 }
06478
06479
06480 static RPCStatus
06481 IDB_protectionDescriptionMake(DbHandle *dbh,
06482 Protection *prot, Database *dbm,
06483 eyedbsm::ProtectionDescription *&pdesc)
06484 {
06485 int pusers_cnt = prot->getPusersCount();
06486
06487 if (!pusers_cnt)
06488 return rpcStatusMake(IDB_ERROR, "invalid protection description");
06489
06490 pdesc = (eyedbsm::ProtectionDescription *)
06491 calloc(eyedbsm::protectionDescriptionSize(pusers_cnt), 1);
06492
06493 strcpy(pdesc->name, prot->getName().c_str());
06494 pdesc->nprot = pusers_cnt;
06495
06496 for (int i = 0; i < pusers_cnt; i++)
06497 {
06498 ProtectionUser *puser = prot->getPusers(i);
06499 if (!puser)
06500 return rpcStatusMake(IDB_ERROR, "user #%d is not set in protection description", i);
06501
06502 ProtectionMode mode = puser->getMode();
06503
06504 if (!mode)
06505 mode = (ProtectionMode)0;
06506
06507 UserEntry *user = (UserEntry *)puser->getUser();
06508 if (!puser)
06509 return rpcStatusMake(IDB_ERROR, "user #%d is not set in protection description", i);
06510
06511 pdesc->desc[i].uid = user->uid();
06512 pdesc->desc[i].prot.r = ((mode == ProtRead || mode == ProtRW) ?
06513 eyedbsm::ReadAll : eyedbsm::ReadNone);
06514 pdesc->desc[i].prot.w = ((mode == ProtRW) ? eyedbsm::WriteAll : eyedbsm::WriteNone);
06515
06516 eyedbsm::DbProtectionDescription dbdesc;
06517 dbdesc.uid = pdesc->desc[i].uid;
06518 dbdesc.prot.r = eyedbsm::ReadAll;
06519 dbdesc.prot.w = eyedbsm::WriteAll;
06520 eyedbsm::Status se_status = eyedbsm::dbProtectionAdd(dbh->sedbh, &dbdesc, 1);
06521
06522 if (se_status)
06523 return rpcStatusMake_se(se_status);
06524 }
06525
06526 return RPCSuccess;
06527 }
06528
06529 static RPCStatus
06530 IDB_protectionRealize(DbHandle *dbh, Data idr, ObjectHeader *hdr, eyedbsm::Oid *oid, Bool create)
06531 {
06532 Database *db = (Database *)dbh->db;
06533 Protection *prot;
06534 Oid xoid(oid);
06535 Status status;
06536 RPCStatus rpc_status;
06537
06538 status = db->makeObject(&xoid, hdr, idr, (Object **)&prot);
06539
06540 if (status)
06541 return rpcStatusMake(status);
06542
06543
06544
06545 DBM_Database *dbm;
06546 const char *dbmdb = db->getDBMDB();
06547 rpc_status = IDB_dbmOpen(dbh->ch, dbmdb, True, &dbm);
06548
06549 if (rpc_status)
06550 {
06551 prot->release();
06552 return rpc_status;
06553 }
06554
06555 eyedbsm::ProtectionDescription *pdesc;
06556
06557 rpc_status = IDB_protectionDescriptionMake(dbh, prot, dbm, pdesc);
06558
06559 if (rpc_status)
06560 {
06561 prot->release();
06562 return rpc_status;
06563 }
06564
06565 eyedbsm::Oid poid;
06566
06567 if (create)
06568 {
06569 rpc_status = rpcStatusMake_se
06570 (eyedbsm::protectionCreate(dbh->sedbh, pdesc, &poid));
06571 if (!rpc_status)
06572 {
06573 prot->setPoid(poid);
06574 Size psize;
06575 (void)prot->getClass()->getIDRObjectSize(&psize);
06576 memcpy(idr, prot->getIDR(), psize);
06577
06578 }
06579 }
06580 else
06581 {
06582
06583 rpc_status = rpcStatusMake_se
06584 (eyedbsm::protectionModify(dbh->sedbh, pdesc, prot->getPoid().getOid()));
06585 }
06586
06587 free(pdesc);
06588 prot->release();
06589 return rpc_status;
06590 }
06591
06592 static RPCStatus
06593 IDB_protectionGetPoid(DbHandle *dbh, const eyedbsm::Oid *prot_oid, eyedbsm::Oid &poid)
06594 {
06595 Oid xoid(prot_oid);
06596 Status status;
06597 RPCStatus rpc_status;
06598 Protection *prot;
06599 Database *db = (Database *)dbh->db;
06600
06601 status = db->loadObject(&xoid, (Object **)&prot);
06602
06603 if (status)
06604 return rpcStatusMake(status);
06605
06606 poid = *prot->getPoid().getOid();
06607 prot->release();
06608
06609 return RPCSuccess;
06610 }
06611
06612 static RPCStatus
06613 IDB_protectionCreate(DbHandle *dbh, short dspid, Data idr, ObjectHeader *hdr, eyedbsm::Oid *oid, void *xdata, Bool coll_update)
06614 {
06615 RPCStatus rpc_status;
06616
06617 rpc_status = IDB_protectionRealize(dbh, idr, hdr, oid, True);
06618 if (rpc_status)
06619 return rpc_status;
06620
06621 return IDB_agregatCreate(dbh, dspid, idr, hdr, oid, xdata);
06622 }
06623
06624 static RPCStatus
06625 IDB_protectionWrite(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid, void *xdata)
06626 {
06627 RPCStatus rpc_status;
06628
06629 rpc_status = IDB_protectionRealize(dbh, idr, hdr, (eyedbsm::Oid *)oid, False);
06630 if (rpc_status)
06631 return rpc_status;
06632
06633 return IDB_agregatWrite(dbh, idr, hdr, oid, xdata);
06634 }
06635
06636 static RPCStatus
06637 IDB_protectionDelete(DbHandle *dbh, Data idr, ObjectHeader *hdr, const eyedbsm::Oid *oid)
06638 {
06639 printf("IDB_protectionDelete()\n");
06640 return IDB_agregatDelete(dbh, idr, hdr, oid);
06641 }
06642
06643 RPCStatus
06644 IDB_objectProtectionSet(DbHandle *dbh, const eyedbsm::Oid *obj_oid, const eyedbsm::Oid *prot_oid)
06645 {
06646 Oid xobj_oid(obj_oid);
06647 Oid xprot_oid(prot_oid);
06648 RPCStatus rpc_status;
06649 eyedbsm::Oid rprot_oid;
06650
06651
06652
06653
06654
06655
06656 if (xprot_oid.isValid())
06657 {
06658 rpc_status = IDB_protectionGetPoid(dbh, prot_oid, rprot_oid);
06659
06660 if (rpc_status)
06661 return rpc_status;
06662 }
06663 else
06664 memset(&rprot_oid, 0, sizeof(rprot_oid));
06665
06666 rpc_status = rpcStatusMake_se(eyedbsm::objectProtectionSet(dbh->sedbh, obj_oid, &rprot_oid));
06667
06668 if (!rpc_status)
06669 {
06670 ObjectHeader hdr;
06671 rpc_status = IDB_objectHeaderRead(dbh, obj_oid, &hdr);
06672 if (rpc_status)
06673 return rpc_status;
06674 hdr.oid_prot = *prot_oid;
06675 return IDB_objectHeaderWrite(dbh, obj_oid, &hdr);
06676 }
06677
06678 return rpc_status;
06679 }
06680
06681 RPCStatus
06682 IDB_objectProtectionGet(DbHandle *dbh, const eyedbsm::Oid *obj_oid, eyedbsm::Oid *prot_oid)
06683 {
06684 Oid xobj_oid(obj_oid);
06685
06686 ObjectHeader hdr;
06687 RPCStatus rpc_status = IDB_objectHeaderRead(dbh, obj_oid, &hdr);
06688 if (rpc_status)
06689 return rpc_status;
06690 *prot_oid = hdr.oid_prot;
06691 return RPCSuccess;
06692
06693 }
06694
06695 #ifdef PASSWD_FILE
06696 static void
06697 get_dbm_passwd(const char *passwdfile)
06698 {
06699 int fd = open(passwdfile, O_RDONLY);
06700
06701 if (fd < 0)
06702 {
06703 fprintf(stderr, "eyedbd: cannot open passwd file '%s' for reading\n",
06704 passwdfile);
06705 exit(1);
06706 }
06707
06708 if (read(fd, dbm_passwd, sizeof(dbm_passwd)) != sizeof(dbm_passwd))
06709 {
06710 fprintf(stderr, "eyedbd: error while reading passwd file '%s'\n",
06711 passwdfile);
06712 exit(1);
06713 }
06714
06715 close(fd);
06716 }
06717 #endif
06718
06719
06720
06721 void new_handler()
06722 {
06723 static Bool _new = False;
06724 if (!_new)
06725 {
06726 char tok[128];
06727 sprintf(tok, "PID %d: Ran out of memory\n", rpc_getpid());
06728 write(2, tok, strlen(tok));
06729
06730 _new = True;
06731 quit_handler(db_list, 0);
06732 }
06733
06734 exit(1);
06735 }
06736
06737 static int timeout = -1;
06738
06739 void
06740 config_init()
06741 {
06742 const char *s;
06743 #ifdef PASSWD_FILE
06744 const char *passwdfile;
06745
06746 if (edb_passwdfile)
06747 passwdfile = strdup(edb_passwdfile);
06748 else if (s = eyedb::getConfigValue("passwd_file"))
06749 passwdfile = strdup(s);
06750 else
06751 {
06752 fprintf(stderr, "eyedbd: EyeDB passwd file is not set, check your 'sv_passwd_file' configuration variable or the '-passwdfile' command line option\n");
06753 exit(1);
06754 }
06755 #endif
06756
06757 if (settimeout)
06758 {
06759 if (timeout >= 0)
06760 settimeout(timeout);
06761 else
06762 {
06763 const char *x = eyedb::ServerConfig::getSValue("timeout");
06764 if (x)
06765 settimeout(atoi(x));
06766 }
06767 }
06768
06769 #ifdef PASSWD_FILE
06770 get_dbm_passwd(passwdfile);
06771 #endif
06772
06773
06774
06775
06776
06777
06778
06779
06780
06781
06782
06783
06784
06785
06786
06787
06788
06789 }
06790
06791 void
06792 IDB_init(const char *databasedir,
06793 const char *dummy,
06794 void *xsesslog, int _timeout)
06795 {
06796
06797 sesslogTempl = (SessionLog *)xsesslog;
06798 set_new_handler(new_handler);
06799
06800 #ifdef PASSWD_FILE
06801 edb_passwdfile = _passwdfile;
06802 #endif
06803 timeout = _timeout;
06804
06805 eyedb::init();
06806 config_init();
06807
06808 if (databasedir)
06809 ServerConfig::getInstance()->setValue("databasedir", databasedir);
06810 }
06811
06812 RPCStatus
06813 IDB_setLogMask(eyedblib::int64)
06814 {
06815 return RPCSuccess;
06816 }
06817
06818 RPCStatus
06819 IDB_getDefaultDataspace(DbHandle * dbh, int *_dspid)
06820 {
06821 short dspid;
06822 eyedbsm::Status s = eyedbsm::dspGetDefault(dbh->sedbh, &dspid);
06823 if (s)
06824 return rpcStatusMake_se(s);
06825
06826 *_dspid = dspid;
06827 return RPCSuccess;
06828 }
06829
06830 RPCStatus
06831 IDB_setDefaultDataspace(DbHandle * dbh, int dspid)
06832 {
06833 std::string dataspace = str_convert((long)dspid);
06834 eyedbsm::Status s = eyedbsm::dspSetDefault(dbh->sedbh, dataspace.c_str());
06835
06836 if (!s) return RPCSuccess;
06837 return rpcStatusMake_se(s);
06838 }
06839
06840 RPCStatus
06841 IDB_dataspaceSetCurrentDatafile(DbHandle * dbh, int dspid, int datid)
06842 {
06843 std::string dataspace = str_convert((long)dspid);
06844 std::string datafile = str_convert((long)datid);
06845 eyedbsm::Status s = eyedbsm::dspSetCurDat(dbh->sedbh, dataspace.c_str(),
06846 datafile.c_str());
06847 if (!s) return RPCSuccess;
06848 return rpcStatusMake_se(s);
06849 }
06850
06851 RPCStatus
06852 IDB_dataspaceGetCurrentDatafile(DbHandle * dbh, int dspid, int * datid)
06853 {
06854 std::string dataspace = str_convert((long)dspid);
06855 short datid_s;
06856 eyedbsm::Status s = eyedbsm::dspGetCurDat(dbh->sedbh, dataspace.c_str(), &datid_s);
06857
06858 if (!s) {
06859 *datid = datid_s;
06860 return RPCSuccess;
06861 }
06862
06863 return rpcStatusMake_se(s);
06864 }
06865
06866 RPCStatus
06867 IDB_realizeDefaultIndexDataspace(DbHandle * dbh, const eyedbsm::Oid * idxoid,
06868 int * dspid, int type, Bool get)
06869 {
06870 eyedbsm::Idx *idx;
06871
06872 if (type)
06873 idx = new eyedbsm::HIdx(dbh->sedbh, idxoid);
06874 else
06875 idx = new eyedbsm::BIdx(dbh->sedbh, *idxoid);
06876
06877 eyedbsm::Status s = idx->status();
06878 if (s) {
06879 delete idx;
06880 return rpcStatusMake_se(s);
06881 }
06882
06883 if (get)
06884 *dspid = idx->getDefaultDspid();
06885 else
06886 idx->setDefaultDspid(*dspid);
06887
06888 delete idx;
06889 return RPCSuccess;
06890 }
06891
06892 RPCStatus
06893 IDB_getDefaultIndexDataspace(DbHandle * dbh, const eyedbsm::Oid * oid, int type, int * dspid)
06894 {
06895 return IDB_realizeDefaultIndexDataspace(dbh, oid, dspid, type, True);
06896 }
06897
06898 RPCStatus
06899 IDB_setDefaultIndexDataspace(DbHandle * dbh, const eyedbsm::Oid * oid, int type, int dspid)
06900 {
06901 return IDB_realizeDefaultIndexDataspace(dbh, oid, &dspid, type, False);
06902 }
06903
06904 static RPCStatus
06905 IDB_getIndexObjects(DbHandle * dbh, const eyedbsm::Oid * idxoid, int type,
06906 eyedbsm::Oid *&oids, unsigned int &cnt)
06907 {
06908 cnt = 0;
06909 eyedbsm::Idx *idx;
06910
06911 if (type)
06912 idx = new eyedbsm::HIdx(dbh->sedbh, idxoid);
06913 else
06914 idx = new eyedbsm::BIdx(dbh->sedbh, *idxoid);
06915
06916 eyedbsm::Status s = idx->status();
06917 if (s) {
06918 delete idx;
06919 return rpcStatusMake_se(s);
06920 }
06921
06922 time_t t0, t1;
06923 time(&t0);
06924
06925 s = idx->getObjects(oids, cnt);
06926 time(&t1);
06927
06928
06929 delete idx;
06930 return rpcStatusMake_se(s);
06931 }
06932
06933 RPCStatus
06934 IDB_getIndexLocations(DbHandle * dbh, const eyedbsm::Oid * oid, int type,
06935 Data * locarr, void *xlocarr)
06936 {
06937 eyedbsm::Oid *oids;
06938 unsigned int cnt;
06939 RPCStatus rpc_status = IDB_getIndexObjects(dbh, oid, type, oids, cnt);
06940 if (rpc_status) return rpc_status;
06941 rpc_status = IDB_getObjectsLocations(dbh, oids, cnt, 0, locarr, xlocarr);
06942 free(oids);
06943 return rpc_status;
06944 }
06945
06946 RPCStatus
06947 IDB_moveIndex(DbHandle * dbh, const eyedbsm::Oid * oid, int type, int dspid)
06948 {
06949 eyedbsm::Oid *oids;
06950 unsigned int cnt;
06951 RPCStatus rpc_status = IDB_getIndexObjects(dbh, oid, type, oids, cnt);
06952 if (rpc_status) return rpc_status;
06953
06954 rpc_status = IDB_moveObjects(dbh, oids, cnt, dspid, 0);
06955 free(oids);
06956 return rpc_status;
06957 }
06958
06959 extern eyedbsm::Oid *
06960 oidArrayToOids(const OidArray &oid_arr, unsigned int &cnt);
06961
06962 RPCStatus
06963 IDB_getInstanceClassLocations(DbHandle * dbh, const eyedbsm::Oid * oid,
06964 int subclasses, Data * locarr, void *xlocarr)
06965 {
06966 Database *db = (Database *)dbh->db;
06967 const Class *cls = db->getSchema()->getClass(*oid);
06968 if (!cls)
06969 return rpcStatusMake(IDB_ERROR, "class %s not found",
06970 Oid(*oid).toString());
06971 Iterator iter(const_cast<Class *>(cls), IDBBOOL(subclasses));
06972 OidArray oid_arr;
06973 Status s = iter.scan(oid_arr);
06974 if (s) return rpcStatusMake(s);
06975
06976 unsigned int cnt;
06977 eyedbsm::Oid *oids = oidArrayToOids(oid_arr, cnt);
06978 RPCStatus rpc_status = IDB_getObjectsLocations(dbh, oids, cnt, 0, locarr,
06979 xlocarr);
06980 delete [] oids;
06981 return rpc_status;
06982 }
06983
06984 RPCStatus
06985 IDB_moveInstanceClass(DbHandle * dbh, const eyedbsm::Oid * oid, int subclasses,
06986 int dspid)
06987 {
06988 Database *db = (Database *)dbh->db;
06989 const Class *cls = db->getSchema()->getClass(*oid);
06990 if (!cls)
06991 return rpcStatusMake(IDB_ERROR, "class %s not found",
06992 Oid(*oid).toString());
06993 Iterator iter(const_cast<Class *>(cls), IDBBOOL(subclasses));
06994 OidArray oid_arr;
06995 Status s = iter.scan(oid_arr);
06996 if (s) return rpcStatusMake(s);
06997
06998 unsigned int cnt;
06999 eyedbsm::Oid *oids = oidArrayToOids(oid_arr, cnt);
07000 if (!cnt) return RPCSuccess;
07001 RPCStatus rpc_status = IDB_moveObjects(dbh, oids, cnt, dspid, 0);
07002 delete [] oids;
07003 return rpc_status;
07004 }
07005
07006 RPCStatus
07007 IDB_getObjectsLocations(DbHandle * dbh, const eyedbsm::Oid * yoids, unsigned int oid_cnt, void *xoids, Data * locarr, void *xlocarr)
07008 {
07009 lock_data((Data *)&yoids, xoids);
07010
07011 const eyedbsm::Oid * oids;
07012 if (xoids)
07013 oids = decode_oids((Data)yoids, &oid_cnt);
07014 else
07015 oids = yoids;
07016
07017 eyedbsm::ObjectLocation *se_locarr = new eyedbsm::ObjectLocation[oid_cnt];
07018 eyedbsm::Status s = eyedbsm::objectsLocationGet(dbh->sedbh, oids, se_locarr, oid_cnt);
07019
07020 if (xlocarr) {
07021 rpc_ServerData *data = (rpc_ServerData *)xlocarr;
07022 data->status = rpc_TempDataUsed;
07023 data->data = code_locarr(se_locarr, oids, oid_cnt, &data->size);
07024 }
07025 else
07026 make_locarr(se_locarr, oids, oid_cnt, locarr);
07027
07028 if (xoids)
07029 delete [] oids;
07030
07031 delete [] se_locarr;
07032
07033 unlock_data((Data)yoids, xoids);
07034 return rpcStatusMake_se(s);
07035 }
07036
07037 RPCStatus
07038 IDB_moveObjects(DbHandle * dbh, const eyedbsm::Oid *yoids, unsigned oid_cnt,
07039 int dspid, void *xoids)
07040 {
07041 CHECK_WRITE((Database *)dbh->db);
07042 lock_data((Data *)&yoids, xoids);
07043
07044 const eyedbsm::Oid * oids;
07045 if (xoids)
07046 oids = decode_oids((Data)yoids, &oid_cnt);
07047 else
07048 oids = yoids;
07049
07050 eyedbsm::Status s = eyedbsm::objectsMoveDsp(dbh->sedbh, oids, oid_cnt, dspid);
07051
07052 if (xoids)
07053 delete [] oids;
07054
07055 unlock_data((Data)yoids, xoids);
07056 return rpcStatusMake_se(s);
07057 }
07058
07059 RPCStatus
07060 IDB_getAttributeLocations(DbHandle * dbh, const eyedbsm::Oid * clsoid, int attrnum, Data * locarr, void *xlocarr)
07061 {
07062 return RPCSuccess;
07063 }
07064
07065 RPCStatus
07066 IDB_moveAttribute(DbHandle * dbh, const eyedbsm::Oid * clsoid, int attrnum, int dspid)
07067 {
07068 return RPCSuccess;
07069 }
07070
07071 RPCStatus
07072 IDB_createDatafile(DbHandle * dbh, const char * datfile, const char * name, int maxsize, int slotsize, int dtype)
07073 {
07074 mode_t file_mask;
07075 const char *file_group;
07076 RPCStatus rpc_status = get_file_mask_group(file_mask, file_group);
07077 if (rpc_status)
07078 return rpc_status;
07079
07080 eyedbsm::Status s = eyedbsm::datCreate(dbh->sedbh, datfile, name, maxsize,
07081 eyedbsm::BitmapType, slotsize,
07082 (eyedbsm::DatType)dtype, file_mask, file_group);
07083
07084 return rpcStatusMake_se(s);
07085 }
07086
07087 RPCStatus
07088 IDB_deleteDatafile(DbHandle * dbh, int datid)
07089 {
07090 eyedbsm::Status s = eyedbsm::datDelete(dbh->sedbh,
07091 str_convert((long)datid).c_str());
07092 return rpcStatusMake_se(s);
07093 }
07094
07095 RPCStatus
07096 IDB_moveDatafile(DbHandle * dbh, int datid, const char * newdatafile)
07097 {
07098 eyedbsm::Status s = eyedbsm::datMove(dbh->sedbh,
07099 str_convert((long)datid).c_str(),
07100 newdatafile);
07101 return rpcStatusMake_se(s);
07102 }
07103
07104 RPCStatus
07105 IDB_defragmentDatafile(DbHandle * dbh, int datid)
07106 {
07107 mode_t file_mask;
07108 const char *file_group;
07109 RPCStatus rpc_status = get_file_mask_group(file_mask, file_group);
07110 if (rpc_status)
07111 return rpc_status;
07112
07113 eyedbsm::Status s = eyedbsm::datDefragment(dbh->sedbh,
07114 str_convert((long)datid).c_str(), file_mask, file_group);
07115 return rpcStatusMake_se(s);
07116 }
07117
07118 RPCStatus
07119 IDB_resizeDatafile(DbHandle * dbh, int datid, unsigned int size)
07120 {
07121 eyedbsm::Status s = eyedbsm::datResize(dbh->sedbh,
07122 str_convert((long)datid).c_str(),
07123 size);
07124 return rpcStatusMake_se(s);
07125 }
07126
07127 RPCStatus
07128 IDB_getDatafileInfo(DbHandle * dbh, int datid, Data * info,
07129 void *xinfo)
07130 {
07131 eyedbsm::DatafileInfo datinfo;
07132 eyedbsm::Status s = eyedbsm::datGetInfo(dbh->sedbh,
07133 str_convert((long)datid).c_str(),
07134 &datinfo);
07135 if (xinfo) {
07136 rpc_ServerData *data = (rpc_ServerData *)xinfo;
07137 data->status = rpc_TempDataUsed;
07138 data->data = code_datinfo(&datinfo, &data->size);
07139 }
07140 else
07141 make_datinfo(&datinfo, info);
07142
07143 return rpcStatusMake_se(s);
07144 }
07145
07146 RPCStatus
07147 IDB_renameDatafile(DbHandle * dbh, int datid, const char * name)
07148 {
07149 eyedbsm::Status s = eyedbsm::datRename(dbh->sedbh,
07150 str_convert((long)datid).c_str(),
07151 name);
07152 return rpcStatusMake_se(s);
07153 }
07154
07155 RPCStatus
07156 IDB_createDataspace(DbHandle * dbh, const char * dspname, void *ydatids,
07157 unsigned int datafile_cnt, void *xdatids)
07158 {
07159 CHECK_WRITE((Database *)dbh->db);
07160 lock_data((Data *)&ydatids, xdatids);
07161
07162 const char **datids;
07163 if (xdatids)
07164 datids = decode_datids((Data)ydatids, &datafile_cnt);
07165 else
07166 datids = (const char **)ydatids;
07167
07168 eyedbsm::Status s = eyedbsm::dspCreate(dbh->sedbh, dspname, datids, datafile_cnt);
07169 if (xdatids)
07170 free(datids);
07171
07172 unlock_data((Data)ydatids, xdatids);
07173 return rpcStatusMake_se(s);
07174 }
07175
07176 RPCStatus
07177 IDB_updateDataspace(DbHandle * dbh, int dspid, void *ydatids,
07178 unsigned int datafile_cnt, void *xdatids,
07179 int flags, int orphan_dspid)
07180 {
07181 CHECK_WRITE((Database *)dbh->db);
07182 lock_data((Data *)&ydatids, xdatids);
07183
07184 const char **datids;
07185 if (xdatids)
07186 datids = decode_datids((Data)ydatids, &datafile_cnt);
07187 else
07188 datids = (const char **)ydatids;
07189
07190 eyedbsm::Status s = eyedbsm::dspUpdate(dbh->sedbh,
07191 str_convert((long)dspid).c_str(),
07192 datids, datafile_cnt,
07193 flags, orphan_dspid);
07194 if (xdatids)
07195 free(datids);
07196
07197 unlock_data((Data)ydatids, xdatids);
07198 return rpcStatusMake_se(s);
07199 }
07200
07201 RPCStatus
07202 IDB_deleteDataspace(DbHandle * dbh, int dspid)
07203 {
07204 eyedbsm::Status s = eyedbsm::dspDelete(dbh->sedbh,
07205 str_convert((long)dspid).c_str());
07206 return rpcStatusMake_se(s);
07207 }
07208
07209 RPCStatus
07210 IDB_renameDataspace(DbHandle * dbh, int dspid, const char * name)
07211 {
07212 eyedbsm::Status s = eyedbsm::dspRename(dbh->sedbh,
07213 str_convert((long)dspid).c_str(),
07214 name);
07215 return rpcStatusMake_se(s);
07216 }
07217
07218 static Status
07219 IDB_makeDatabase(ConnHandle *ch, const char *dbmdb, const char *dbname,
07220 int dbid, int flags, DbHandle *ldbh,
07221 rpcDB_LocalDBContext *ldbctx,
07222 const eyedbsm::Oid *sch_oid, unsigned int version, Database *&db)
07223 {
07224 Status status;
07225 db = new Database(dbname, dbmdb);
07226
07227 Oid _oid(sch_oid);
07228
07229 if ((status = db->set(ch, dbid, flags, ldbh, ldbctx, &_oid, version)) == Success)
07230 return status;
07231 else
07232 {
07233 db->release();
07234 return status;
07235 }
07236 }
07237
07238
07239
07240
07241
07242
07243
07244
07245
07246
07247
07248
07249
07250
07251
07252 void object_epilogue(void *xdb, const eyedbsm::Oid *oid,
07253 Data inv_data, Bool creating)
07254 {
07255
07256
07257
07258
07259
07260
07261 if (!inv_data)
07262 return;
07263
07264 Database *db = (Database *)xdb;
07265
07266 LinkedList inv_list;
07267
07268 InvOidContext::decode(inv_data, inv_list);
07269
07270 free(inv_data);
07271
07272 LinkedListCursor c(inv_list);
07273 InvOidContext *ctx;
07274
07275 #ifdef EPITRACE
07276 if (inv_list.getCount())
07277 printf("object_epilogue -> %d\n", inv_list.getCount());
07278 #endif
07279
07280 for (int i = 0; c.getNext((void *&)ctx); i++)
07281 {
07282 #ifdef EPITRACE
07283 printf("object_epilogue[%d] -> %s %d %d %s\n",
07284 i, ctx->objoid.toString(), ctx->attr_num, ctx->attr_offset,
07285 ctx->valoid.toString());
07286 #endif
07287 Object *o = db->getCacheObject(ctx->objoid);
07288 if (o)
07289 {
07290 #ifdef EPITRACE
07291 printf("object_epilogue: updating object %s\n",
07292 ctx->objoid.toString());
07293 #endif
07294
07295
07296 eyedbsm::Oid toid;
07297 eyedbsm::h2x_oid(&toid, ctx->valoid.getOid());
07298 mcp(o->getIDR()+ctx->attr_offset, &toid, sizeof(Oid));
07299 }
07300
07301 delete ctx;
07302 }
07303 }
07304
07305 eyedbsm::DbHandle *
07306 IDB_get_se_DbHandle(Database *db)
07307 {
07308 return database_getDbHandle(db)->sedbh;
07309 }
07310
07311
07312
07313
07314
07315 Data code_oids(const eyedbsm::Oid *oids, unsigned int oid_cnt, int *size)
07316 {
07317 Data idr = 0;
07318 Size alloc_size = 0;
07319 Offset offset = 0;
07320 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&oid_cnt);
07321
07322 for (int i = 0; i < oid_cnt; i++)
07323 oid_code(&idr, &offset, &alloc_size, &oids[i]);
07324
07325 *size = offset;
07326 return idr;
07327 }
07328
07329 static eyedbsm::Oid *
07330 decode_oids(Data idr, unsigned int *poid_cnt)
07331 {
07332 *poid_cnt = 0;
07333 Offset offset = 0;
07334 int32_decode(idr, &offset, (eyedblib::int32 *)poid_cnt);
07335 eyedbsm::Oid *oids = new eyedbsm::Oid[*poid_cnt];
07336 for (int i = 0; i < *poid_cnt; i++)
07337 oid_decode(idr, &offset, &oids[i]);
07338 return oids;
07339 }
07340
07341 void
07342 decode_locarr(Data idr, void *xlocarr)
07343 {
07344 Offset offset = 0;
07345 eyedblib::int32 cnt;
07346 int32_decode(idr, &offset, &cnt);
07347
07348 ObjectLocation *locs = new ObjectLocation[cnt];
07349 for (int i = 0; i < cnt; i++) {
07350 eyedbsm::Oid oid;
07351 eyedblib::int16 dspid;
07352 eyedblib::int16 datid;
07353 ObjectLocation::Info info;
07354
07355 oid_decode(idr, &offset, &oid);
07356 int16_decode(idr, &offset, &dspid);
07357 int16_decode(idr, &offset, &datid);
07358 int32_decode(idr, &offset, (eyedblib::int32 *)&info.size);
07359 int32_decode(idr, &offset, (eyedblib::int32 *)&info.slot_start_num);
07360 int32_decode(idr, &offset, (eyedblib::int32 *)&info.slot_end_num);
07361 int32_decode(idr, &offset, (eyedblib::int32 *)&info.dat_start_pagenum);
07362 int32_decode(idr, &offset, (eyedblib::int32 *)&info.dat_end_pagenum);
07363 int32_decode(idr, &offset, (eyedblib::int32 *)&info.omp_start_pagenum);
07364 int32_decode(idr, &offset, (eyedblib::int32 *)&info.omp_end_pagenum);
07365 int32_decode(idr, &offset, (eyedblib::int32 *)&info.dmp_start_pagenum);
07366 int32_decode(idr, &offset, (eyedblib::int32 *)&info.dmp_end_pagenum);
07367
07368 locs[i].set(oid, dspid, datid, info);
07369 }
07370
07371 ((ObjectLocationArray *)xlocarr)->set(locs, cnt);
07372 }
07373
07374 static Data
07375 code_locarr(const eyedbsm::ObjectLocation *se_locarr, const eyedbsm::Oid *oids,
07376 unsigned int cnt, int *size)
07377 {
07378 Data idr = 0;
07379 Size alloc_size = 0;
07380 Offset offset = 0;
07381
07382 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&cnt);
07383 for (int i = 0; i < cnt; i++) {
07384 const eyedbsm::ObjectLocation *loc = &se_locarr[i];
07385
07386 oid_code(&idr, &offset, &alloc_size, &oids[i]);
07387 int16_code(&idr, &offset, &alloc_size, &loc->dspid);
07388 int16_code(&idr, &offset, &alloc_size, &loc->datid);
07389 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->size);
07390 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->slot_start_num);
07391 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->slot_end_num);
07392 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->dat_start_pagenum);
07393 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->dat_end_pagenum);
07394 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->omp_start_pagenum);
07395 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->omp_end_pagenum);
07396 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->dmp_start_pagenum);
07397 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&loc->dmp_end_pagenum);
07398 }
07399
07400 *size = offset;
07401 return idr;
07402 }
07403
07404 static void
07405 make_locarr(const eyedbsm::ObjectLocation *se_locarr, const eyedbsm::Oid *oids,
07406 unsigned int cnt, void *xlocarr)
07407 {
07408 ObjectLocationArray *locarr = (ObjectLocationArray *)xlocarr;
07409 ObjectLocation *locs = new ObjectLocation[cnt];
07410 for (int i = 0; i < cnt; i++) {
07411 const eyedbsm::ObjectLocation *loc = &se_locarr[i];
07412
07413 ObjectLocation::Info info;
07414 info.size = loc->size;
07415 info.slot_start_num = loc->slot_start_num;
07416 info.slot_end_num = loc->slot_end_num;
07417 info.dat_start_pagenum = loc->dat_start_pagenum;
07418 info.dat_end_pagenum = loc->dat_end_pagenum;
07419 info.omp_start_pagenum = loc->omp_start_pagenum;
07420 info.omp_end_pagenum = loc->omp_end_pagenum;
07421 info.dmp_start_pagenum = loc->dmp_start_pagenum;
07422 info.dmp_end_pagenum = loc->dmp_end_pagenum;
07423
07424 locs[i].set(oids[i], loc->dspid, loc->datid, info);
07425 }
07426
07427 locarr->set(locs, cnt);
07428 }
07429
07430 Data
07431 code_dbdescription(const DbCreateDescription *dbdesc, int *size)
07432 {
07433 Data idr = 0;
07434 Size alloc_size = 0;
07435 Offset offset = 0;
07436 const eyedbsm::DbCreateDescription *d = &dbdesc->sedbdesc;
07437 int i;
07438
07439 string_code(&idr, &offset, &alloc_size, dbdesc->dbfile);
07440
07441
07442
07443
07444
07445
07446 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&d->dbid);
07447 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&d->nbobjs);
07448 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->dbsfilesize);
07449 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->dbsfileblksize);
07450 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->ompfilesize);
07451 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->ompfileblksize);
07452 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->shmfilesize);
07453 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&d->shmfileblksize);
07454 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&d->ndat);
07455 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&d->ndsp);
07456
07457
07458
07459 for (i = 0; i < d->ndat; i++)
07460 {
07461 const eyedbsm::Datafile *v = &d->dat[i];
07462 string_code(&idr, &offset, &alloc_size, v->file);
07463 string_code(&idr, &offset, &alloc_size, v->name);
07464 int type = v->mtype;
07465 int16_code(&idr, &offset, &alloc_size, &v->dspid);
07466 int32_code(&idr, &offset, &alloc_size, &type);
07467 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&v->sizeslot);
07468 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&v->maxsize);
07469 eyedblib::int32 dtype = v->dtype;
07470 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&dtype);
07471 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&v->extflags);
07472 }
07473
07474 for (i = 0; i < d->ndsp; i++)
07475 {
07476 const eyedbsm::Dataspace *v = &d->dsp[i];
07477 string_code(&idr, &offset, &alloc_size, v->name);
07478 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&v->ndat);
07479 for (int j = 0; j < v->ndat; j++)
07480 int16_code(&idr, &offset, &alloc_size, &v->datid[j]);
07481 }
07482
07483 *size = offset;
07484 return idr;
07485 }
07486
07487 static const char **
07488 decode_datids(Data idr, unsigned int *oid_cnt)
07489 {
07490 Offset offset = 0;
07491 eyedblib::int32 cnt;
07492 int32_decode(idr, &offset, &cnt);
07493 const char **datids = new const char *[cnt];
07494
07495 for (int i = 0; i < cnt; i++)
07496 string_decode(idr, &offset, (char **)&datids[i]);
07497
07498 *oid_cnt = cnt;
07499 return datids;
07500 }
07501
07502 Data
07503 code_datafiles(void *datafiles, unsigned int datafile_cnt, int *size)
07504 {
07505 char **s = (char **)datafiles;
07506 Data idr = 0;
07507 Size alloc_size = 0;
07508 Offset offset = 0;
07509 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&datafile_cnt);
07510 for (int i = 0; i < datafile_cnt; i++)
07511 string_code(&idr, &offset, &alloc_size, s[i]);
07512 *size = offset;
07513 return idr;
07514 }
07515
07516 static Data
07517 code_datinfo(const eyedbsm::DatafileInfo *info, int *size)
07518 {
07519 Data idr = 0;
07520 Size alloc_size = 0;
07521 Offset offset = 0;
07522
07523 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->objcnt);
07524 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->slotcnt);
07525 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->busyslotcnt);
07526 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->totalsize);
07527 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->avgsize);
07528 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->lastbusyslot);
07529 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->lastslot);
07530 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->busyslotsize);
07531 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->datfilesize);
07532 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->datfileblksize);
07533 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->dmpfilesize);
07534 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->dmpfileblksize);
07535 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->curslot);
07536 int64_code(&idr, &offset, &alloc_size, (eyedblib::int64 *)&info->defragmentablesize);
07537 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&info->slotfragcnt);
07538 double_code(&idr, &offset, &alloc_size, &info->used);
07539
07540 *size = offset;
07541 return idr;
07542 }
07543
07544 void
07545 decode_datinfo(Data idr, void *xinfo)
07546 {
07547 DatafileInfo::Info *info = (DatafileInfo::Info *)xinfo;
07548 Offset offset = 0;
07549
07550 int32_decode(idr, &offset, (eyedblib::int32 *)&info->objcnt);
07551 int32_decode(idr, &offset, (eyedblib::int32 *)&info->slotcnt);
07552 int32_decode(idr, &offset, (eyedblib::int32 *)&info->busyslotcnt);
07553 int64_decode(idr, &offset, (eyedblib::int64 *)&info->totalsize);
07554 int32_decode(idr, &offset, (eyedblib::int32 *)&info->avgsize);
07555 int32_decode(idr, &offset, (eyedblib::int32 *)&info->lastbusyslot);
07556 int32_decode(idr, &offset, (eyedblib::int32 *)&info->lastslot);
07557 int64_decode(idr, &offset, (eyedblib::int64 *)&info->busyslotsize);
07558 int64_decode(idr, &offset, (eyedblib::int64 *)&info->datfilesize);
07559 int64_decode(idr, &offset, (eyedblib::int64 *)&info->datfileblksize);
07560 int64_decode(idr, &offset, (eyedblib::int64 *)&info->dmpfilesize);
07561 int64_decode(idr, &offset, (eyedblib::int64 *)&info->dmpfileblksize);
07562 int32_decode(idr, &offset, (eyedblib::int32 *)&info->curslot);
07563 int64_decode(idr, &offset, (eyedblib::int64 *)&info->defragmentablesize);
07564 int32_decode(idr, &offset, (eyedblib::int32 *)&info->slotfragcnt);
07565 double_decode(idr, &offset, &info->used);
07566 }
07567
07568 static void
07569 make_datinfo(const eyedbsm::DatafileInfo *datinfo, Data *xinfo)
07570 {
07571 DatafileInfo::Info *info = (DatafileInfo::Info *)xinfo;
07572
07573 info->objcnt = datinfo->objcnt;
07574 info->slotcnt = datinfo->slotcnt;
07575 info->busyslotcnt = datinfo->busyslotcnt;
07576 info->totalsize = datinfo->totalsize;
07577 info->avgsize = datinfo->avgsize;
07578 info->lastbusyslot = datinfo->lastbusyslot;
07579 info->lastslot = datinfo->lastslot;
07580 info->busyslotsize = datinfo->busyslotsize;
07581 info->datfilesize = datinfo->datfilesize;
07582 info->datfileblksize = datinfo->datfileblksize;
07583 info->dmpfilesize = datinfo->dmpfilesize;
07584 info->dmpfileblksize = datinfo->dmpfileblksize;
07585 info->curslot = datinfo->curslot;
07586 info->defragmentablesize = datinfo->defragmentablesize;
07587 info->slotfragcnt = datinfo->slotfragcnt;
07588 info->used = datinfo->used;
07589 }
07590
07591
07592 void
07593 decode_dbdescription(Data idr, void *xdata, DbCreateDescription *dbdesc)
07594 {
07595 Offset offset = 0;
07596 eyedbsm::DbCreateDescription *d = &dbdesc->sedbdesc;
07597 int i;
07598 char *s;
07599
07600 memset(dbdesc, 0, sizeof(*dbdesc));
07601 lock_data(&idr, xdata);
07602 string_decode(idr, &offset, &s);
07603 strcpy(dbdesc->dbfile, s);
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616
07617 int32_decode(idr, &offset, (eyedblib::int32 *)&d->dbid);
07618 int32_decode(idr, &offset, (eyedblib::int32 *)&d->nbobjs);
07619 int64_decode(idr, &offset, (eyedblib::int64 *)&d->dbsfilesize);
07620 int64_decode(idr, &offset, (eyedblib::int64 *)&d->dbsfileblksize);
07621 int64_decode(idr, &offset, (eyedblib::int64 *)&d->ompfilesize);
07622 int64_decode(idr, &offset, (eyedblib::int64 *)&d->ompfileblksize);
07623 int64_decode(idr, &offset, (eyedblib::int64 *)&d->shmfilesize);
07624 int64_decode(idr, &offset, (eyedblib::int64 *)&d->shmfileblksize);
07625 int32_decode(idr, &offset, (eyedblib::int32 *)&d->ndat);
07626 int32_decode(idr, &offset, (eyedblib::int32 *)&d->ndsp);
07627
07628
07629
07630
07631 for (i = 0; i < d->ndat; i++)
07632 {
07633 eyedbsm::Datafile *v = &d->dat[i];
07634 string_decode(idr, &offset, &s);
07635 strcpy(v->file, s);
07636 string_decode(idr, &offset, &s);
07637 strcpy(v->name, s);
07638 eyedblib::int32 type;
07639 int16_decode(idr, &offset, &v->dspid);
07640 int32_decode(idr, &offset, &type);
07641 v->mtype = (eyedbsm::MapType)type;
07642 int32_decode(idr, &offset, (eyedblib::int32 *)&v->sizeslot);
07643 int64_decode(idr, &offset, (eyedblib::int64 *)&v->maxsize);
07644 eyedblib::int32 dtype;
07645 int32_decode(idr, &offset, (eyedblib::int32 *)&dtype);
07646 v->dtype = (DatType)dtype;
07647 int32_decode(idr, &offset, (eyedblib::int32 *)&v->extflags);
07648 }
07649
07650 for (i = 0; i < d->ndsp; i++)
07651 {
07652 eyedbsm::Dataspace *v = &d->dsp[i];
07653 string_decode(idr, &offset, &s);
07654 strcpy(v->name, s);
07655 int32_decode(idr, &offset, (eyedblib::int32 *)&v->ndat);
07656 for (int j = 0; j < v->ndat; j++)
07657 int16_decode(idr, &offset, &v->datid[j]);
07658 }
07659
07660 unlock_data(idr, xdata);
07661 }
07662
07663 static void
07664 decode_index_impl_r(Data data, void *ximpl, Offset &offset)
07665 {
07666 short type;
07667 int16_decode(data, &offset, &type);
07668
07669 if (type == IndexImpl::Hash) {
07670 int key_count;
07671
07672
07673
07674
07675 int32_decode(data, &offset, &key_count);
07676 int impl_hints[eyedbsm::HIdxImplHintsCount];
07677 for (int i = 0; i < eyedbsm::HIdxImplHintsCount; i++)
07678 int32_decode(data, &offset, &impl_hints[i]);
07679
07680 *(IndexImpl **)ximpl = new IndexImpl(IndexImpl::Hash,
07681 0,
07682 key_count,
07683 0,
07684 impl_hints,
07685 eyedbsm::HIdxImplHintsCount);
07686 }
07687 else {
07688 int degree;
07689 int32_decode(data, &offset, °ree);
07690 int impl_hints[eyedbsm::HIdxImplHintsCount];
07691 for (int i = 0; i < eyedbsm::HIdxImplHintsCount; i++)
07692 int32_decode(data, &offset, &impl_hints[i]);
07693
07694 *(IndexImpl **)ximpl = new IndexImpl(IndexImpl::BTree,
07695 0,
07696 degree,
07697 0,
07698 impl_hints,
07699 eyedbsm::HIdxImplHintsCount);
07700 }
07701 }
07702
07703 void decode_index_impl(Data data, void *ximpl)
07704 {
07705 Offset offset = 0;
07706 decode_index_impl_r(data, ximpl, offset);
07707 }
07708
07709 void decode_index_stats(Data data, void *xstats)
07710 {
07711 Offset offset = 0;
07712
07713 short type;
07714 int16_decode(data, &offset, &type);
07715
07716 if (type == IndexImpl::Hash) {
07717 HashIndexStats *stats = new HashIndexStats();
07718 decode_index_impl_r(data, &stats->idximpl, offset);
07719
07720 int32_decode(data, &offset, (eyedblib::int32 *)&stats->min_objects_per_entry);
07721 int32_decode(data, &offset, (eyedblib::int32 *)&stats->max_objects_per_entry);
07722 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_object_count);
07723 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_hash_object_count);
07724 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_hash_object_size);
07725 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_hash_object_busy_size);
07726 int32_decode(data, &offset, (eyedblib::int32 *)&stats->busy_key_count);
07727 int32_decode(data, &offset, (eyedblib::int32 *)&stats->free_key_count);
07728
07729 int32_decode(data, &offset, (eyedblib::int32 *)&stats->key_count);
07730 HashIndexStats::Entry *entry = stats->entries =
07731 new HashIndexStats::Entry[stats->key_count];
07732 for (int i = 0; i < stats->key_count; i++, entry++) {
07733 int32_decode(data, &offset, (eyedblib::int32 *)&entry->object_count);
07734 int32_decode(data, &offset, (eyedblib::int32 *)&entry->hash_object_count);
07735 int32_decode(data, &offset, (eyedblib::int32 *)&entry->hash_object_size);
07736 int32_decode(data, &offset, (eyedblib::int32 *)&entry->hash_object_busy_size);
07737 }
07738 *(HashIndexStats **)xstats = stats;
07739 }
07740 else {
07741 BTreeIndexStats *stats = new BTreeIndexStats();
07742 decode_index_impl_r(data, &stats->idximpl, offset);
07743
07744 int32_decode(data, &offset, (eyedblib::int32 *)&stats->degree);
07745 int32_decode(data, &offset, (eyedblib::int32 *)&stats->dataSize);
07746 int32_decode(data, &offset, (eyedblib::int32 *)&stats->keySize);
07747 int32_decode(data, &offset, (eyedblib::int32 *)&stats->keyOffset);
07748 int32_decode(data, &offset, (eyedblib::int32 *)&stats->keyType);
07749
07750 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_object_count);
07751 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_btree_object_count);
07752 int32_decode(data, &offset, (eyedblib::int32 *)&stats->btree_node_size);
07753 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_btree_node_count);
07754 int32_decode(data, &offset, (eyedblib::int32 *)&stats->btree_key_object_size);
07755 int32_decode(data, &offset, (eyedblib::int32 *)&stats->btree_data_object_size);
07756 int32_decode(data, &offset, (eyedblib::int32 *)&stats->total_btree_object_size);
07757
07758 *(BTreeIndexStats **)xstats = stats;
07759 }
07760 }
07761
07762 static void
07763 make_index_stats(const eyedbsm::BIdx::Stats &stats, Data *xrstats)
07764 {
07765 BTreeIndexStats *rstats = new BTreeIndexStats();
07766 rstats->degree = stats.idx->getDegree();
07767 rstats->dataSize = stats.idx->getDataSize();
07768 rstats->keySize = stats.idx->getKeySize();
07769 rstats->keyOffset = stats.keyOffset;
07770 rstats->keyType = stats.keyType;
07771
07772 rstats->total_object_count = stats.total_object_count;
07773 rstats->total_btree_object_count = stats.total_btree_object_count;
07774 rstats->btree_node_size = stats.btree_node_size;
07775 rstats->total_btree_node_count = stats.total_btree_node_count;
07776 rstats->btree_key_object_size = stats.btree_key_object_size;
07777 rstats->btree_data_object_size = stats.btree_data_object_size;
07778 rstats->total_btree_object_size = stats.total_btree_object_size;
07779
07780 rstats->idximpl = new IndexImpl(IndexImpl::BTree, 0,
07781 stats.idx->getDegree(),
07782 0, 0, 0);
07783 *(BTreeIndexStats **)xrstats = rstats;
07784 }
07785
07786 static void
07787 make_index_stats(const eyedbsm::HIdx::Stats &stats, Data *xrstats)
07788 {
07789 HashIndexStats *rstats = new HashIndexStats();
07790 rstats->min_objects_per_entry = stats.min_objects_per_entry;
07791 rstats->max_objects_per_entry = stats.max_objects_per_entry;
07792 rstats->total_object_count = stats.total_object_count;
07793 rstats->total_hash_object_count = stats.total_hash_object_count;
07794 rstats->total_hash_object_size = stats.total_hash_object_size;
07795 rstats->total_hash_object_busy_size = stats.total_hash_object_busy_size;
07796 rstats->busy_key_count = stats.busy_key_count;
07797 rstats->free_key_count = stats.free_key_count;
07798
07799 rstats->key_count = stats.idx.key_count;
07800 rstats->entries = new HashIndexStats::Entry[rstats->key_count];
07801 for (int i = 0; i < rstats->key_count; i++) {
07802 rstats->entries[i].object_count = stats.entries[i].object_count;
07803 rstats->entries[i].hash_object_count = stats.entries[i].hash_object_count;
07804 rstats->entries[i].hash_object_size = stats.entries[i].hash_object_size;
07805 rstats->entries[i].hash_object_busy_size = stats.entries[i].hash_object_busy_size;
07806 }
07807
07808 rstats->idximpl = new IndexImpl(IndexImpl::Hash, 0,
07809 stats.idx.key_count,
07810 0, stats.idx.impl_hints,
07811 eyedbsm::HIdxImplHintsCount);
07812 *(HashIndexStats **)xrstats = rstats;
07813 }
07814
07815
07816 static Data
07817 code_index_impl(const eyedbsm::BIdx &idx, int *size,
07818 Data &idr, Offset &offset, Size &alloc_size)
07819 {
07820
07821 short xtype = IndexImpl::BTree;
07822 int16_code(&idr, &offset, &alloc_size, &xtype);
07823
07824
07825 unsigned int degree = idx.getDegree();
07826 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)°ree);
07827 for (int i = 0; i < eyedbsm::HIdxImplHintsCount; i++) {
07828 int zero = 0;
07829 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&zero);
07830 }
07831 *size = offset;
07832 return idr;
07833 }
07834
07835 static Data
07836 code_index_impl(const eyedbsm::BIdx &idx, int *size)
07837 {
07838 Data idr = 0;
07839 Offset offset = 0;
07840 Size alloc_size = 0;
07841 return code_index_impl(idx, size, idr, offset, alloc_size);
07842 }
07843
07844 static Data
07845 code_index_impl(const eyedbsm::HIdx::_Idx &idx, int *size,
07846 Data &idr, Offset &offset, Size &alloc_size)
07847 {
07848
07849 short xtype = IndexImpl::Hash;
07850 int16_code(&idr, &offset, &alloc_size, &xtype);
07851
07852
07853 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&idx.key_count);
07854 for (int i = 0; i < eyedbsm::HIdxImplHintsCount; i++)
07855 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&idx.impl_hints[i]);
07856
07857 *size = offset;
07858 return idr;
07859 }
07860
07861 static Data
07862 code_index_impl(const eyedbsm::HIdx::_Idx &idx, int *size)
07863 {
07864 Data idr = 0;
07865 Offset offset = 0;
07866 Size alloc_size = 0;
07867 return code_index_impl(idx, size, idr, offset, alloc_size);
07868 }
07869
07870 static void
07871 make_index_impl(const eyedbsm::BIdx &idx, Data *data)
07872 {
07873 *(IndexImpl **)data = new IndexImpl(IndexImpl::BTree,
07874 0, idx.getDegree(), 0,
07875 0, 0);
07876 }
07877
07878 static void
07879 make_index_impl(const eyedbsm::HIdx::_Idx &idx, Data *data)
07880 {
07881 *(IndexImpl **)data = new IndexImpl(IndexImpl::Hash,
07882 0,
07883 idx.key_count, 0,
07884 idx.impl_hints,
07885 eyedbsm::HIdxImplHintsCount);
07886 }
07887
07888 static Data
07889 code_index_stats(IndexImpl::Type type, const void *xstats,
07890 int *size)
07891 {
07892 Data idr = 0;
07893 Offset offset = 0;
07894 Size alloc_size = 0;
07895 short xtype = type;
07896 int16_code(&idr, &offset, &alloc_size, &xtype);
07897
07898 if (type == IndexImpl::Hash) {
07899 const eyedbsm::HIdx::Stats *stats = (const eyedbsm::HIdx::Stats *)xstats;
07900 int dummy;
07901 code_index_impl(stats->idx, &dummy, idr, offset, alloc_size);
07902 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->min_objects_per_entry);
07903 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->max_objects_per_entry);
07904 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_object_count);
07905 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_hash_object_count);
07906 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_hash_object_size);
07907 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_hash_object_busy_size);
07908 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->busy_key_count);
07909 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->free_key_count);
07910 const eyedbsm::HIdx::Stats::Entry *entry = stats->entries;
07911 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->idx.key_count);
07912 for (int i = 0; i < stats->idx.key_count; i++, entry++) {
07913 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&entry->object_count);
07914 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&entry->hash_object_count);
07915 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&entry->hash_object_size);
07916 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&entry->hash_object_busy_size);
07917 }
07918 }
07919 else {
07920 const eyedbsm::BIdx::Stats *stats = (const eyedbsm::BIdx::Stats *)xstats;
07921 int dummy;
07922 code_index_impl(*stats->idx, &dummy, idr, offset, alloc_size);
07923
07924 unsigned int x = stats->idx->getDegree();
07925 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&x);
07926 x = stats->idx->getDataSize();
07927 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&x);
07928 x = stats->idx->getKeySize();
07929 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&x);
07930 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->keyOffset);
07931 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->keyType);
07932
07933 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_object_count);
07934 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_btree_object_count);
07935 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->btree_node_size);
07936 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_btree_node_count);
07937 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->btree_key_object_size);
07938 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->btree_data_object_size);
07939 int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&stats->total_btree_object_size);
07940 }
07941
07942 *size = offset;
07943 return idr;
07944 }
07945
07946
07947
07948 static void
07949 code_atom_array(rpc_ServerData *data, void *atom_array, int count,
07950 int nalloc)
07951 {
07952 Offset offset = 0;
07953 Data idr;
07954 Size alloc_size;
07955 int c, size = sizeof(eyedblib::int32);
07956 IteratorAtom *p = (IteratorAtom *)atom_array;
07957
07958 for (c = 0; c < count; c++, p++)
07959 size += sizeof(eyedblib::int16) + p->getSize();
07960
07961 if (size <= data->buff_size)
07962 data->status = rpc_BuffUsed;
07963 else
07964 {
07965 data->status = rpc_TempDataUsed;
07966 data->data = (unsigned char *)malloc(size);
07967 }
07968
07969 alloc_size = size;
07970 data->size = size;
07971 idr = (Data)data->data;
07972
07973 p = (IteratorAtom *)atom_array;
07974
07975 for (c = 0; c < count; c++, p++)
07976 p->code(&idr, &offset, &alloc_size);
07977
07978 idbFreeVect((IteratorAtom *)atom_array, IteratorAtom, nalloc);
07979 }
07980
07981 static void
07982 code_value(rpc_ServerData *data, Value *value)
07983 {
07984 Offset offset = 0;
07985 Size alloc_size = 0;
07986 Data idr = 0;
07987
07988 value->code(idr, offset, alloc_size);
07989
07990 if (alloc_size <= data->buff_size)
07991 {
07992 data->status = rpc_BuffUsed;
07993 memcpy(data->data, idr, alloc_size);
07994
07995 }
07996 else
07997 {
07998 data->status = rpc_TempDataUsed;
07999 data->data = idr;
08000 }
08001
08002 data->size = offset;
08003 delete value;
08004 }
08005
08006
08007
08008
08009
08010 struct ServerOutOfBandData {
08011 ServerOutOfBandData(unsigned int _type, unsigned char *_data,
08012 unsigned int _size) {
08013 type = _type;
08014 size = _size;
08015 data = new unsigned char[size];
08016 memcpy(data, _data, size);
08017 }
08018
08019 ~ServerOutOfBandData() {delete [] data;}
08020
08021 unsigned int type;
08022 unsigned char *data;
08023 unsigned int size;
08024 };
08025
08026 LinkedList server_data_list;
08027 static unsigned max_server_data = 1024;
08028 static eyedblib::Mutex server_data_mt;
08029 static eyedblib::Condition server_data_cnd;
08030
08031 void
08032 setServerOutOfBandData(unsigned int type, unsigned char *data,
08033 unsigned int len)
08034 {
08035 server_data_mt.lock();
08036
08037 while (server_data_list.getCount() >= max_server_data)
08038 server_data_list.deleteObject(server_data_list.getFirstObject());
08039
08040 server_data_list.insertObjectLast
08041 (new ServerOutOfBandData(type, data, len));
08042 server_data_mt.unlock();
08043 server_data_cnd.signal();
08044 }
08045
08046 void
08047 setServerMessage(const char *msg)
08048 {
08049 setServerOutOfBandData(IDB_SERVER_MESSAGE, (unsigned char *)msg,
08050 strlen(msg)+1);
08051 }
08052
08053
08054
08055
08056
08057 RPCStatus
08058 IDB_getServerOutOfBandData(ConnHandle *, int *type, Data *ldata,
08059 unsigned int *size, void *xdata)
08060 {
08061 rpc_ServerData *data = (rpc_ServerData *)xdata;
08062
08063 for (;;) {
08064 server_data_cnd.wait();
08065 server_data_mt.lock();
08066 ServerOutOfBandData *srvdata = (ServerOutOfBandData *)server_data_list.getFirstObject();
08067 if (srvdata) {
08068 if ((*type) & srvdata->type) {
08069 *type = srvdata->type;
08070 if (data) {
08071 data->status = rpc_TempDataUsed;
08072 data->size = srvdata->size;
08073 data->data = new unsigned char[data->size];
08074 memcpy(data->data, srvdata->data, data->size);
08075 }
08076 else {
08077 *size = srvdata->size;
08078 *ldata = new unsigned char[*size];
08079 memcpy(*ldata, srvdata->data, *size);
08080 }
08081 server_data_list.deleteObject(srvdata);
08082 delete srvdata;
08083 server_data_mt.unlock();
08084 return RPCSuccess;
08085 }
08086
08087 server_data_list.deleteObject(srvdata);
08088 delete srvdata;
08089 }
08090 server_data_mt.unlock();
08091 }
08092 }
08093
08094 RPCStatus
08095 IDB_setMaxObjCount(DbHandle * dbh, int obj_cnt)
08096 {
08097 eyedbsm::Status s = eyedbsm::objectNumberSet(dbh->sedbh, (eyedbsm::Oid::NX)obj_cnt);
08098 return rpcStatusMake_se(s);
08099 }
08100
08101 RPCStatus
08102 IDB_getMaxObjCount(DbHandle * dbh, int * obj_cnt)
08103 {
08104 eyedbsm::Oid::NX esm_obj_cnt;
08105 eyedbsm::Status s = eyedbsm::objectNumberGet(dbh->sedbh, &esm_obj_cnt);
08106 *obj_cnt = esm_obj_cnt;
08107 return rpcStatusMake_se(s);
08108 }
08109
08110 RPCStatus
08111 IDB_setLogSize(DbHandle * dbh, int size)
08112 {
08113 eyedbsm::Status s = eyedbsm::shmSizeSet(dbh->sedbh, size);
08114 return rpcStatusMake_se(s);
08115 }
08116
08117
08118 RPCStatus
08119 IDB_getLogSize(DbHandle * dbh, int * size)
08120 {
08121 eyedbsm::Status s = eyedbsm::shmSizeGet(dbh->sedbh, size);
08122 return rpcStatusMake_se(s);
08123 }
08124
08125
08126 eyedbsm::DbHandle *get_eyedbsm_DbHandle(DbHandle *dbh)
08127 {
08128 return dbh->sedbh;
08129 }
08130 }