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