kernel.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021   Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 //#define PASSWD_FILE
00026 
00027 using namespace std;
00028 
00029 #define NEW_COLLBE_MAN
00030 
00031 #define _IDB_KERN_
00032 
00033 #include <eyedbconfig.h>
00034 
00035 // @@@ ???????????????
00036 // #define private public
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     static char *
00111     crypt(const char *passwd, const char *salt)
00112     {
00113     return crypt(passwd, salt);
00114     }
00115   */
00116 
00117   //static const char sch_default_name[] = "eyedb";
00118 
00119   // introduced the 17/12/99
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()) // added the 5/01/01
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           printf("THERE IS SOME ACTION TO DO for '%s' %d, %s\n",
00296           cls->getName(), w, obj_oid.getString());
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     // check file name
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     // check challenge
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     // check uid
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     // check time
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     // check mode
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     //#define SUPPORT_DEV_RANDOM
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     // check for file name
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     // if (conn_ctx.ci && conn_ctx.ci->mode == rpc_ConnInfo::UNIX) {
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       if (conn_ctx.clinfo)
00553       fprintf(stderr, "release conn CONN_CTX.CLINFO is OK %d\n", rpc_getpid());
00554       else
00555       fprintf(stderr, "release conn CONN_CTX.CLINFO is NULL %d\n", rpc_getpid());
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     // TBD: should improved that!
00587     // should check whether `dbmdb' belongs to an authoritative list!
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     printf("IDB_dbmOpen(%s) #1\n", dbmdb);
00599 
00600 #if 1
00601     if (!strcmp(dbmdb, DBM_Database::defaultDBMDB))
00602       dbmdb = Database::getDefaultServerDBMDB();
00603 #else
00604     if (!strcmp(dbmdb, DBM_Database::defaultDBMDB))
00605       dbmdb = Database::getDefaultDBMDB();
00606 #endif
00607 
00608     printf("IDB_dbmOpen(%s) #2\n", dbmdb);
00609     */
00610 
00611     if (*dbm = DBM_Database::getDBM_Database(dbmdb))
00612       {
00613         if (!rw_mode || ((*dbm)->getOpenFlag() & _DBRW))
00614           return RPCSuccess;
00615 
00616         /* added the 8/04/01 because on linux one cannot have 1 database opened
00617            and 2 EYEDBDBM opened (for instance to move a database) */
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     // check file $IDBSVPASSWDFILE against passwdauth
00757 
00758     /*
00759       if (!*dbm_passwd) {
00760       const char *passwdfile;
00761       const char *s;
00762       if (passwdfile)
00763       passwdfile = strdup(passwdfile);
00764       else if (s = eyedb::getConfigValue("passwd_file"))
00765       passwdfile = strdup(s);
00766       else {
00767       fprintf(stderr, "eyedbd: EyeDB passwd file is not set, check your 'sv_passwd_file' configuration variable or the '-passwdfile' command line option\n");
00768       exit(1);
00769       }
00770       
00771       get_dbm_passwd(passwdfile);
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       if (!rpc_status)
00791       status = dbm->updateEntry(dbid, DBM_Database::makeTempName(dbid),
00792       dbname, dbfile);
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   //#undef IS_DATA
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   /*static*/ 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       //eyedblib::display_time("#9");
00961       Status s = dbm->getDbFile(pdbname, dbid, *dbfile);
00962       //eyedblib::display_time("#10");
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 #if 1
00978         if (!strcmp(dbmdb, DBM_Database::defaultDBMDB))
00979           dbmdb = Database::getDefaultServerDBMDB();
00980 #else
00981         if (!strcmp(dbmdb, DBM_Database::defaultDBMDB))
00982           dbmdb = Database::getDefaultDBMDB();
00983 #endif
00984       */
00985 
00986         /*
00987         RPCStatus rpc_status = IDB_checkAuthDbm(dbmdb);
00988         if (rpc_status)
00989           return rpc_status;
00990         */
00991 
00992         *dbfile = dbmdb;
00993 
00994         if (dbid)
00995           *dbid = DBM_Database::getDbid();
00996 
00997         if (pdbm) {
00998           // added 16/01/06
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   /* administration */
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     //rpc_print_tcpip(stdout, &conn_ctx.ci->u.tcpip);
01140   }
01141 
01142   //#define STUART_SUGGESTION
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); // memory leak (not important)
01164       }
01165       
01166       return username;
01167     }
01168 
01169     if (true) { //conn_ctx.ci->mode == rpc_ConnInfo::TCPIP) {
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     /* check that if in case of need_passwd is false, user is really an
01260        unix user; if not, need_passwd becomes true */
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   /*static*/ 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     /* check that if in case of need_passwd is false, user is really an
01392        unix user; if not, need_passwd becomes true */
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     //  const char *pwd = (*passwd ? crypt(passwd, salt) : 0);
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     rpc_status = IDB_checkAuthDbm(dbmdb);
01664     if (rpc_status)
01665       return rpc_status;
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           if (pid)
01689           *pid = (*pdbh)->sedbh->ldbctx.rdbhid;
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     rpc_status = IDB_checkAuthDbm(dbmdb);
01714     if (rpc_status)
01715       return rpc_status;
01716     */
01717 
01718     //eyedblib::display_time("%s %s", dbname, "#1");
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     //eyedblib::display_time("%s %s", dbname, "#2");
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     //  if (!(flags_o & _DBOpenLocal))
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     //eyedblib::display_time("%s %s", dbname, "#3");
01762     //char *pwd = getcwd(NULL, PATH_MAX);
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     //eyedblib::display_time("%s %s", dbname, "#4");
01776     /*
01777       if (pwd)
01778       {
01779       chdir(pwd);
01780       free(pwd);
01781       }
01782     */
01783 
01784     if (status)
01785       return rpcStatusMake_se(status);
01786 
01787     // disconnected 2/05/05
01788     /*
01789       if (pid) {
01790       *pid = sedbh->ldbctx.rdbhid;
01791       }
01792     */
01793 
01794     *rdbid = dbid; //eyedbsm::dataBaseIdGet((eyedbsm::DbHandle *)sedbh->u.dbh);
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     //eyedblib::display_time("%s %s", dbname, "#5");
01802     rpc_status = IDB_schemaClassHeadGet(*pdbh);
01803 
01804     //eyedblib::display_time("%s %s", dbname, "#6");
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         //eyedblib::display_time("%s %s", dbname, "#7");
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              /* was: ((Database *)(*pdbh)->db)->getName() */
01835              userauth,
01836              /* was: ((Database *)(*pdbh)->db)->getUserAuth() */
01837              flags_o);
01838       }
01839 
01840     //eyedblib::display_time("%s %s", dbname, "#8");
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       if (rpc_status == RPCSuccess)
01854       db_list->deleteObject(dbh->db);
01855 
01856       if (conn_ctx.clinfo)
01857       conn_ctx.clinfo->suppressDatabase(((Database *)dbh->db)->getName(),
01858       ((Database *)dbh->db)->getUserAuth(),
01859       ((Database *)dbh->db)->getOpenFlag());
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     //*ldbctx = dbh->sedbh->ldbctx;
01890     *sch_oid = dbh->sch.oid;
01891   }
01892 
01893   RPCStatus
01894   IDB_dbCloseLocal(DbHandle *dbh)
01895   {
01896     oqml_reinit((Database *)dbh->db);
01897     //printf("IDB_dbCloseLocal: sedbh: %p\n", dbh->sedbh);
01898     //printf("IDB_dbCloseLocal: sedbh->u.dbh: %p\n", dbh->sedbh->u.dbh);
01899     // changed 09/05/05: 
01900     //  return rpcStatusMake_se(eyedbsm::dbClose((eyedbsm::DbHandle *)dbh->sedbh->u.dbh));
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   /* transaction management */
01951 
01952   //#define TRS_TRACE
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   /* typed object */
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       // 11/06/01: should add:
02274       // if (db->getOpenFlag() & idbDBSREAD)
02275       // return Exception::make(IDB_ERROR, "....");
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; // added the 6/6/01
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     // added the 17/09/01
02310     if (db->getOpenFlag() & _DBSRead)
02311     return RPCSuccess;
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         printf("decoding: %p %x %x %d %d %d %s\n",
02367         xhdr,
02368         xhdr->magic,
02369         xhdr->type,
02370         xhdr->size,
02371         xhdr->ctime,
02372         xhdr->mtime,
02373         se_getOidString(&xhdr->oid_cl));
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); // was idr_psize
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     // WARNING: disconnected on the 8/01/99
02649     // is it a good idea to have disconnected this code?
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         //se_statusPrint(se_status, "IDB_objectCheckAccess");
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     /* changed the 23/08/99 */
02736     /*rpc_status = rpcStatusMake_se(eyedbsm::objectCreate(dbh->sedbh, se_ObjectNone,
02737       size, oid));*/
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   /* raw data functions */
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   /* vardim */
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     //printf("VDdataCreate(%s)\n", item->getName());
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     //printf("VDdataWrite(%s)\n", item->getName());
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     //  printf("VDdataDelete(%s)\n", item->getName());
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       if (!check || !attr_comp->getPropagate())
03227       return RPCSuccess;
03228     */
03229     if (!check)
03230       return RPCSuccess;
03231 
03232     // magic value set in Index::reimplement() to inform backend that it is
03233     // a reimplementation
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     //if (cattr_comp) {
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         printf("comp %s [%s] found for class %s ",
03270         comp->getName(), comp->getOid().toString(), cls->getName());
03271       */
03272       found = True;
03273       return RPCSuccess;
03274     }
03275 
03276     /*
03277       printf("comp %s [%s] NOT found for class %s: should create\n",
03278       comp->getName(), comp->getOid().toString(),
03279       cls->getName());
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     // should be factorized into: attrCompPropagate
03291     if (!attr_comp->getPropagate())
03292       return RPCSuccess;
03293 
03294     //printf("\nPropagating...\n");
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   //extern eyedbsm::HIdx::hash_key_t hash_key;
03371 
03372   //#define REIMPL_TRACE
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       //printf("Index moving...\n");
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       printf("INDEX_REMOVE(%s, %s, oid=%s, idxoid=%s)\n",
03500       attr_comp->getAttrpath(), cls->getName(), Oid(objoid).toString(),
03501       attr_comp->asIndex()->getIdxOid().toString());
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     //return RPCSuccess;
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       printf("CONSTRAINT_CREATE(%s, %s, %s)\n",
03531       attr_comp->getAttrpath(), cls->getName(), Oid(objoid).toString());
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       printf("CONSTRAINT_DELETE(%p, %s, %s, %s, reentrant=%d)\n", attr_comp,
03566       attr_comp->getAttrpath(), cls->getName(), Oid(objoid).toString(),
03567       reentrant);
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 {// not implemented
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     //if (idxtype == IndexImpl::Hash)
03880     //eyedbsm::HIdx hidx(dbh->sedbh, idxoid);
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       //eyedbsm::BIdx bidx(dbh->sedbh, *idxoid);
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   /* collections */
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       printf("getCollBE called from %s\n", from);
03925       printf("%s: size=%d locked=%d: ", 
03926       db->getName(), db->getBEQueue()->getCollectionCount(), locked);
03927     */
03928 
03929     Oid _oid(colloid);
03930     if (!(collbe = db->getBEQueue()->getCollection(&_oid, dbh))) {
03931       collbe = new CollectionBE(db, dbh, &_oid, locked);
03932 
03933       //printf("not found -> %p\n", collbe);
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       else
03944       printf("FOUND -> %p\n", collbe);
03945     */
03946 
03947     *status = Success;
03948     return collbe;
03949   }
03950 
03951   //static Bool collectionLocked = False;
03952 
03953   void
03954   IDB_free(Database *db, CollectionBE *collbe)
03955   {
03956     if (!collbe->isLocked())
03957       delete collbe;
03958   }
03959 
03960   // 10/09/05
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     /* item_size */
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       //is_literal = IDBBOOL(x);
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     printf("IDB_collectionCreate dspid = %d\n", dspid);
04015     printf("creating collection %s\n", idximpl->getHintsString().c_str());
04016     printf("idximpl->getType() %d %d\n", idximpl->getType(), IndexImpl::BTree);
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       if (idx1->status())
04053       se_statusPrint(idx1->status(), "collection create");
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         //if (idximpl->getType() == IndexImpl::BTree)
04066 #endif
04067         eyedbsm::BIdx::KeyType ktypes;
04068       
04069         // EV: changed 14/12/01
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     // XDR: should really decode ??
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       printf("items_cnt %d vs. xitems_cnt %d, change_cnt %d, new count %d\n",
04239       items_cnt, xitems_cnt, change_cnt, xitems_cnt + change_cnt);
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       //printf("NEW IMPLEMENTATION %s\n", (const char *)idximpl->toString());
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             //printf("KTYPE BEFORE %d\n", ktype.type);
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             //printf("KTYPE AFTER %d\n", idx->getKeyType().type);
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         printf("NEWOIDS IDX1 %s vs. %s\n", Oid(newoid[0]).toString(),
04332         Oid(idx1->oid()).toString());
04333         if (idx2)
04334         printf("NEWOIDS IDX2 %s vs. %s\n", Oid(newoid[1]).toString(),
04335         Oid(idx2->oid()).toString());
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             //se_status = idx->remove(temp, inv_oid.getOid(), &found);
04452             //se_status = idx->remove(temp, inv_temp, &found);
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           // added the 15/08/06 but not correct
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--; // to cancel next 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         /* else coherent: do nothing!! */
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     //if (collbe->isBIdx())
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       1) get coll from the cache:
04749       if is not put it (coll = new CollectionBE(db, colloid) -> bequeue)
04750       2) coll->getIdx1()->searchAny(ind) -> found?
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       1) get coll from the cache (see above)
04809       2) coll->getIdx2()->searchAny(oid) -> found?
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     // 30/08/05 : code suppressed because HIdx::searchAny() performs the swap
04827     // seems that other code does not perform swap before
04828     // 09/09/05: reconnected
04829 
04830     // 9/9/05 (later): new doit pas etre fait la, mais dans le client (si E_XDR)
04831     // disconnected !
04832 #if 0 /*defined(E_XDR) && defined(NEW_COLL_XDR)*/
04833     eyedbsm::Oid toid;
04834     /*
04835       Offset offset = 0;
04836       printf("GET_BY_VALUE\n");
04837       oid_decode(val, &offset, &toid);
04838       val = (Data)&toid;
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   /* queries */
04886 
04887   /*
04888     static void
04889     IDB_schCode(IteratorBE *qbe, void *pschinfo, void *sch_data)
04890     {
04891     rpc_ServerData *data = (rpc_ServerData *)sch_data;
04892 
04893     if (data)
04894     {
04895     data->status = rpc_TempDataUsed;
04896     code_sch_info(qbe->getSchemaInfo(),
04897     (Data *)&data->data, &data->size);
04898     }
04899     else
04900     *((SchemaInfo **)pschinfo) = qbe->getSchemaInfo();
04901     }
04902 
04903     RPCStatus
04904     IDB_queryLangCreate(DbHandle *dbh, const char *qstr, int *qid,
04905     int *pcount, void *pschinfo, void *qstr_data,
04906     void *sch_data)
04907     {
04908     Database *db = (Database *)dbh->db;
04909     Status status;
04910 
04911     lock_data((Data *)&qstr, qstr_data);
04912     IteratorBE *qbe = new IteratorBE(db, dbh, qstr, *pcount);
04913 
04914     if ((status = qbe->getStatus()) == Success)
04915     {
04916     *qid = qbe->getQid();
04917 
04918     IDB_schCode(qbe, pschinfo, sch_data);
04919     unlock_data((Data)qstr, qstr_data);
04920 
04921     return RPCSuccess;
04922     }
04923   
04924     *qid = 0;
04925 
04926     IDB_schCode(qbe, pschinfo, sch_data);
04927 
04928     db->getBEQueue()->removeIterator(qbe);
04929     delete qbe;
04930 
04931     unlock_data((Data)qstr, qstr_data);
04932     return rpcStatusMake(status);
04933     }
04934 
04935     RPCStatus
04936     IDB_queryDatabaseCreate(DbHandle *dbh, int *qid)
04937     {
04938     return RPCSuccess;
04939     }
04940 
04941     RPCStatus
04942     IDB_queryClassCreate(DbHandle *dbh, const eyedbsm::Oid *cloid, int *qid)
04943     {
04944     return RPCSuccess;
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   /* OQL */
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   /* schema functions */
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     //  printf("IDB_schemaClassHeadGet()\n");
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         // 9/9/05: must swap oid read
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     // must swap sch->oid
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     // must swap before sch->oid
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   /* classes functions */
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     //collectionLocked = True;
05303     status = coll->realize();
05304     //collectionLocked = False;
05305 
05306     /*
05307       printf("has created %s collection -> %s class=[%d, %s]\n",
05308       name, coll->getOid().getString(),
05309       coll->getClass(), coll->getClass()->getName());
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     // XDR: should be h2x ??
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     // XDR: we h2x !
05330     memcpy(idr + offset, &xoid, sizeof(eyedbsm::Oid));
05331     // DONT!
05332     //memcpy(idr + offset, &colloid, sizeof(eyedbsm::Oid));
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       // tries again
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         // no chance 
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       //printf("ClassCreate(%s, %s)\n", name, Oid(oid).toString());
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         printf("decoding idximpl for class %s: %s\n", name,
05580         (const char *)idximpl->toString());
05581       */
05582       /*
05583         offset = IDB_CLASS_MAG_ORDER;
05584         eyedblib::int32 mag_order;
05585         int32_decode(idr, &offset, &mag_order);
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             status->print(stdout);
05671             const Class *x = db->getSchema()->getClass(o->asClass()->getName());
05672             printf("adding class error %s [%s %s]\n", o->asClass()->getName(),
05673             o->getOid().toString(), x->getOid().toString());
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     //printf("ClassWrite(%s, %s, cl=%p)\n", cl->getName(),
05749     //cl->getOid().toString(), cl);
05750     //trace_oids(cl);
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     //printf("writing class %s [%p vs. %p]\n", o->asClass()->getName(), o, cl);
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             //printf("ClassWrite adding class %p\n", o);
05767             //trace_oids((Class *)o);
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     // 19/06/01: instance removing does not work
05849     // suppressed for now!
05850     // 4/04/03: reconnected
05851     OidArray oid_arr;
05852     s = extent->getElements(oid_arr);
05853     if (s) return rpcStatusMake(s);
05854 
05855     int cnt = oid_arr.getCount();
05856     //printf("removing %d instances of class %s\n", cnt, cl->getName());
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       // remove components collection
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     // disconnected 3/05/06 because it produced a bug in ODL updates when
05936     // we add an attribute in some case, for instance :
05937     // adding the attribute int contig_count produces a problem :
05938     /*
05939     class A {
05940       int j; index<hash> on j;
05941     };
05942 
05943     class C extends A {
05944       // int contig_count;  index<btree> on contig_count;
05945       string s;
05946       int h; constraint<notnull> on h;
05947     };
05948     */
05949     // but this deconnexion leads to DB memory leaks, because some
05950     // unuseful attr_comp_sets still in the DB : is it really a problem ?
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   /* class functions */
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     // 24/08/05: MODIF time()
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     /* then must pass object to high level back end to create
06106        index entries */
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     // 24/08/05: MODIF time()
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       BUG concurrence sur le delete.
06208 
06209       client A: delete obj1 (sans faire commit ou abort!).
06210 
06211       client B: obj1 :
06212       oql error: eyedb error: object `obj1' does not exist anymore
06213       ou bien
06214       oql error: storage manager: invalid oid: invalid oid `obj1'
06215 
06216       -> ce probleme vient du fait qu'on ne detruit pas un objet (lorsque
06217       DELETED_KEEP est definit)
06218       -> on le modifie, puis on le change de taille! -> c.a.d. qu'on
06219       en cree un nouveau de la nouvelle taille et on affecte l'OID
06220       a ce nouveau. => ce nouvel oid (qui est en fait l'ancien) est
06221       locké en private.
06222       -> j'ai donc essaye de le locker en lockS normal!
06223       dans ce cas, l'object peut etre lu mais l'object_header qu'il
06224       contient est different de l'objet stocké puisque la taille stockée et
06225       la taille souhaitée (qui est la taille de tous les objets de sa classe)
06226       est differente.
06227 
06228       Solutions:
06229       - ne plus garder les OIDs detruits
06230       - les garder et:
06231       + reparer le probleme de concurrence de object size modify
06232       + ou ne pas modifier la taille de l'object: c.a.d. le garder en
06233       totalité (un peu couteux!).
06234 
06235       De toute facon, le fait de garder ou non les OIDs detruits devrait
06236       etre controllable:
06237       = un flag stocké dans la DB (default flag): modifiable par programme.
06238       = ce flag pourrait etre overloadé au runtime.
06239     */
06240 
06241     /*
06242       Une list markDeleted attaché ŕ Database a été introduite
06243       afin de différer le changement de size => le bug précédant
06244       a été corrigé.
06245       Cependant il en reste un:
06246       si le create/remove d'un objet a lieu dans la meme transaction,
06247       cet objet est definitivement oublié: meme apres un commit,
06248       il n'apparait pas dans les autres clients: ce qui peut etre
06249       assez normal (en fait, non!).
06250       Cependant, il continue apparaitre dans le processus qui
06251       a cree et detruit cet objet => un peu bizarre.
06252 
06253       client 1: [eyedb] new Person();
06254       this_oid
06255       [eyedb] delete this_oid;
06256       [eyedb] !print
06257       <object removed>
06258 
06259       client 2: [eyedb] this_oid;
06260       invalid oid ....
06261 
06262       client 1: [eyedb] !commit
06263       [eyedb] !print this_oid
06264       <object removed>
06265 
06266       client 2: [eyedb] this_oid;
06267       invalid oid ....
06268 
06269       client 3: eyedboql -db <db>
06270       [eyedb] this_oid;
06271       invalid oid ....
06272 
06273       Par contre, si un !abort est fait au lieu d'un commit, c'est completement
06274       coherent.
06275 
06276       A noter que c'est le sizeModify qui fout le bordel.
06277       En supprimant l'appel a sizeModify, l'objet apparait bien dans
06278       les autres clients apres le commit sous forme d'une 'object removed'.
06279       C'est donc bien un bug!
06280 
06281       => corrected! (see se_trs.c: SE_TRObjectUnlock)
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     // 24/08/05: MODIF time()
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     // added the 27/02/02
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   /* agregats */
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           //fprintf(stderr, "error deletion %s\n", rpc_status->err_msg);
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           //fprintf(stderr, "error deletion %s\n", rpc_status->err_msg);
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           //fprintf(stderr, "error deletion %s\n", rpc_status->err_msg);
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   /* protections */
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; // idbProtRead;
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     //  printf(create ? "IDB_protectionCreate()\n" : "IDB_protectionMofidy\n");
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             //    printf("OID : %s\n", prot->getPoid().getString());
06566           }
06567       }
06568     else
06569       {
06570         //      printf("ROID : %s\n", prot->getOid().getString());
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       printf("objectProtectionSet(%s, %s)\n", xobj_oid.getString(),
06641       xprot_oid.getString());
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     //  printf("objectProtectionGet(%s)\n", xobj_oid.getString());
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     //  return rpcStatusMake_se(eyedbsm::objectProtectionGet(dbh->sedbh, obj_oid, prot_oid));
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   //extern void idbInit_();
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     // kludge
06763     s = eyedb::ServerConfig::getSValue("coll_hidx_oid");
06764     if (s) {
06765       if (!strcasecmp(s, "no")) {
06766         coll_hidx_oid = False;
06767       }
06768       else if (!strcasecmp(s, "yes")) {
06769         coll_hidx_oid = True;
06770       }
06771       else {
06772         printf("invalid value for coll_hidx_oid %s\n", s);
06773         exit(1);
06774       }
06775     }
06776     */
06777   }
06778 
06779   void
06780   IDB_init(const char *databasedir,
06781            const char *dummy, // was  _passwdfile,
06782            void *xsesslog, int _timeout)
06783   {
06784     //conn_ctx.sesslog = (SessionLog *)xsesslog;
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     //printf("getIndexObjects start\n");
06913     s = idx->getObjects(oids, cnt);
06914     time(&t1);
06915     //printf("getIndexObjects end count=%d [elapsed %d]\n", t1-t0);
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     const char *
07226     time()
07227     {
07228     time_t t;
07229     time(&t);
07230     char *s = ctime(&t);
07231     s[strlen(s)-1] = 0;
07232     return s;
07233     }
07234   */
07235 
07236   //#define EPITRACE
07237 
07238   void object_epilogue(void *xdb, const eyedbsm::Oid *oid,
07239                        Data inv_data, Bool creating)
07240   {
07241     // should cache Object.here
07242     /*
07243       if (creating)
07244       db->cacheObject(oid);
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             // 22/05/06
07281             //mcp(o->getIDR()+ctx->attr_offset, &ctx->valoid, sizeof(Oid));
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   // coding and decoding functions
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     eyedblib::int32 mode = d->file_mode;
07428     int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&mode);
07429     string_code(&idr, &offset, &alloc_size, d->file_group);
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     //int type = d->mtype;
07443     //int32_code(&idr, &offset, &alloc_size, &type);
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     eyedblib::int32 mode;
07593     int32_decode(idr, &offset, (eyedblib::int32 *)&mode);
07594     d->file_mode = mode;
07595     string_decode(idr, &offset, &s);
07596     int len = strlen(s);
07597     if (len > sizeof(d->file_group)-1)
07598       len = sizeof(d->file_group);
07599     strncpy(d->file_group, s, len);
07600     d->file_group[len] = 0;
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     //int mtype;
07614     //int32_decode(idr, &offset, &mtype);
07615     //d->mtype = (se_MapType)mtype;
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         short dspid;
07659         int16_decode(data, &offset, &dspid);
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, // dspid ???
07668                                            key_count,
07669                                            0, // mth ???
07670                                            impl_hints,
07671                                            eyedbsm::HIdxImplHintsCount);
07672     }
07673     else {
07674       int degree;
07675       int32_decode(data, &offset, &degree);
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     //int16_code(&idr, &offset, &alloc_size, &idx.dspid);
07811     unsigned int degree = idx.getDegree();
07812     int32_code(&idr, &offset, &alloc_size, (eyedblib::int32 *)&degree);
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     //int16_code(&idr, &offset, &alloc_size, &idx.dspid);
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         // MIND! ne faut-il pas détruire idr !?
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   // Server message management
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   // should be executed in a parallel thread
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   // moved from p.h
08081   eyedbsm::DbHandle *get_eyedbsm_DbHandle(DbHandle *dbh)
08082   {
08083     return dbh->sedbh;
08084   }
08085 }

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