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)
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();
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
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
00306
00307 if (status)
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)
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
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
00512
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
00616
00617 *(Instance *)this = Instance::operator=((const Instance &)o);
00618
00619 copy(&o, False);
00620
00621 return *this;
00622 }
00623 }