Object.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 private public
00026 #include "eyedb_p.h"
00027 #include <eyedblib/butils.h>
00028 #include "UserDataHT.h"
00029 #include <time.h>
00030 #include <sstream>
00031 
00032 using std::ostringstream;
00033 
00034 // 31/08/06
00035 #define NO_GARB_REALIZE
00036 
00037 using namespace std;
00038 
00039 namespace eyedb {
00040 
00041 #define IDR_TRACE(MSG) printf("IDR: " MSG " %d => %p\n", idr_sz, idr) 
00042 #undef IDR_TRACE
00043 
00044 #ifdef IDR_TRACE
00045 
00046 #define FREE_IDR_TRACE()   if (idr) IDR_TRACE("free")
00047 
00048 #define ALLOC_IDR_TRACE()  if (idr_sz) IDR_TRACE("allocate")
00049 
00050 #define SET_IDR_TRACE()    if (idr_sz) IDR_TRACE("set")
00051 
00052 #else
00053 
00054 #define FREE_IDR_TRACE()
00055 #define ALLOC_IDR_TRACE()
00056 #define SET_IDR_TRACE()
00057 
00058 #endif
00059 
00060   Bool Object::release_cycle_detection = False;
00061 
00062   // force static initialisation order
00063   static std::string &getObjectTag() {
00064     static std::string ObjectTag = "eyedb::Object";
00065     return ObjectTag;
00066   }
00067 
00068   void *idr_dbg;
00069 
00070   void stop_alloc_dbg() {
00071   }
00072 
00073   void
00074   alloc_dbg(void *idr)
00075   {
00076     if (idr != 0 && idr == idr_dbg)
00077       stop_alloc_dbg();
00078   }
00079 
00080   Object::IDR::IDR(Size _idr_sz)
00081   {
00082     refcnt = 1;
00083     idr_sz = _idr_sz;
00084     idr = (unsigned char *)(idr_sz ? malloc(idr_sz) : 0);
00085     ALLOC_IDR_TRACE();
00086     alloc_dbg(idr);
00087   }
00088 
00089   Object::IDR::IDR(Size _idr_sz, Data _idr)
00090   {
00091     refcnt = 1;
00092     idr_sz = _idr_sz;
00093     idr = _idr;
00094     SET_IDR_TRACE();
00095   }
00096 
00097   void
00098   Object::IDR::setIDR(Size sz)
00099   {
00100     FREE_IDR_TRACE();
00101     free(idr);
00102     idr_sz = sz;
00103     idr = (unsigned char *)(idr_sz ? malloc(idr_sz) : 0);
00104     ALLOC_IDR_TRACE();
00105     alloc_dbg(idr);
00106   }
00107 
00108   void
00109   Object::IDR::setIDR(Data _idr)
00110   {
00111     if (idr == _idr)
00112       return;
00113 
00114     FREE_IDR_TRACE();
00115     free(idr);
00116     idr = _idr;
00117     SET_IDR_TRACE();
00118   }
00119 
00120   void
00121   Object::IDR::setIDR(Size sz, Data _idr)
00122   {
00123     if (idr == _idr)
00124       {
00125         assert(idr_sz == sz);
00126         return;
00127       }
00128 
00129     FREE_IDR_TRACE();
00130     free(idr);
00131 
00132     idr = _idr;
00133     idr_sz = sz;
00134     SET_IDR_TRACE();
00135   }
00136 
00137   Object::IDR::~IDR()
00138   {
00139     assert(refcnt <= 1);
00140     FREE_IDR_TRACE();
00141     free(idr);
00142   }
00143 
00144   void Object::init(Bool _init)
00145   {
00146     state = 0;
00147     modify = False;
00148     applyingTrigger = False;
00149     dirty = False;
00150     user_data = (void *)0;
00151     user_data_ht = 0;
00152     oql_info = (void *)0;
00153     xinfo = 0;
00154 
00155     dataspace = 0;
00156     dspid = Dataspace::DefaultDspid;
00157 
00158     removed = False;
00159     unrealizable = False;
00160     grt_obj = False;
00161     c_time = 0;
00162     m_time = 0;
00163     master_object = 0;
00164     damaged_attr = 0;
00165 
00166     if (_init) {
00167       memset(&oid, 0, sizeof(oid));
00168       db = 0;
00169       idr = new IDR(0);
00170       cls = 0;
00171       type = 0;
00172     }
00173     
00174     IDB_LOG(IDB_LOG_OBJ_INIT, ("Object::init(o=%p)\n", this));
00175   }
00176 
00177   void Object::initialize(Database *_db)
00178   {
00179     init(True);
00180     db = _db;
00181     //  userInitialize();
00182   }
00183 
00184   Object::Object(Database *_db, const Dataspace *_dataspace) : gbxObject(getObjectTag())
00185   {
00186     init(True); // conceptually this 3 calls are: Object::initialize(_db);
00187     dataspace = _dataspace;
00188     db = _db;
00189     if (db) db->addToRegister(this);
00190   }
00191 
00192   void
00193   Object::copy(const Object *o, Bool share)
00194   {
00195     IDB_LOG(IDB_LOG_OBJ_COPY, ("Object::operator=(o=%p <= %p [share=%s])\n",
00196                                this, o, share ? "true" : "false"));
00197     if (!o) {
00198       init(True);
00199       return;
00200     }
00201 
00202     init(False);
00203 
00204     oid = o->oid;
00205     db = o->db;
00206     cls = o->cls;
00207     type = o->type;
00208     dataspace = o->dataspace;
00209     dspid = o->dspid;
00210     c_time = o->c_time;
00211     m_time = o->m_time;
00212     master_object = o->master_object;
00213 
00214     if (share) {
00215       idr = o->idr;
00216       idr->incrRefCount();
00217     }
00218     else {
00219       idr = new IDR(o->idr->getSize());
00220       if (idr->getSize())
00221         memcpy(idr->getIDR(), o->idr->getIDR(), idr->getSize());
00222     }
00223 
00224     if (cls)
00225       setTag(cls->getName());
00226   }
00227 
00228   Object::Object(const Object *o, Bool share) : gbxObject(o)
00229   {
00230     idr = 0;
00231     copy(o, share);
00232   }
00233 
00234 
00235   Object::Object(const Object &o) : gbxObject(o)
00236   {
00237     idr = 0;
00238     copy(&o, False);
00239   }
00240 
00241   void
00242   Object::setClass(Class *_cls)
00243   {
00244     cls = _cls;
00245     if (cls)
00246       setTag(cls->getName());
00247   }
00248 
00249   void
00250   Object::setClass(const Class *_cls)
00251   {
00252     cls = const_cast<Class *>(_cls);
00253     if (cls)
00254       setTag(cls->getName());
00255   }
00256 
00257   void
00258   Object::unlock_refcnt()
00259   {
00260     gbx_locked = gbxFalse;
00261     while (getRefCount() > 1)
00262       decrRefCount();
00263   }
00264 
00265   Object& Object::operator=(const Object &o)
00266   {
00267     if (&o == this)
00268       return *this;
00269 
00270     unlock_refcnt();
00271 
00272 #ifndef NO_GARB_REALIZE
00273     garbageRealize();
00274 #endif
00275 
00276     *(gbxObject *)this = gbxObject::operator=((const gbxObject &)o);
00277 
00278     copy(&o, False);
00279 
00280     return *this;
00281   }
00282 
00283   /*
00284     const Type Object::getType() const
00285     {
00286     return type;
00287     }
00288 
00289     const Oid Object::getOid() const
00290     {
00291     return oid;
00292     }
00293   */
00294 
00295   void Object::setOid(const Oid& oid_new)
00296   {
00297     Oid oid_last = oid;
00298 
00299     if (db && oid_last.isValid() && !oid_last.compare(oid_new))
00300       db->uncacheObject(this);
00301 
00302     oid = oid_new;
00303   }
00304 
00305   void *Object::setUserData(void *nuser_data)
00306   {
00307     void *x = user_data;
00308     user_data = nuser_data;
00309     return x;
00310   }
00311 
00312   void *Object::setOQLInfo(void *noql_info)
00313   {
00314     void *x = oql_info;
00315     oql_info = noql_info;
00316     return x;
00317   }
00318 
00319   void *Object::getOQLInfo()
00320   {
00321     return oql_info;
00322   }
00323 
00324   Status Object::setDatabase(Database *mdb)
00325   {
00326     if (unrealizable)
00327       return Exception::make(IDB_SETDATABASE_ERROR, "object not realizable");
00328 
00329     Database *odb = db;
00330 
00331     if (odb &&
00332         odb != mdb &&
00333         oid.isValid() &&
00334         oid.getDbid() != mdb->getDbid())
00335       return Exception::make(IDB_SETDATABASE_ERROR,
00336                              "cannot change dynamically database of "
00337                              "a persistent object");
00338 
00339     if (cls)
00340       {
00341         const char *name = cls->getName();
00342         cls = mdb->getSchema()->getClass(name);
00343       
00344         if (!cls)
00345           return Exception::make(IDB_SETDATABASE_ERROR,
00346                                  "class '%s' not found in schema\n", name);
00347       }
00348 
00349     if (db != mdb)
00350       {
00351         if (db)
00352           db->rmvFromRegister(this);
00353         db = mdb;
00354         if (db)
00355           db->addToRegister(this);
00356       }
00357 
00358     return Success;
00359   }
00360 
00361   void Object::setUnrealizable(Bool _unrealizable)
00362   {
00363     unrealizable = _unrealizable;
00364     if (unrealizable)
00365       {
00366         db = 0;
00367         setOid(*getInvalidOid());
00368       }
00369   }
00370 
00371   /*
00372     Bool Object::isUnrealizable() const
00373     {
00374     return unrealizable;
00375     }
00376 
00377     Database *Object::getDatabase()
00378     {
00379     return db;
00380     }
00381 
00382     const Database *Object::getDatabase() const
00383     {
00384     return db;
00385     }
00386   */
00387 
00388   void Object::headerCode(eyedblib::int32 t, eyedblib::int32 size, eyedblib::int32 _xinfo)
00389   {
00390     ObjectHeader hdr;
00391 
00392     memset(&hdr, 0, sizeof(hdr));
00393 
00394     hdr.type = t;
00395     hdr.size = size;
00396     hdr.xinfo = _xinfo;
00397 
00398     if (cls)
00399       hdr.oid_cl = *cls->getOid().getOid();
00400 
00401     object_header_code_head(idr->getIDR(), &hdr);
00402 
00403     if (eyedb_is_type(hdr, _Class_Type))
00404       memset(idr->getIDR() + IDB_CLASS_COLL_START, 0,
00405              IDB_CLASS_COLLS_CNT * sizeof(eyedbsm::Oid));
00406   }
00407 
00408   void Object::classOidCode(void)
00409   {
00410     Offset offset = IDB_OBJ_HEAD_OID_MCL_INDEX;
00411     Size alloc_size = IDB_OBJ_HEAD_SIZE;
00412 
00413     Data data = idr->getIDR();
00414     oid_code(&data, &offset, &alloc_size, cls->getOid().getOid());
00415   }
00416 
00417   Status Object::realize(const RecMode *rcm)
00418   {
00419     if (state & Realizing)
00420       return Success;
00421 
00422     CHK_OBJ(this);
00423 
00424     if (master_object)
00425       return master_object->realize(rcm);
00426 
00427     Status status;
00428     state |= Realizing;
00429 
00430     if (!oid.isValid())
00431       status = create();
00432     else /* if (modify) */
00433       status = update();
00434 
00435     if (!status)
00436       {
00437         modify = False;
00438         applyingTrigger = False;
00439         dirty = False;
00440       }
00441   
00442     state &= ~Realizing;
00443     return status;
00444   }
00445 
00446   Bool Object::traceRemoved(FILE *fd, const char *indent_str) const
00447   {
00448     if (removed)
00449       {
00450         fprintf(fd, "%s<object removed>\n", indent_str);
00451         return True;
00452       }
00453     return False;
00454   }
00455 
00456   Status Object::remove(const RecMode *rcm)
00457   {
00458     return remove_r(rcm);
00459   }
00460 
00461   Status Object::remove_r(const RecMode *rcm, unsigned int flags)
00462   {
00463     if (removed)
00464       return Exception::make(IDB_OBJECT_REMOVE_ERROR, "object %s already removed", oid.toString());
00465     if (!oid.isValid())
00466       return Exception::make(IDB_OBJECT_REMOVE_ERROR, "invalid object to remove");
00467 
00468     IDB_CHECK_WRITE(db);
00469 
00470     RPCStatus rpc_status;
00471 
00472     rpc_status = objectDelete(db->getDbHandle(), oid.getOid(), flags);
00473 
00474     if (rpc_status == RPCSuccess)
00475       {
00476         db->uncacheObject(this);
00477         removed = True;
00478       }
00479 
00480     return StatusMake(rpc_status);
00481   }
00482 
00483 #define ObjectMagicDeleted 6666666
00484 
00485   void Object::garbage()
00486   {
00487     IDB_LOG(IDB_LOG_OBJ_GARBAGE,
00488             ("Object::garbage(o=%p, oid=%s, class=\"%s\", "
00489              "idr=%p, idr:refcnt=%d)\n",
00490              this, oid.toString(), cls ? cls->getName() : "<unknown>",
00491              idr->getIDR(), idr->getRefCount()));
00492 
00493     if (db)
00494       {
00495         db->uncacheObject(this);
00496         db->rmvFromRegister(this);
00497       }
00498 
00499     if (!idr->decrRefCount())
00500       {
00501         delete idr;
00502         idr = 0;
00503       }
00504 
00505     delete user_data_ht;
00506   }
00507 
00508 
00509   Object::~Object()
00510   {
00511     garbageRealize();
00512   }
00513 
00514   /*
00515     Bool Object::isModify() const
00516     {
00517     return modify;
00518     }
00519   */
00520 
00521   void Object::touch()
00522   {
00523     modify = True;
00524     /*
00525       if (master_object)
00526       master_object->touch();
00527     */
00528   }
00529 
00530   Status
00531   Object::setLock(LockMode lockmode)
00532   {
00533     return db->setObjectLock(oid, lockmode);
00534   }
00535 
00536   Status
00537   Object::setLock(LockMode lockmode, LockMode &alockmode)
00538   {
00539     return db->setObjectLock(oid, lockmode, alockmode);
00540   }
00541 
00542   Status
00543   Object::getLock(LockMode &lockmode)
00544   {
00545     return db->getObjectLock(oid, lockmode);
00546   }
00547 
00548   eyedbsm::Oid ClassOidDecode(Data idr)
00549   {
00550     Offset offset = IDB_OBJ_HEAD_OID_MCL_INDEX;
00551     eyedbsm::Oid oid;
00552 
00553     oid_decode(idr, &offset, &oid);
00554     return oid;
00555   }
00556 
00557   const char *Object::getStringCTime() const
00558   {
00559     return eyedblib::setbuftime(c_time);
00560   }
00561 
00562   const char *Object::getStringMTime() const
00563   {
00564     return eyedblib::setbuftime(m_time);
00565   }
00566 
00567   void
00568   Object::trace_flags(FILE *fd, unsigned int flags) const
00569   {
00570     if (flags & PointerTrace)
00571       fprintf(fd, "[this = 0x%x] ", this);
00572 
00573     if (oid.isValid())
00574       {
00575         if ((flags & CMTimeTrace) == CMTimeTrace)
00576           fprintf(fd, "ctime = %s / mtime = %s",
00577                   getStringCTime(), getStringMTime());
00578         else if ((flags & CTimeTrace) == CTimeTrace)
00579           fprintf(fd, "ctime = %s", getStringCTime());
00580         else if ((flags & MTimeTrace) == MTimeTrace)
00581           fprintf(fd, "mtime = %s", getStringMTime());
00582       }
00583   }
00584 
00585   Status 
00586   Object::apply(Database *_db, Method *mth, ArgArray &argarray,
00587                 Argument &retarg, Bool checkArgs)
00588   {
00589     return mth->applyTo(_db, this, argarray, retarg, checkArgs);
00590   }
00591 
00592   const Object *Object::getMasterObject(bool recurs) const
00593   {
00594     return const_cast<Object *>(this)->getMasterObject(recurs);
00595   }
00596 
00597   Object *Object::getMasterObject(bool recurs)
00598   {
00599     if (!recurs || !master_object)
00600       return master_object;
00601 
00602     assert(recurs && master_object);
00603 
00604     if (master_object->getMasterObject(false)) // has an immediate master object
00605       return master_object->getMasterObject(true);
00606 
00607     return master_object;
00608   }
00609 
00610   Status
00611   Object::setMasterObject(Object *_master_object)
00612   {
00613     master_object = _master_object;
00614     return Success;
00615   }
00616 
00617   Status
00618   Object::releaseMasterObject()
00619   {
00620     master_object = 0;
00621     /*
00622     printf("Release_master_object %d\n", protect_on_release_master);
00623     if (getOid().isValid() && !protect_on_release_master) {
00624       printf("removing %s\n", getOid().toString());
00625       return remove();
00626     }
00627     */
00628 
00629     return Success;
00630   }
00631 
00632   Status
00633   Object::setProtection(const Oid &prot_oid)
00634   {
00635     if (!db)
00636       return Exception::make(IDB_ERROR, "no database associated with object");
00637     return db->setObjectProtection(oid, prot_oid);
00638   }
00639 
00640   Status
00641   Object::setProtection(Protection *prot)
00642   {
00643     if (!db)
00644       return Exception::make(IDB_ERROR, "no database associated with object");
00645     return db->setObjectProtection(oid, prot);
00646   }
00647 
00648   Status
00649   Object::getProtection(Oid &prot_oid) const
00650   {
00651     if (!db)
00652       return Exception::make(IDB_ERROR, "no database associated with object");
00653     prot_oid = oid_prot;
00654     return Success;
00655     //  return db->getObjectProtection(oid, prot_oid);
00656   }
00657 
00658   Status
00659   Object::getProtection(Protection *&prot) const
00660   {
00661     if (!db)
00662       return Exception::make(IDB_ERROR, "no database associated with object");
00663 
00664     if (oid_prot.isValid())
00665       return db->loadObject(&oid_prot, (Object **)&prot);
00666 
00667     prot = NULL;
00668     return Success;
00669     //  return db->getObjectProtection(oid, prot);
00670   }
00671 
00672   //
00673   // ObjectArray
00674   //
00675 
00676 #define TRY_GETELEMS_GC
00677 
00678   ObjectArray::ObjectArray(Object **_objs, unsigned int _count)
00679   {
00680     objs = 0;
00681     count = 0;
00682     auto_garb = False;
00683     set(_objs, _count);
00684   }
00685 
00686   ObjectArray::ObjectArray(bool _auto_garb, Object **_objs, unsigned int _count)
00687   {
00688     objs = 0;
00689     count = 0;
00690     auto_garb = _auto_garb;
00691     set(_objs, _count);
00692   }
00693 
00694   ObjectArray::ObjectArray(const Collection *coll, bool _auto_garb)
00695   {
00696     objs = 0;
00697     count = 0;
00698     auto_garb = _auto_garb;
00699     coll->getElements(*this);
00700   }
00701 
00702   void ObjectArray::set(Object **_objs, unsigned int _count)
00703   {
00704     // 01/11/06
00705 #ifdef TRY_GETELEMS_GC
00706     if (auto_garb && _count && !_objs)
00707       throw *Exception::make(IDB_ERROR,
00708                              "cannot set an auto-garbaged object array "
00709                              "for %d objets with no object pointer",
00710                              _count);
00711 
00712 #endif
00713     if (auto_garb)
00714       garbage();
00715 
00716     free(objs);
00717 
00718     int sz = _count * sizeof(Object *);
00719     objs = (Object **)malloc(sz);
00720     if (_objs)
00721       memcpy(objs, _objs, sz);
00722     count = _count;
00723 
00724 #ifdef TRY_GETELEMS_GC
00725     if (auto_garb) {
00726       for (int n = 0; n < count; n++) {
00727         if (objs[n]) {
00728           objs[n]->incrRefCount();
00729         }
00730       }
00731     }
00732 #endif
00733   }
00734 
00735   void ObjectArray::setMustRelease(bool must_release)
00736   {
00737     for (int i = 0; i < count; i++)
00738       if (objs[i])
00739         objs[i]->setMustRelease(must_release);
00740   }
00741 
00742   ObjectArray::ObjectArray(const ObjectArray &objarr)
00743   {
00744     count = 0;
00745     objs = 0;
00746     auto_garb = False;
00747     *this = objarr;
00748   }
00749 
00750   Status ObjectArray::setObjectAt(unsigned int ind, Object *o)
00751   {
00752     if (ind >= count)
00753       return Exception::make(IDB_ERROR, "invalid range %d (maximun is %d)",
00754                              ind, count);
00755     if (objs[ind] == o)
00756       return Success;
00757 
00758 #ifdef TRY_GETELEMS_GC
00759     if (auto_garb) {
00760 
00761       if (objs[ind])
00762         objs[ind]->release();
00763 
00764       objs[ind] = o;
00765 
00766       if (objs[ind])
00767         objs[ind]->incrRefCount();
00768 
00769       return Success;
00770     }
00771 #endif
00772 
00773     objs[ind] = o;
00774     return Success;
00775   }
00776 
00777   ObjectArray::ObjectArray(const ObjectList &list)
00778   {
00779     count = 0;
00780     auto_garb = False;
00781 
00782     int cnt = list.getCount();
00783     if (!cnt)
00784       {
00785         objs = 0;
00786         return;
00787       }
00788 
00789     objs = (Object **)malloc(sizeof(Object *) * cnt);
00790 
00791     ObjectListCursor c(list);
00792     Object *o;
00793 
00794     for (; c.getNext(o); count++) {
00795       objs[count] = o;
00796       /*
00797 #ifdef TRY_GETELEMS_GC
00798       // 31/10/06
00799       if (auto_garb)
00800         o->incrRefCount();
00801 #endif
00802       */
00803     }
00804   }
00805 
00806   ObjectArray& ObjectArray::operator=(const ObjectArray &objarr)
00807   {
00808     set(objarr.objs, objarr.count);
00809 #ifndef TRY_GETELEMS_GC
00810     auto_garb = objarr.auto_garb;
00811 #endif
00812     return *this;
00813   }
00814 
00815   void ObjectArray::garbage()
00816   {
00817     for (int i = 0; i < count; i++)
00818       if (objs[i]) {
00819         objs[i]->release();
00820         objs[i] = 0;
00821       }
00822   }
00823 
00824   ObjectList *
00825   ObjectArray::toList() const
00826   {
00827     return new ObjectList(*this);
00828   }
00829 
00830   void ObjectArray::makeObjectPtrVector(ObjectPtrVector &obj_vect)
00831   {
00832     for (int n = 0; n < count; n++)
00833       obj_vect.push_back(objs[n]);
00834   }
00835 
00836   ObjectArray::~ObjectArray()
00837   {
00838     if (auto_garb)
00839       garbage();
00840 
00841     free(objs);
00842   }
00843 
00844   extern ostream& 
00845   tmpfile2stream(const char *file, ostream& os, FILE *fd);
00846 
00847   ostream& operator<<(ostream& os, const ObjectPtr &o_ptr)
00848   {
00849     return os << o_ptr.getObject();
00850   }
00851 
00852   ostream& operator<<(ostream& os, const Object &o)
00853   {
00854     return os << &o;
00855   }
00856 
00857   ostream& operator<<(ostream& os, const Object *o)
00858   {
00859     if (!o)
00860       return os << "NULL\n";
00861 
00862     Status s = o->trace(get_file());
00863     if (s) return os << s->getDesc();
00864     return convert_to_stream(os);
00865   }
00866 
00867   std::string
00868   Object::toString(unsigned int flags, const RecMode *rcm,
00869                    Status *pstatus) const
00870   {
00871     Status status = trace(get_file(), flags, rcm);
00872     if (status) {
00873       if (pstatus) *pstatus = status;
00874       return status->getDesc();
00875     }
00876 
00877     ostringstream ostr;
00878     convert_to_stream(ostr);
00879     //ostr << ends;
00880     //const std::string &str = ostr.str();
00881     //std::string s(str);
00882     std::string s(ostr.str());
00883     if (pstatus) *pstatus = Success;
00884     return s;
00885   }
00886 
00887   void
00888   Object::freeList(LinkedList *list, Bool wipeOut)
00889   {
00890     if (!list)
00891       return;
00892 
00893     if (wipeOut)
00894       {
00895         Object *o;
00896         LinkedListCursor c(list);
00897   
00898         while (c.getNext((void *&)o))
00899           o->release();
00900       }
00901   
00902     delete list;
00903   }
00904 
00905 
00906   LinkedList *
00907   Object::copyList(const LinkedList *list, Bool copy)
00908   {
00909     if (!list)
00910       return (LinkedList *)0;
00911 
00912     LinkedList *rlist = new LinkedList();
00913     Object *o;
00914 
00915     LinkedListCursor c(list);
00916 
00917     while (c.getNext((void *&)o))
00918       rlist->insertObject(copy && o ? o->clone() : o);
00919   
00920     return rlist;
00921   }
00922 
00923   //
00924   // object list
00925   //
00926 
00927   ObjectList::ObjectList()
00928   {
00929     list = new LinkedList();
00930   }
00931 
00932   ObjectList::ObjectList(const ObjectArray &obj_array)
00933   {
00934     list = new LinkedList();
00935     for (int i = 0; i < obj_array.getCount(); i++)
00936       insertObjectLast(const_cast<Object *>(obj_array[i]));
00937   }
00938 
00939   int ObjectList::getCount(void) const
00940   {
00941     return list->getCount();
00942   }
00943 
00944   void
00945   ObjectList::insertObject(Object *o)
00946   {
00947     list->insertObject(o);
00948   }
00949 
00950   void
00951   ObjectList::insertObjectFirst(Object *o)
00952   {
00953     list->insertObjectFirst(o);
00954   }
00955 
00956   void
00957   ObjectList::insertObjectLast(Object *o)
00958   {
00959     list->insertObjectLast(o);
00960   }
00961 
00962   Bool
00963   ObjectList::suppressObject(Object *o)
00964   {
00965     return list->deleteObject(o) ? True : False;
00966   }
00967 
00968   Bool
00969   ObjectList::exists(const Object *o) const
00970   {
00971     return list->getPos((void *)o) >= 0 ? True : False;
00972   }
00973 
00974   void
00975   ObjectList::empty()
00976   {
00977     list->empty();
00978   }
00979 
00980   ObjectArray *
00981   ObjectList::toArray() const
00982   {
00983     int cnt = list->getCount();
00984     if (!cnt)
00985       return new ObjectArray();
00986     Object **arr = (Object **)malloc(sizeof(Object *) * cnt);
00987 
00988     LinkedListCursor c(list);
00989     for (int i = 0; c.getNext((void *&)arr[i]); i++)
00990       ;
00991   
00992     ObjectArray *obj_arr = new ObjectArray(arr, cnt);
00993     free(arr);
00994     return obj_arr;
00995   }
00996 
00997   ObjectList::~ObjectList()
00998   {
00999     delete list;
01000   }
01001 
01002   ObjectListCursor::ObjectListCursor(const ObjectList &oidlist)
01003   {
01004     c = new LinkedListCursor(oidlist.list);
01005   }
01006 
01007   ObjectListCursor::ObjectListCursor(const ObjectList *oidlist)
01008   {
01009     c = new LinkedListCursor(oidlist->list);
01010   }
01011 
01012   Bool
01013   ObjectListCursor::getNext(Object *&o)
01014   {
01015     return c->getNext((void *&)o) ? True : False;
01016   }
01017 
01018   ObjectListCursor::~ObjectListCursor()
01019   {
01020     delete c;
01021   }
01022 
01023   Status
01024   Object::loadPerform(const Oid&, LockMode,AttrIdxContext &idx_ctx,
01025                       const RecMode*)
01026   {
01027     return Success;
01028   }
01029 
01030   Status
01031   Object::removePerform(const Oid&, const Oid&, AttrIdxContext&, const RecMode*)
01032   {
01033     return Success;
01034   }
01035 
01036   Status
01037   Object::realizePerform(const Oid&, const Oid&, AttrIdxContext&, const RecMode*)
01038   {
01039     CHK_OBJ(this);
01040     return Success;
01041   }
01042 
01043   Status
01044   Object::getDataspace(const Dataspace *&_dataspace,
01045                        Bool refetch) const
01046   {
01047     /*
01048       if (dataspace) {
01049       _dataspace = dataspace;
01050       return Success;
01051       }
01052 
01053       getDataspaceID();
01054 
01055       if (dspid == Dataspace::DefaultDspid) {
01056       _dataspace = 0;
01057       return Success;
01058       }
01059 
01060       Status s = db->getDataspace(dspid, _dataspace);
01061       if (s) return s;
01062       const_cast<Object *>(this)->dataspace = _dataspace;
01063       return Success;
01064     */
01065 
01066     _dataspace = 0;
01067 
01068     if (oid.isValid() && ((!dataspace && dspid == Dataspace::DefaultDspid) ||
01069                           refetch)) {
01070       ObjectLocation objloc;
01071       Status s = getLocation(objloc);
01072       if (s)
01073         return s;
01074       const_cast<Object *>(this)->dspid = objloc.getDspid();
01075       s = db->getDataspace(dspid, _dataspace);
01076       if (s)
01077         return s;
01078       const_cast<Object *>(this)->dataspace = _dataspace;
01079       return Success;
01080     }
01081 
01082     if (dataspace) {
01083       _dataspace = dataspace;
01084       return Success;
01085     }
01086 
01087     if (dspid != Dataspace::DefaultDspid) {
01088       Status s = db->getDataspace(dspid, _dataspace);
01089       if (s)
01090         return s;
01091       const_cast<Object *>(this)->dataspace = _dataspace;
01092       return Success;
01093     }
01094 
01095     return Success;
01096   }
01097 
01098   Status
01099   Object::getLocation(ObjectLocation &loc) const
01100   {
01101     OidArray oid_arr(&oid, 1);
01102     ObjectLocationArray locarr;
01103     Status s = db->getObjectLocations(oid_arr, locarr);
01104     if (s)
01105       return s;
01106     loc = locarr.getLocation(0);
01107     return Success;
01108   }
01109 
01110 
01111   Status
01112   Object::setDataspace(const Dataspace *_dataspace)
01113   {
01114     /*
01115       if (oid.isValid() && dataspace) {
01116       if (dataspace->getId() == _dataspace->getId())
01117       return Success;
01118       return Exception::make(IDB_ERROR, "use the move method to change the "
01119       "dataspace [#%d to #%d] on the already "
01120       "created object %s", dataspace->getId(),
01121       _dataspace->getId(), oid.toString());
01122 
01123       }
01124     */
01125 
01126     Status s = getDataspace(dataspace);
01127     if (s)
01128       return s;
01129 
01130     if (oid.isValid() && dataspace && dataspace->getId() != _dataspace->getId())
01131       return Exception::make(IDB_ERROR, "use the move method to change the "
01132                              "dataspace [#%d to #%d] on the already "
01133                              "created object %s", dataspace->getId(),
01134                              _dataspace->getId(), oid.toString());
01135   
01136 
01137     dataspace = _dataspace;
01138     dspid = dataspace->getId();
01139     return Success;
01140   }
01141 
01142   Status
01143   Object::move(const Dataspace *_dataspace)
01144   {
01145     OidArray oid_arr(&oid, 1);
01146     return db->moveObjects(oid_arr, _dataspace);
01147     /*
01148       return Exception::make(IDB_ERROR, "Object::move() is "
01149       "not yet implemented");
01150     */
01151   }
01152 
01153   short
01154   Object::getDataspaceID() const
01155   {
01156     if (dataspace)
01157       return dataspace->getId();
01158 
01159     /*
01160       if (dspid != Dataspace::DefaultDspid)
01161       return dspid;
01162 
01163       if (cls) {
01164       const Dataspace *tmp = 0;
01165       Status s = cls->getDefaultInstanceDataspace(tmp);
01166       if (s) throw *s;
01167       if (tmp)
01168       const_cast<Object *>(this)->dspid = tmp->getId();
01169       }
01170     */
01171 
01172     return dspid;
01173   }
01174 
01175   void
01176   Object::setDspid(short _dspid)
01177   {
01178     dspid = _dspid;
01179   }
01180 
01181   void *
01182   Object::setUserData(const char *s, void *x)
01183   {
01184     void *r = getUserData(s);
01185 
01186     if (!user_data_ht)
01187       user_data_ht = new UserDataHT();
01188 
01189     user_data_ht->insert(s, x);
01190     return r;
01191   }
01192 
01193   void *
01194   Object::getUserData(const char *s)
01195   {
01196     if (!user_data_ht)
01197       return (void *)0;
01198 
01199     return user_data_ht->get(s);
01200   }
01201 
01202   const void *
01203   Object::getUserData(const char *s) const
01204   {
01205     if (!user_data_ht)
01206       return (void *)0;
01207 
01208     return user_data_ht->get(s);
01209   }
01210 
01211   void
01212   Object::getAllUserData(LinkedList *&key_list, LinkedList *&data_list) const
01213   {
01214     if (!user_data_ht) {
01215       key_list = new LinkedList();
01216       data_list = new LinkedList();
01217       return;
01218     }
01219 
01220     user_data_ht->getall(key_list, data_list);
01221   }
01222 
01223   gbxBool
01224   Object::grant_release()
01225   {
01226     //return master_object ? gbxFalse : gbxTrue;
01227     return gbxTrue;
01228   }
01229 
01230   void
01231   Object::setDamaged(const Attribute *_damaged_attr)
01232   {
01233     damaged_attr = _damaged_attr;
01234     //printf("setting damaged %s to %p\n", damaged_attr->getName(), this);
01235   }
01236 
01237   Bool
01238   Object::setReleaseCycleDetection(Bool x)
01239   {
01240     Bool o = release_cycle_detection;
01241     release_cycle_detection = x;
01242     return o;
01243   }
01244 
01245   ObjectReleaser::ObjectReleaser(Object *_o)
01246   {
01247     o = _o;
01248     dont_release = False;
01249   }
01250 
01251   Object *
01252   ObjectReleaser::dontRelease()
01253   {
01254     dont_release = True;
01255     return o;
01256   }
01257 
01258   ObjectReleaser::~ObjectReleaser()
01259   {
01260     if (!dont_release)
01261       o->release();
01262   }
01263 
01264   ObjectListReleaser::ObjectListReleaser()
01265   {
01266     dont_release = False;
01267   }
01268 
01269   void
01270   ObjectListReleaser::add(Object *o)
01271   {
01272     list.insertObject(o);
01273   }
01274 
01275   void
01276   ObjectListReleaser::dontRelease()
01277   {
01278     dont_release = True;
01279   }
01280 
01281   ObjectListReleaser::~ObjectListReleaser()
01282   {
01283     if (!dont_release) {
01284       LinkedListCursor c(list);
01285       Object *o;
01286       while (c.getNext((void *&)o))
01287         o->release();
01288     }
01289   }
01290 
01291   ObjectObserver::ObjectObserver(const std::string &tag) :
01292     gbxObserver(tag)
01293   {
01294   }
01295 
01296   void ObjectObserver::addObj(gbxObject *o)
01297   {
01298     if (o->getPTag() == getObjectTag()) {
01299       gbxObserver::addObj(o);
01300     }
01301   }
01302 
01303   void ObjectObserver::rmvObj(gbxObject *_o)
01304   {
01305     /*
01306     Object *o = dynamic_cast<Object *>(_o);
01307     if (o) {
01308     */
01309     if (_o->getPTag() == getObjectTag()) {
01310       gbxObserver::rmvObj(_o);
01311     }
01312   }
01313 
01314   ObjectObserver::~ObjectObserver() {
01315   }
01316 
01317   void ObjectObserver::getObjects(std::vector<Object *> &ov) const
01318   {
01319     std::map<gbxObject *, bool>::const_iterator begin = obj_map->begin();
01320     std::map<gbxObject *, bool>::const_iterator end = obj_map->end();
01321 
01322     ov.erase(ov.begin(), ov.end());
01323     while (begin != end) {
01324       gbxObject *o = (*begin).first;
01325       if (o->getPTag() != getObjectTag()) {
01326         //if (!o) {
01327         std::cerr << "eyedb::Observer error: " << (void *)(*begin).first <<
01328           " is not an eyedb::Object\n";
01329       }
01330       else
01331         ov.push_back((eyedb::Object *)o);
01332       ++begin;
01333     }
01334   }
01335 
01336   bool ObjectObserver::isObjectRegistered(Object *o) const
01337   {
01338     return gbxObserver::isObjectRegistered(o);
01339   }
01340 
01341 }

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