Agregat.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 #include "eyedb_p.h"
00026 #include "IteratorBE.h"
00027 #include "CollectionBE.h"
00028 #include <assert.h>
00029 #include "Attribute_p.h"
00030 #include "eyedb/gbxcyctx.h"
00031 
00032 //
00033 // Agregat methods
00034 //
00035 
00036 
00037 namespace eyedb {
00038 
00039 Status Agregat::checkAgreg(const Attribute *agreg) const
00040 {
00041   unsigned int num;
00042   const Attribute **items = ((AgregatClass *)getClass())->getAttributes(num);
00043 
00044   if (!agreg)
00045     return Exception::make(IDB_ATTRIBUTE_ERROR, "invalid null attribute in agregat class '%s'", getClass()->getName());
00046 
00047   if (agreg->num >= num || agreg != items[agreg->num])
00048     return Exception::make(IDB_ATTRIBUTE_ERROR, "attribute '%s' [%d vs %d] is not valid for agregat class '%s'",
00049                            agreg->name, agreg->num, num, getClass()->getName());
00050 
00051   return Success;
00052 }
00053 
00054 Status Agregat::setItemOid(const Attribute *agreg, const Oid *poid, int nb, int from)
00055 {
00056   Status status;
00057   status = agreg->setOid(this, poid, nb, from);
00058 
00059   if (status == Success)
00060     modify = True;
00061 
00062   return status;
00063 }
00064 
00065 Status Agregat::getItemOid(const Attribute *agreg, Oid *poid, int nb, int from) const
00066 {
00067   Status status = checkAgreg(agreg);
00068 
00069   if (status)
00070     return status;
00071 
00072   return agreg->getOid(this, poid, nb, from);
00073 }
00074 
00075 Status Agregat::setItemValue(const Attribute* agreg, Data data,
00076                              int nb, int from)
00077 {
00078   Status status = checkAgreg(agreg);
00079 
00080   if (status)
00081     return status;
00082 
00083   status = agreg->setValue(this, data, nb, from);
00084 #if 1
00085   if (status == Success)
00086     {
00087       if (((AgregatClass *)getClass())->asUnionClass())
00088         ((Union *)this)->setCurrentItem(agreg);
00089       modify = True;
00090     }
00091 #endif
00092   return status;
00093 }
00094 
00095 Status Agregat::setItemSize(const Attribute* agreg, Size size)
00096 {
00097   Status status = checkAgreg(agreg);
00098 
00099   if (status)
00100     return status;
00101 
00102   return agreg->setSize(this, size);
00103 }
00104 
00105 Status Agregat::getItemSize(const Attribute* agreg, Size* psize) const
00106 {
00107   Status status = checkAgreg(agreg);
00108 
00109   if (status)
00110     return status;
00111 
00112   return agreg->getSize(this, *psize);
00113 }
00114 
00115 Status Agregat::trace_realize(FILE *fd, int indent, unsigned int flags,
00116                               const RecMode *rcm) const
00117 {
00118   IDB_CHECK_INTR();
00119   AgregatClass *ma = (AgregatClass *)getClass();
00120   Status status = Success;
00121   int j;
00122   char *indent_str = make_indent(indent);
00123   char *lastindent_str = make_indent(indent-INDENT_INC);
00124 
00125   fprintf(fd, "{ ");
00126   trace_flags(fd, flags);
00127   fprintf(fd, "\n");
00128 
00129   if (state & Tracing)
00130     {
00131       fprintf(fd, "%s<trace cycle>\n", indent_str);
00132       fprintf(fd, "%s};\n", lastindent_str);
00133       delete_indent(indent_str);
00134       delete_indent(lastindent_str);
00135       return Success;
00136     }
00137 
00138   const_cast<Agregat *>(this)->state |= Tracing;
00139 
00140   if (traceRemoved(fd, indent_str))
00141     goto out;
00142  
00143   if (!getClass()->isAttrsComplete())
00144     {
00145       Status status = const_cast<Class*>(getClass())->attrsComplete();
00146       if (status) goto out;
00147     }
00148 
00149   if (((AgregatClass *)getClass())->asUnionClass())
00150     {
00151       const Attribute *item;
00152       if ((item = ((const Union *)this)->getCurrentItem()) >= 0)
00153         status = item->trace(this, fd, &indent, flags, rcm);
00154     }
00155   else
00156     {
00157       unsigned int items_cnt;
00158       int isnat = ((flags & NativeTrace) == NativeTrace);
00159       const Attribute **items = getClass()->getAttributes(items_cnt);
00160       for (int n = 0; n < items_cnt; n++)
00161         if (!items[n]->isNative() || isnat)
00162           {
00163             if ((status = items[n]->trace(this, fd, &indent, flags, rcm)) != Success)
00164               break;
00165           }
00166     }
00167 
00168  out:
00169   const_cast<Agregat *>(this)->state &= ~Tracing;
00170   fprintf(fd, "%s};\n", lastindent_str);
00171   delete_indent(indent_str);
00172   delete_indent(lastindent_str);
00173 
00174   return status;
00175 }
00176 
00177 Status Agregat::trace(FILE *fd, unsigned int flags, const RecMode *rcm) const
00178 {
00179   fprintf(fd, "%s {%s} = ", getClass()->getName(), oid.getString());
00180   return trace_realize(fd, INDENT_INC, flags, rcm);
00181 }
00182 
00183 Status Agregat::create_realize(Bool realizing)
00184 {
00185   if (!getClass())
00186     return Exception::make(IDB_NO_CLASS);
00187 
00188   if (!getClass()->getOid().isValid())
00189     return Exception::make(IDB_CLASS_NOT_CREATED, "creating agregat of class '%s'", getClass()->getName());
00190 
00191   classOidCode();
00192 
00193   if (!realizing)
00194     {
00195       RPCStatus rpc_status;
00196 
00197       rpc_status = oidMake(db->getDbHandle(), getDataspaceID(),
00198                                idr->getIDR(), idr->getSize(),
00199                                oid.getOid());
00200 
00201       return StatusMake(rpc_status);
00202     }
00203 
00204   modify = True;
00205   return Success;
00206 }
00207 
00208 Status Agregat::create()
00209 {
00210   fprintf(stderr, "!cannot use create method!\n");
00211   abort();
00212   if (oid.isValid())
00213     return Exception::make(IDB_OBJECT_ALREADY_CREATED, "creating agregat of class '%s'", getClass()->getName());
00214 
00215   return create_realize(False);
00216 }
00217 
00218 Status Agregat::update_realize(Bool realizing)
00219 {
00220   if (!getClass()->getOid().isValid())
00221     return Exception::make(IDB_CLASS_NOT_CREATED, "updating agregat of class '%s'", getClass()->getName());
00222 
00223 #if 1
00224   classOidCode(); // added the 28/08/01
00225 #endif
00226 
00227   if (!realizing)
00228     {
00229       RPCStatus rpc_status;
00230       rpc_status = objectWrite(db->getDbHandle(), idr->getIDR(), oid.getOid());
00231 
00232       if (rpc_status != RPCSuccess)
00233         return StatusMake(rpc_status);
00234 
00235     }
00236   
00237   return Success;
00238 }
00239 
00240 Status Agregat::update()
00241 {
00242   if (!oid.isValid())
00243     return Exception::make(IDB_OBJECT_ALREADY_CREATED, "updating agregat of class '%s'", getClass()->getName());
00244 
00245   return update_realize(False);
00246 }
00247 
00248 Status Agregat::realize(const RecMode *rcm)
00249 {
00250   //printf("Agregat::realize(%p %s)\n", this, getClass()->getName());
00251   if (state & Realizing)
00252     return Success;
00253 
00254   CHK_OBJ(this);
00255 
00256   IDB_CHECK_WRITE(db);
00257 
00258   Status status;
00259 
00260   if (getMasterObject(true)) {
00261     return getMasterObject(true)->realize(rcm);
00262   }
00263 
00264   Bool creating;
00265 
00266   state |= Realizing;
00267 
00268   if (!oid.isValid())
00269     {
00270       status = create_realize(False);
00271       creating = True;
00272     }
00273   else
00274     {
00275       status = update_realize(True);
00276       creating = False;
00277     }
00278 
00279   if (!status)
00280     {
00281       AttrIdxContext idx_ctx;
00282       status = realizePerform(getClass()->getOid(), getOid(), idx_ctx, rcm);
00283 
00284       if (!status)
00285         {
00286           if (creating)
00287             {
00288               status = StatusMake
00289                 (objectCreate(db->getDbHandle(), getDataspaceID(),
00290                               idr->getIDR(), oid.getOid()));
00291               if (!status)
00292                 modify = False;
00293             }
00294           else if (modify)
00295             {
00296               status = StatusMake
00297                 (objectWrite(db->getDbHandle(),
00298                              idr->getIDR(), oid.getOid()));
00299               if (!status)
00300                 modify = False;
00301             }
00302         }
00303     }
00304 
00305   // added the 17/05/99 because of cache incohency
00306   //if (status && isDirty())
00307   if (status) // changed the 2/05/99 because of index incoherency
00308     {
00309       int err = status->getStatus();
00310       if (err != IDB_UNIQUE_CONSTRAINT_ERROR &&
00311           err != IDB_UNIQUE_COMP_CONSTRAINT_ERROR &&
00312           err != IDB_NOTNULL_CONSTRAINT_ERROR &&
00313           err != IDB_NOTNULL_COMP_CONSTRAINT_ERROR)
00314         {
00315           db->setIncoherency();
00316           db->uncacheObject(this);
00317           std::string str = status->getString();
00318           status = Exception::make(status->getStatus(),
00319                                    str + ": the current transaction must "
00320                                    "be aborted");
00321         }
00322     }
00323   else if (creating)
00324     db->cacheObject(this);
00325 
00326   state &= ~Realizing;
00327   return status;
00328 }
00329 
00330 Status Agregat::realizePerform(const Oid& cloid,
00331                                const Oid& objoid,
00332                                AttrIdxContext &idx_ctx,
00333                                const RecMode *rcm)
00334 {
00335   CHK_OBJ(this);
00336 
00337   Status status;
00338   unsigned int items_cnt;
00339   const Attribute **items;
00340 
00341   items = getClass()->getAttributes(items_cnt);
00342   
00343   for (int i = 0; i < items_cnt; i++)
00344     if (status = items[i]->realize(db, this, cloid, objoid, idx_ctx, rcm))
00345       return status;
00346 
00347   return Success;
00348 }
00349 
00350 void
00351 Agregat::manageCycle(gbxCycleContext &r)
00352 {
00353   if (r.isCycle()) {
00354 #ifdef MANAGE_CYCLE_TRACE
00355     printf("found #1 premature cycle for %p\n", this);
00356 #endif
00357     return;
00358   }
00359 
00360   if (gbx_chgRefCnt) {
00361     r.manageCycle(this);
00362     return;
00363   }
00364 
00365   if (!getClass())
00366     return;
00367 
00368   gbx_chgRefCnt = gbxTrue;
00369 
00370   unsigned int items_cnt;
00371   const Attribute **items;
00372   items = getClass()->getAttributes(items_cnt);
00373 
00374   for (int i = 0; i < items_cnt; i++)
00375     items[i]->manageCycle(db, this, r);
00376 
00377   gbx_chgRefCnt = gbxFalse;
00378   return;
00379 }
00380 
00381 Status Agregat::removePerform(const Oid& cloid, 
00382                               const Oid& objoid,
00383                               AttrIdxContext &idx_ctx,
00384                               const RecMode *rcm)
00385 {
00386   if (((AgregatClass *)getClass())->asUnionClass())
00387     {
00388       Attribute *item = (Attribute *)((Union *)this)->getCurrentItem();
00389       if (item)
00390         return item->remove(db, this, cloid, objoid, idx_ctx, rcm);
00391       return Success;
00392     }
00393 
00394   Status status;
00395   unsigned int items_cnt;
00396   const Attribute **items;
00397   
00398   items = ((AgregatClass *)getClass())->getAttributes(items_cnt);
00399   
00400   for (int i = 0; i < items_cnt; i++)
00401     if ((status = items[i]->remove(db, this, cloid, objoid, idx_ctx, rcm)) !=
00402         Success &&
00403         status->getStatus() != IDB_OBJECT_NOT_CREATED)
00404       return status;
00405   
00406   return Success;
00407 }
00408 
00409 Status Agregat::remove(const RecMode *rcm)
00410 {
00411   if (!oid.isValid())
00412     return Exception::make(IDB_OBJECT_NOT_CREATED,
00413                            "removing agregat of class '%s'",
00414                            getClass()->getName());
00415 
00416   if (state & Removing)
00417     return Success;
00418 
00419   Status status;
00420   state |= Removing;
00421 
00422   AttrIdxContext idx_ctx;
00423   status = removePerform(getClass()->getOid(), getOid(), idx_ctx, rcm);
00424 
00425   if (status == Success)
00426     status = Object::remove(rcm);
00427 
00428   if (status) // changed the 9/07/99 because of index incoherency
00429     {
00430       db->setIncoherency();
00431       db->uncacheObject(this);
00432       std::string str = status->getString();
00433       status = Exception::make(status->getStatus(),
00434                                str + ": the current transaction must "
00435                                "be aborted");
00436     }
00437 
00438   state &= ~Removing;
00439   return status;
00440 }
00441 
00442 void Agregat::initialize(Database *_db)
00443 {
00444   Instance::initialize(_db);
00445 }
00446 
00447 Agregat::Agregat(Database *_db, const Dataspace *_dataspace) :
00448   Instance(_db, _dataspace)
00449 {
00450   //  Instance::initialize(_db); // conceptually is Agregat::initialize(_db)
00451 }
00452 
00453 Status
00454 Agregat::loadPerform(const Oid& cloid,
00455                      LockMode lockmode,
00456                      AttrIdxContext &idx_ctx,
00457                      const RecMode *rcm)
00458 {
00459   unsigned int items_cnt;
00460   const Attribute **items = getClass()->getAttributes(items_cnt);
00461   
00462   for (int i = 0; i < items_cnt; i++)
00463     {
00464       Status status;
00465       status = items[i]->load(db, this, cloid, lockmode, idx_ctx, rcm);
00466       if (status) return status;
00467     }
00468 
00469   return Success;
00470 }
00471 
00472 Status
00473 agregatMake(Database *db, const Oid *oid, Object **o,
00474                 const RecMode *rcm, const ObjectHeader *hdr,
00475                 Data idr, LockMode lockmode, const Class *_class)
00476 {
00477   RPCStatus rpc_status;
00478 
00479   if (!_class)
00480     {
00481       _class = db->getSchema()->getClass(hdr->oid_cl, True);
00482 
00483       if (!_class)
00484         return Exception::make(IDB_CLASS_NOT_FOUND, "agregat class '%s'",
00485                                OidGetString(&hdr->oid_cl));
00486     }
00487 
00488   Status status;
00489   Agregat *a;
00490   *o = 0;
00491 
00492   Database::consapp_t consapp = db->getConsApp(_class);
00493   if (consapp) 
00494     {
00495       if (!ObjectPeer::isRemoved(*hdr))
00496         *o = consapp(_class, idr);
00497       else
00498         *o = consapp(_class, 0);
00499     }
00500   
00501   if (!*o)
00502     {
00503       if (idr && !ObjectPeer::isRemoved(*hdr))
00504         *o = _class->newObj(idr + IDB_OBJ_HEAD_SIZE, False);
00505       else
00506         *o = _class->newObj();
00507     }
00508   
00509   a = (Agregat *)*o;
00510   /*
00511     status = a->setDatabase(db);
00512     if (status) return status;
00513   */
00514 
00515   ObjectPeer::setDatabase(*o, db);
00516 
00517   if (idr)
00518     rpc_status = RPCSuccess;
00519   else
00520     rpc_status = objectRead(db->getDbHandle(), a->getIDR(), 0, 0,
00521                                 oid->getOid(), 0, lockmode, 0);
00522 
00523   if (rcm->getType() != RecMode_NoRecurs)
00524     db->insertTempCache(*oid, *o);
00525 
00526   if (!rpc_status)
00527     {
00528       AttrIdxContext idx_ctx;
00529       return a->loadPerform(_class->getOid(), lockmode, idx_ctx, rcm);
00530     }
00531 
00532   return StatusMake(rpc_status);
00533 }
00534 
00535 Status Agregat::getValue(unsigned char**) const
00536 {
00537   return Success;
00538 }
00539 
00540 Status Agregat::setValue(unsigned char*)
00541 {
00542   return Success;
00543 }
00544 
00545 #ifdef GBX_NEW_CYCLE
00546 void Agregat::decrRefCountPropag()
00547 {
00548   int items_cnt;
00549   const Attribute **items =
00550     ((AgregatClass *)getClass())->getAttributes(items_cnt);
00551   
00552   for (int i = 0; i < items_cnt; i++)
00553     items[i]->decrRefCountPropag(this, idr->getRefCount());
00554 }
00555 #endif
00556 
00557 void Agregat::garbage()
00558 {
00559   if (getClass() && getClass()->isValidObject())  {
00560     if (((AgregatClass *)getClass())->asUnionClass()) {
00561       Attribute *item = (Attribute *)((Union *)this)->getCurrentItem();
00562       if (item)
00563         item->garbage(this, idr->getRefCount());
00564     }
00565     else {
00566       unsigned int items_cnt;
00567       const Attribute **items =
00568         ((AgregatClass *)getClass())->getAttributes(items_cnt);
00569 
00570       for (int i = 0; i < items_cnt; i++)
00571         items[i]->garbage(this, idr->getRefCount());
00572     }
00573   }
00574 
00575   Instance::garbage();
00576 }
00577 
00578 Agregat::~Agregat()
00579 {
00580   garbageRealize();
00581 }
00582 
00583 void
00584 Agregat::copy(const Agregat *o, Bool share)
00585 {
00586   if (((AgregatClass *)getClass())->asUnionClass()) {
00587     Attribute *item = (Attribute *)((Union *)this)->getCurrentItem();
00588     if (item)
00589       item->copy(this, share);
00590   }
00591   else {
00592     unsigned int items_cnt;
00593     const Attribute **items =
00594       ((AgregatClass *)getClass())->getAttributes(items_cnt);
00595       
00596     for (int i = 0; i < items_cnt; i++)
00597       items[i]->copy(this, share);
00598   }
00599 }
00600 
00601 Agregat::Agregat(const Agregat *o, Bool share) : Instance(o, share) {
00602   copy(o, share);
00603 }
00604 
00605 Agregat::Agregat(const Agregat &o) : Instance(o)
00606 {
00607   copy(&o, False);
00608 }
00609 
00610 Agregat& Agregat::operator=(const Agregat &o)
00611 {
00612   if (&o == this)
00613     return *this;
00614 
00615   //garbageRealize();
00616 
00617   *(Instance *)this = Instance::operator=((const Instance &)o);
00618 
00619   copy(&o, False);
00620 
00621   return *this;
00622 }
00623 }

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