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