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
00026 #define NEW_GET_ELEMENTS
00027
00028 #include "eyedb_p.h"
00029 #include "ValueCache.h"
00030 #include "CollectionBE.h"
00031 #include <assert.h>
00032 #include "AttrNative.h"
00033 #include "Attribute_p.h"
00034
00035 #define NEW_MASTER_OBJ
00036
00037 #define TRY_GETELEMS_GC
00038
00039
00040
00041 static bool eyedb_support_stack = getenv("EYEDB_SUPPORT_STACK") ? true : false;
00042
00043 using namespace std;
00044
00045 namespace eyedb {
00046
00047 static Offset LITERAL_OFFSET;
00048
00049 extern int
00050 get_item_size(const Class *coll_class, int dim);
00051
00052 static Bool collupd_noopt = getenv("EYEDB_COLLUPD_NOOPT") ? True : False;
00053
00054 #define CACHE_LIST(C) ((C) ? (C)->getList() : (LinkedList *)0)
00055 #define CACHE_LIST_COUNT(C) ((C) ? (C)->getIdMap().size() : 0)
00056
00057
00058
00059 #define COLL_OPTIM_CREATE
00060 #define COLL_OPTIM_LOAD
00061
00062 #define COLL_REENTRANT
00063
00064
00065
00066
00067 static int COLLIMPL_DEFAULT = (int)CollImpl::HashIndex;
00068
00069 const Size Collection::defaultSize = (Size)-1;
00070
00071
00072
00073
00074
00075 static inline IndexImpl *getDefaultIndexImpl()
00076 {
00077 static IndexImpl *defIndexImpl;
00078 if (!defIndexImpl) {
00079 defIndexImpl = new IndexImpl(IndexImpl::Hash, 0, 0, 0, 0, 0);
00080 }
00081 return defIndexImpl;
00082 }
00083
00084 static inline CollImpl *getDefaultCollImpl(int impl_type)
00085 {
00086 static CollImpl *defCollImpl_noindex;
00087 static CollImpl *defCollImpl_hashindex;
00088 if (impl_type == CollImpl::NoIndex) {
00089 if (!defCollImpl_noindex) {
00090 defCollImpl_noindex = new CollImpl(CollImpl::NoIndex);
00091 }
00092 return defCollImpl_noindex;
00093 }
00094
00095 if (!defCollImpl_hashindex) {
00096 defCollImpl_hashindex = new CollImpl(getDefaultIndexImpl());
00097 }
00098 return defCollImpl_hashindex;
00099 }
00100
00101 void Collection::_init(const CollImpl *_collimpl)
00102 {
00103 if (isref || !coll_class)
00104 item_size = sizeof(Oid);
00105 else
00106 item_size = get_item_size(coll_class, dim);
00107
00108 Exception::Mode mode = Exception::setMode(Exception::StatusMode);
00109
00110 #if 0
00111 if (item_size > COLL_SIZE_MAX)
00112 status = Exception::make(IDB_COLLECTION_ITEM_SIZE_TOO_LARGE,
00113 "collection '%s', item size is '%d', "
00114 "max size is '%d'",
00115 name, item_size, COLL_SIZE_MAX);
00116 else
00117 #endif
00118 if (item_size == 0)
00119 status = Exception::make(IDB_COLLECTION_ITEM_SIZE_UNKNOWN,
00120 "collection '%s'", name);
00121 else
00122 status = Success;
00123
00124 Exception::setMode(mode);
00125
00126 cache = 0;
00127
00128 read_cache.obj_arr = 0;
00129 read_cache.oid_arr = 0;
00130 read_cache.val_arr = 0;
00131
00132 read_cache_state_oid = read_cache_state_value = read_cache_state_object = coherent;
00133 read_cache_state_index = False;
00134 locked = False;
00135 if (!_collimpl) {
00136 _collimpl = getDefaultCollImpl(COLLIMPL_DEFAULT);
00137 }
00138
00139 collimpl = _collimpl->clone();
00140 isStringColl();
00141 card = NULL;
00142 card_oid.invalidate();
00143 bottom = top = 0;
00144 inv_oid.invalidate();
00145 inv_item = 0;
00146 inverse_valid = True;
00147 literal_oid.invalidate();
00148 is_literal = False;
00149 is_pure_literal = False;
00150 is_complete = True;
00151 idx_data = 0;
00152 idx_data_size = 0;
00153 implModified = False;
00154 nameModified = False;
00155 #ifdef INIT_IDR
00156 inv_oid_offset = 0;
00157 init_idr();
00158 #endif
00159 }
00160
00161 void Collection::unvalidReadCache()
00162 {
00163 read_cache_state_oid = read_cache_state_object = read_cache_state_value = modified;
00164 read_cache_state_index = False;
00165 }
00166
00167 void Collection::create_cache()
00168 {
00169 if (!cache)
00170 cache = new ValueCache(this);
00171 }
00172
00173 void Collection::isStringColl()
00174 {
00175 if (!strcmp(coll_class->getName(), char_class_name) && dim > 1)
00176 string_coll = True;
00177 else
00178 string_coll = False;
00179 }
00180
00181 void Collection::decode(Data data) const
00182 {
00183 Offset offset = 0;
00184 if (isref) {
00185 eyedbsm::Oid smoid;
00186 oid_decode(data, &offset, &smoid);
00187 memcpy(data, &smoid, sizeof(smoid));
00188 }
00189 else if (coll_class->asInt16Class()) {
00190 eyedblib::int16 i16;
00191 int16_decode(data, &offset, &i16);
00192 memcpy(data, &i16, sizeof(i16));
00193 }
00194 else if (coll_class->asInt32Class()) {
00195 eyedblib::int32 i32;
00196 int32_decode(data, &offset, &i32);
00197 memcpy(data, &i32, sizeof(i32));
00198 }
00199 else if (coll_class->asInt64Class()) {
00200 eyedblib::int64 i64;
00201 int64_decode(data, &offset, &i64);
00202 memcpy(data, &i64, sizeof(i64));
00203 }
00204 else if (coll_class->asFloatClass()) {
00205 double d;
00206 double_decode(data, &offset, &d);
00207 memcpy(data, &d, sizeof(d));
00208 }
00209 }
00210
00211 Data Collection::make_data(Data data, Size size, Bool swap) const
00212 {
00213 if (size == defaultSize)
00214 size = item_size;
00215
00216 if (size < 0 || size > item_size)
00217 return 0;
00218
00219 Data item_data;
00220
00221 item_data = (unsigned char *)malloc(item_size);
00222
00223 if (string_coll) {
00224 int len = strlen((char *)data);
00225
00226 if (len >= item_size) {
00227 free(item_data);
00228 return 0;
00229 }
00230
00231 strcpy((char *)item_data, (char *)data);
00232 memset((char *)item_data+len, 0, item_size-len);
00233 }
00234 else if (swap) {
00235 if (isref)
00236 oid_code(item_data, data);
00237 else if (coll_class->asInt16Class())
00238 int16_code(item_data, data);
00239 else if (coll_class->asInt32Class())
00240 int32_code(item_data, data);
00241 else if (coll_class->asInt64Class())
00242 int64_code(item_data, data);
00243 else if (coll_class->asFloatClass())
00244 double_code(item_data, data);
00245 else {
00246 memcpy(item_data, data, size);
00247
00248 if (size < item_size)
00249 memset(item_data+size, 0, item_size-size);
00250 }
00251 }
00252 else {
00253 memcpy(item_data, data, size);
00254
00255 if (size < item_size)
00256 memset(item_data+size, 0, item_size-size);
00257 }
00258
00259 return item_data;
00260 }
00261
00262 Status Collection::realizeInverse(const Oid& _inv_oid, int _inv_item)
00263 {
00264 setInverse(_inv_oid, _inv_item);
00265
00266
00267 if (!inv_oid.isValid())
00268 return Success;
00269
00270 if (status != Success)
00271 return Exception::make(IDB_COLLECTION_ERROR,
00272 "invalid collection status: \"%s\"",
00273 status->getDesc());
00274
00275 if (!getOidC().isValid())
00276 return Exception::make(IDB_COLLECTION_ERROR, "collection oid '%s' is not valid", name);
00277
00278 Data temp = 0;
00279 Offset offset = IDB_OBJ_HEAD_SIZE;
00280 Size alloc_size = 0;
00281
00282 oid_code(&temp, &offset, &alloc_size, inv_oid.getOid());
00283 int16_code(&temp, &offset, &alloc_size, &inv_item);
00284
00285 ObjectHeader hdr;
00286 memset(&hdr, 0, sizeof(hdr));
00287
00288 hdr.type = type;
00289 hdr.size = alloc_size;
00290 hdr.xinfo = IDB_XINFO_INV;
00291
00292 offset = 0;
00293
00294 object_header_code(&temp, &offset, &alloc_size, &hdr);
00295
00296 RPCStatus rpc_status;
00297
00298 rpc_status = objectWrite(db->getDbHandle(), temp, getOidC().getOid());
00299
00300 free(temp);
00301
00302 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
00303 }
00304
00305 void Collection::setInverse(const Oid& _inv_oid, int _inv_item)
00306 {
00307
00308 inv_oid = _inv_oid;
00309 inv_item = _inv_item;
00310 }
00311
00312 void Collection::setCardinalityConstraint(Object *_card)
00313 {
00314 #ifdef CARD_TRACE
00315 printf("Collection::setCardinalityConstraint(%p)\n", _card);
00316 #endif
00317 if (!_card) {
00318 card = NULL;
00319 card_oid.invalidate();
00320 return;
00321 }
00322
00323 if (!strcmp(_card->getClass()->getName(), "cardinality_constraint")) {
00324 card = ((CardinalityConstraint *)_card)->getCardDesc();
00325 if (!card) {
00326 card_oid.invalidate();
00327 return;
00328 }
00329 }
00330 else
00331 card = (CardinalityDescription *)_card;
00332
00333 card_oid = _card->getOid();
00334 card_bottom = card->getBottom();
00335 card_bottom_excl = card->getBottomExcl();
00336 card_top = card->getTop();
00337 card_top_excl = card->getTopExcl();
00338 }
00339
00340 CardinalityDescription *Collection::getCardinalityConstraint() const
00341 {
00342 return card;
00343 }
00344
00345
00346
00347
00348
00349 Collection::Collection(const char *n, Class *_class,
00350 const Oid& _idx1_oid,
00351 const Oid& _idx2_oid,
00352 int icnt,
00353 int _bottom, int _top,
00354 const CollImpl *_collimpl,
00355 Object *_card, Bool _is_literal, Bool _is_pure_literal,
00356 Data _idx_data, Size _idx_data_size) :
00357 Instance()
00358 {
00359 name = strdup(n);
00360 p_items_cnt = icnt;
00361 v_items_cnt = icnt;
00362 setClass(_class);
00363 bottom = _bottom;
00364 top = _top;
00365 setCardinalityConstraint(_card);
00366 coll_class = getClass()->asCollectionClass()->getCollClass(&isref,
00367 &dim,
00368 &item_size);
00369 if (dim <= 0) {
00370 Exception::Mode mode = Exception::setMode(Exception::StatusMode);
00371 status = Exception::make(IDB_COLLECTION_ERROR, "invalid dimension: %d\n", dim);
00372 Exception::setMode(mode);
00373 return;
00374 }
00375
00376 idx1_oid = _idx1_oid;
00377 idx2_oid = _idx2_oid;
00378
00379 status = Success;
00380
00381 locked = False;
00382
00383 if (!_collimpl) {
00384 _collimpl = getDefaultCollImpl(COLLIMPL_DEFAULT);
00385 }
00386
00387 collimpl = _collimpl->clone();
00388 cache = 0;
00389
00390 unvalidReadCache();
00391
00392 read_cache.obj_arr = 0;
00393 read_cache.oid_arr = 0;
00394 read_cache.val_arr = 0;
00395
00396 isStringColl();
00397 inv_oid.invalidate();
00398 inv_item = 0;
00399 inverse_valid = True;
00400 literal_oid.invalidate();
00401 is_literal = _is_literal;
00402 is_pure_literal = _is_pure_literal;
00403 is_complete = True;
00404 idx_data_size = _idx_data_size;
00405 idx_data = (idx_data_size ? (Data)malloc(idx_data_size) : 0);
00406 memcpy(idx_data, _idx_data, idx_data_size);
00407 implModified = False;
00408 nameModified = False;
00409 #ifdef INIT_IDR
00410 inv_oid_offset = 0;
00411 init_idr();
00412 #endif
00413
00414 #ifdef COLLTRACE
00415 printf("Collection[%p] -> %s\n", this,
00416 (const char *)AttrIdxContext(idx_data, idx_data_size).getString());
00417 #endif
00418 }
00419
00420 void Collection::make(const char *n, Class *mc, Bool _isref,
00421 const CollImpl *_collimpl)
00422 {
00423 name = strdup(n);
00424 p_items_cnt = 0;
00425 v_items_cnt = 0;
00426 coll_class = (mc ? mc : Object_Class);
00427 isref = _isref;
00428 dim = 1;
00429
00430 status = Success;
00431
00432 _init(_collimpl);
00433 }
00434
00435 void Collection::make(const char *n, Class *mc, int _dim,
00436 const CollImpl *_collimpl)
00437 {
00438 name = strdup(n);
00439 p_items_cnt = 0;
00440 v_items_cnt = 0;
00441 coll_class = (mc ? mc : Object_Class);
00442 isref = False;
00443 dim = _dim;
00444
00445 if (dim <= 0) {
00446 Exception::Mode mode = Exception::setMode(Exception::StatusMode);
00447 status = Exception::make(IDB_COLLECTION_ERROR, "invalid dimension: %d\n", dim);
00448 Exception::setMode(mode);
00449 return;
00450 }
00451
00452 status = Success;
00453
00454 _init(_collimpl);
00455 }
00456
00457 Collection::Collection(const char *n, Class *mc, Bool _isref,
00458 const CollImpl *_collimpl) : Instance()
00459 {
00460 make(n, mc, _isref, _collimpl);
00461 }
00462
00463 Collection::Collection(const char *n, Class *mc, int _dim,
00464 const CollImpl *_collimpl) : Instance()
00465 {
00466 make(n, mc, _dim, _collimpl);
00467 }
00468
00469 Collection::Collection(const Collection &coll) : Instance(coll)
00470 {
00471 name = 0;
00472 cache = 0;
00473 idx_data = 0;
00474 idx_data_size = 0;
00475 memset(&read_cache, 0, sizeof(ReadCache));
00476 status = Success;
00477 collimpl = 0;
00478 *this = coll;
00479 }
00480
00481 #define CLONE(X) ((X) ? (X)->clone() : 0)
00482 #define STRDUP(X) ((X) ? strdup(X) : 0)
00483
00484 #ifndef NEW_MASTER_OBJ
00485 static Object *
00486 get_master_object(Object *o)
00487 {
00488 if (!o) return 0;
00489
00490 if (o->getMasterObject())
00491 return get_master_object(o->getMasterObject());
00492
00493 return o;
00494 }
00495 #endif
00496
00497 void Collection::setImplementation(const CollImpl *_collimpl)
00498 {
00499 if (!collimpl->compare(_collimpl)) {
00500 if (collimpl)
00501 collimpl->release();
00502 collimpl = _collimpl->clone();
00503 #ifdef NEW_MASTER_OBJ
00504 if (is_literal && getMasterObject(true))
00505 getMasterObject(true)->touch();
00506 #else
00507 if (is_literal && getMasterObject())
00508 get_master_object(getMasterObject())->touch();
00509 #endif
00510 touch();
00511 implModified = True;
00512 }
00513 }
00514
00515 Collection& Collection::operator=(const Collection &coll)
00516 {
00517
00518
00519 *(Object *)this = (const Object &)coll;
00520 type = coll.type;
00521 name = STRDUP(coll.name);
00522 ordered = coll.ordered;
00523 allow_dup = coll.allow_dup;
00524 string_coll = coll.string_coll;
00525 bottom = coll.bottom;
00526 top = coll.top;
00527
00528 coll_class = coll.coll_class;
00529
00530 isref = coll.isref;
00531 dim = coll.dim;
00532 item_size = coll.item_size;
00533 cl_oid = coll.cl_oid;
00534
00535 locked = coll.locked;
00536 collimpl = coll.collimpl->clone();
00537 inv_oid = coll.inv_oid;
00538 inv_item = coll.inv_item;
00539
00540 card = (CardinalityDescription *)CLONE(coll.card);
00541 card_bottom = coll.card_bottom;
00542 card_bottom_excl = coll.card_bottom_excl;
00543 card_top = coll.card_top;
00544 card_top_excl = coll.card_top_excl;
00545 card_oid = coll.card_oid;
00546
00547 idx1_oid = coll.idx1_oid;
00548 idx2_oid = coll.idx2_oid;
00549 idx1 = coll.idx1;
00550 idx2 = coll.idx2;
00551 p_items_cnt = coll.p_items_cnt;
00552 v_items_cnt = coll.v_items_cnt;
00553 inverse_valid = coll.inverse_valid;
00554 is_literal = coll.is_literal;
00555 is_pure_literal = coll.is_pure_literal;
00556 is_complete = coll.is_complete;
00557 literal_oid = coll.literal_oid;
00558 idx_data_size = coll.idx_data_size;
00559 idx_data = (idx_data_size ? (Data)malloc(idx_data_size) : 0);
00560 memcpy(idx_data, coll.idx_data, idx_data_size);
00561
00562
00563 cache = 0;
00564
00565 read_cache.obj_arr = 0;
00566 read_cache.oid_arr = 0;
00567 read_cache.val_arr = 0;
00568
00569 return *this;
00570 }
00571
00572 Status Collection::setDatabase(Database *mdb)
00573 {
00574 if (mdb == db)
00575 return Success;
00576
00577 Database *odb = db;
00578
00579 if (odb && odb != mdb) {
00580 assert(0);
00581 return Exception::make(IDB_ERROR, "cannot change dynamically database of an object");
00582 }
00583
00584 db = mdb;
00585
00586 Class *_cls = getClass();
00587 Status s = CollectionClass::make(db, &_cls);
00588 if (!s)
00589 setClass(_cls);
00590 return s;
00591 }
00592
00593 void Collection::setLiteral(Bool _is_literal)
00594 {
00595 is_literal = _is_literal;
00596 }
00597
00598 void Collection::setPureLiteral(Bool _is_pure_literal)
00599 {
00600 is_pure_literal = _is_pure_literal;
00601 }
00602
00603 char Collection::codeLiteral() const
00604 {
00605 if (is_pure_literal)
00606 return CollPureLiteral;
00607
00608 if (is_literal)
00609 return CollLiteral;
00610
00611 return CollObject;
00612 }
00613
00614 void Collection::decodeLiteral(char c, Bool &is_literal, Bool &is_pure_literal)
00615 {
00616 if (c == CollPureLiteral) {
00617 is_pure_literal = True;
00618 is_literal = True;
00619 }
00620 else if (c == CollLiteral) {
00621 is_pure_literal = False;
00622 is_literal = True;
00623 }
00624 else {
00625 is_pure_literal = False;
00626 is_literal = False;
00627 }
00628 }
00629
00630 Status Collection::loadLiteral()
00631 {
00632 unsigned char data[1];
00633 short dspid = 0;
00634 Oid toid = literal_oid;
00635 if (!toid.isValid())
00636 toid = getOid();
00637
00638 if (!toid.isValid())
00639 return Success;
00640
00641 RPCStatus rpc_status = dataRead(db->getDbHandle(), LITERAL_OFFSET,
00642 sizeof(char),
00643 data, &dspid, toid.getOid());
00644 if (rpc_status)
00645 return StatusMake(rpc_status);
00646
00647 Offset offset = 0;
00648 char c;
00649 char_decode (data, &offset, &c);
00650 Collection::decodeLiteral(c, is_literal, is_pure_literal);
00651
00652 return Success;
00653 }
00654
00655 Status Collection::updateLiteral()
00656 {
00657 if (db) {
00658 char new_code = codeLiteral();
00659
00660 Oid toid = literal_oid;
00661 if (!toid.isValid())
00662 toid = getOid();
00663
00664 if (toid.isValid()) {
00665 Offset offset = 0;
00666 Size alloc_size = sizeof(char);
00667 unsigned char data[1];
00668 unsigned char *pdata = data;
00669 char_code(&pdata, &offset, &alloc_size, &new_code);
00670 RPCStatus rpc_status = dataWrite(db->getDbHandle(), LITERAL_OFFSET,
00671 sizeof(char),
00672 data, toid.getOid());
00673
00674 if (rpc_status)
00675 return StatusMake(rpc_status);
00676 }
00677 }
00678
00679 return Success;
00680 }
00681
00682 Bool Collection::isLiteralObject() const
00683 {
00684 return is_literal && !is_pure_literal ? True : False;
00685 }
00686
00687 Status Collection::setLiteralObject(bool reload)
00688 {
00689 if (reload) {
00690 Status s = loadLiteral();
00691 if (s)
00692 return s;
00693 }
00694
00695 if (!isLiteral())
00696 return Exception::make(IDB_COLLECTION_ERROR,
00697 "collection %s is not a literal",
00698 getOid().toString());
00699
00700
00701 #if 0
00702 if (isLiteralObject())
00703 return Exception::make(IDB_COLLECTION_ERROR,
00704 "collection %s is already a literal object",
00705 getOid().toString());
00706 #endif
00707
00708 setPureLiteral(False);
00709
00710 return updateLiteral();
00711 }
00712
00713 Status Collection::setMasterObject(Object *_master_object)
00714 {
00715 Object *master_obj = 0;
00716 if (is_literal && (master_obj = getMasterObject(true))) {
00717 Object *r_master_object = _master_object->getMasterObject(true);
00718 if (!r_master_object)
00719 r_master_object = _master_object;
00720
00721 if ((master_obj->getOid().isValid() ||
00722 r_master_object->getOid().isValid()) &&
00723 master_obj->getOid() != r_master_object->getOid()) {
00724 return Exception::make("collection setting master object %s: "
00725 "%s is already a literal attribute "
00726 "for the object",
00727 r_master_object->getOid().toString(),
00728 getOidC().toString(),
00729 master_obj->getOid().toString());
00730 }
00731 }
00732
00733 Status s = Object::setMasterObject(_master_object);
00734 if (s)
00735 return s;
00736
00737
00738
00739
00740
00741
00742
00743 char old_code = codeLiteral();
00744
00745 setLiteral(True);
00746
00747 if (getOid().isValid())
00748 setPureLiteral(False);
00749 else
00750 setPureLiteral(True);
00751
00752
00753
00754
00755 if (!getLiteralOid().isValid())
00756 setLiteralOid(getOid());
00757
00758 if (!is_pure_literal)
00759 ObjectPeer::setOid(this, Oid::nullOid);
00760
00761 if (!getDatabase())
00762 setDatabase(_master_object->getDatabase());
00763
00764 char new_code = codeLiteral();
00765 if (new_code != old_code) {
00766 Status s = updateLiteral();
00767 if (s)
00768 return s;
00769 }
00770
00771 return Success;
00772 }
00773
00774 Status Collection::releaseMasterObject()
00775 {
00776 Status s = loadLiteral();
00777 if (s)
00778 return s;
00779
00780 bool to_release = (is_pure_literal && getOidC().isValid());
00781 char old_code = codeLiteral();
00782
00783 setLiteral(False);
00784 setPureLiteral(False);
00785
00786 char new_code = codeLiteral();
00787
00788 if (new_code != old_code) {
00789 s = updateLiteral();
00790 if (s)
00791 return s;
00792 }
00793
00794
00795
00796
00797
00798 ObjectPeer::setOid(this, getLiteralOid());
00799 setLiteralOid(Oid::nullOid);
00800
00801 s = Object::releaseMasterObject();
00802 if (s)
00803 return s;
00804
00805 if (to_release) {
00806 return remove();
00807 }
00808
00809 return Success;
00810 }
00811
00812
00813
00814
00815
00816 Status Collection::check(const Oid &item_oid,
00817 const Class *item_class,
00818 Error err) const
00819 {
00820 Bool is;
00821 Status s = coll_class->isSuperClassOf(item_class, &is);
00822
00823 if (s)
00824 return s;
00825
00826 if (is)
00827 return Success;
00828
00829 return Exception::make(err, "item '%s' is of class '%s', expected subclass of '%s'", item_oid.getString(),
00830 item_class->getName(),
00831 coll_class->getName());
00832 }
00833
00834 Status Collection::check(const Oid& item_oid, Error err) const
00835 {
00836 if (status != Success)
00837 return Exception::make(err,
00838 "invalid collection status: \"%s\"",
00839 status->getDesc());
00840 if (!isref)
00841 return Exception::make(err,
00842 "must use Collection::insert(Data, Size)"
00843 " or Collection::insert(const Value &)");
00844
00845 Status s;
00846 Class *item_class;
00847
00848 s = db->getObjectClass(item_oid, item_class);
00849
00850 if (s)
00851 return s;
00852
00853 return check(item_oid, item_class, err);
00854 }
00855
00856 Status Collection::check(const Object *item_o, Error err) const
00857 {
00858 if (status != Success)
00859 return Exception::make(err,
00860 "invalid collection status: \"%s\"",
00861 status->getDesc());
00862
00863 if (!item_o)
00864 return Exception::make(err, "");
00865
00866 if (item_o->isOnStack()) {
00867 if (!eyedb_support_stack)
00868 return Exception::make(IDB_COLLECTION_ERROR,
00869 "cannot insert a stack allocated object in collection '%s'", oid.toString());
00870 }
00871
00872
00873 if (!isref &&
00874 !coll_class->asBasicClass() &&
00875 !coll_class->asEnumClass()) {
00876 unsigned int attr_cnt;
00877 const Attribute **attrs = coll_class->getAttributes(attr_cnt);
00878 for (int n = 0; n < attr_cnt; n++) {
00879 const Attribute *attr = attrs[n];
00880 if (!attr->isIndirect())
00881 continue;
00882
00883 const TypeModifier &tmod = attr->getTypeModifier();
00884 for (int i = 0; i < tmod.pdims; i++) {
00885 Data data_obj = 0;
00886 Status s = attr->getValue(item_o, &data_obj, 1, i);
00887 if (s)
00888 return s;
00889 if (!data_obj)
00890 continue;
00891
00892 Oid item_oid;
00893 s = attr->getOid(item_o, &item_oid, 1, i);
00894 if (s)
00895 return s;
00896 if (!item_oid.isValid())
00897 return Exception::make(IDB_COLLECTION_ERROR,
00898 "object is not completed: attribute "
00899 "%s::%s has a value and no oid",
00900 coll_class->getName(),
00901 attr->getName());
00902 }
00903 }
00904 }
00905
00906 if (isref)
00907 return check(item_o->getOid(), item_o->getClass(), err);
00908
00909 return Success;
00910 }
00911
00912 Status Collection::check(Data val, Size size, Error err) const
00913 {
00914 if (status != Success)
00915 return Exception::make(err,
00916 "invalid collection status: \"%s\"",
00917 status->getDesc());
00918
00919 if (isref)
00920 return Exception::make(err, "must use Collection::insert(const Object *) or insert(const Oid&)");
00921
00922 if (!val)
00923 return Exception::make(err, "trying to insert a null value");
00924
00925 if (size != defaultSize && size > item_size)
00926 return Exception::make(err, "size too large %d, expected %d", size, item_size);
00927
00928 return Success;
00929 }
00930
00931 static const char invalid_type_fmt[] = "invalid type: expected %s, got %s";
00932
00933 Status Collection::check(const Value &v, Error err) const
00934 {
00935 if (v.type == Value::tObject)
00936 return check(v.o, err);
00937
00938 if (v.type == Value::tObjectPtr)
00939 return check(v.o_ptr->getObject(), err);
00940
00941 if (v.type == Value::tOid)
00942 return check(Oid(*v.oid), err);
00943
00944 if (v.type == Value::tString) {
00945 if (!string_coll)
00946 return Exception::make(err, invalid_type_fmt,
00947 getStringType().c_str(), v.getStringType());
00948 return check((Data)v.str, strlen(v.str), err);
00949 }
00950
00951 if (v.type == Value::tChar) {
00952 if (!coll_class->asCharClass())
00953 return Exception::make(err, invalid_type_fmt,
00954 getStringType().c_str(), v.getStringType());
00955 return check((Data)&v.c, sizeof(v.c), err);
00956 }
00957
00958 if (v.type == Value::tShort) {
00959 if (!coll_class->asInt16Class())
00960 return Exception::make(err, invalid_type_fmt,
00961 getStringType().c_str(), v.getStringType());
00962 return check((Data)&v.s, sizeof(v.s), err);
00963 }
00964
00965 if (v.type == Value::tInt) {
00966 if (!coll_class->asInt32Class())
00967 return Exception::make(err, invalid_type_fmt,
00968 getStringType().c_str(), v.getStringType());
00969 return check((Data)&v.i, sizeof(v.i), err);
00970 }
00971
00972 if (v.type == Value::tLong) {
00973 if (!coll_class->asInt64Class())
00974 return Exception::make(err, invalid_type_fmt,
00975 getStringType().c_str(), v.getStringType());
00976 return check((Data)&v.l, sizeof(v.l), err);
00977 }
00978
00979 if (v.type == Value::tDouble) {
00980 if (!coll_class->asFloatClass())
00981 return Exception::make(err, invalid_type_fmt,
00982 getStringType().c_str(), v.getStringType());
00983 return check((Data)&v.d, sizeof(v.d), err);
00984 }
00985
00986 if (v.type == Value::tData) {
00987 if (!coll_class->asByteClass())
00988 return Exception::make(err, invalid_type_fmt,
00989 getStringType().c_str(), v.getStringType());
00990 return check(v.data.data, v.data.size, err);
00991 }
00992
00993 return Exception::make(err, invalid_type_fmt, getStringType().c_str(),
00994 v.getStringType());
00995 }
00996
00997 std::string Collection::getStringType() const
00998 {
00999 string s = coll_class->getName();
01000 if (isref)
01001 s += "*";
01002 if (dim > 1)
01003 s += "[" + str_convert(dim) + "]";
01004 return s;
01005 }
01006
01007 Status Collection::insert(const Value &v, Bool noDup)
01008 {
01009 Status s = check(v, IDB_COLLECTION_INSERT_ERROR);
01010 if (s)
01011 return s;
01012
01013 if (v.type == Value::tObject)
01014 return insert_p(v.o, noDup);
01015
01016 if (v.type == Value::tObjectPtr)
01017 return insert_p(v.o_ptr->getObject(), noDup);
01018
01019 if (v.type == Value::tOid)
01020 return insert_p(Oid(*v.oid), noDup);
01021
01022 Size size;
01023 Data data = v.getData(&size);
01024
01025 return insert_p(data, noDup, size);
01026 }
01027
01028 Status Collection::suppress(const Value &v, Bool checkFirst)
01029 {
01030 Status s = check(v, IDB_COLLECTION_SUPPRESS_ERROR);
01031 if (s)
01032 return s;
01033
01034 if (v.type == Value::tObject)
01035 return suppress_p(v.o, checkFirst);
01036
01037 if (v.type == Value::tObjectPtr)
01038 return suppress_p(v.o_ptr->getObject(), checkFirst);
01039
01040 if (v.type == Value::tOid)
01041 return suppress_p(Oid(*v.oid), checkFirst);
01042
01043 Size size;
01044 Data data = v.getData(&size);
01045
01046 return suppress_p(data, checkFirst, size);
01047 }
01048
01049
01050
01051
01052
01053 Status Collection::suppress_p(const Oid &item_oid, Bool checkFirst)
01054 {
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 if (CollectionPeer::isLocked(this))
01070 return Exception::make(IDB_COLLECTION_LOCKED, "collection '%s' is locked for writing", name);
01071
01072 if (status)
01073 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR,
01074 "invalid collection status: \"%s\"",
01075 status->getDesc());
01076
01077
01078
01079
01080 IDB_COLL_LOAD_DEFERRED();
01081 touch();
01082 ValueItem *item;
01083
01084 if (cache && (item = cache->get(item_oid))) {
01085 int s = item->getState();
01086 if (s == removed) {
01087 if (checkFirst)
01088 return Success;
01089 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "item '%s' is already suppressed", item_oid.getString());
01090 }
01091 else if (s == coherent)
01092 item->setState(removed);
01093 else if (s == added)
01094 cache->suppressOid(item);
01095
01096 v_items_cnt--;
01097 return Success;
01098 }
01099
01100 if (!getOidC().isValid())
01101 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "collection oid is invalid (collection has not been stored)");
01102
01103 int found, ind;
01104
01105 RPCStatus rpc_status;
01106
01107 if ((rpc_status = collectionGetByOid(db->getDbHandle(),
01108 getOidC().getOid(),
01109 item_oid.getOid(), &found, &ind)) ==
01110 RPCSuccess) {
01111 if (!found) {
01112 if (checkFirst)
01113 return Success;
01114 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "item '%s' not found in collection '%s'", item_oid.getString(), name);
01115 }
01116 }
01117 else
01118 return StatusMake(IDB_COLLECTION_SUPPRESS_ERROR, rpc_status);
01119
01120 create_cache();
01121
01122 cache->insert(item_oid, ValueCache::DefaultItemID, removed);
01123 v_items_cnt--;
01124 return Success;
01125 }
01126
01127 Status Collection::suppress_p(const Object *item_o, Bool checkFirst)
01128 {
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 if (CollectionPeer::isLocked(this))
01153 return Exception::make(IDB_COLLECTION_LOCKED, "collection '%s' is locked for writing", name);
01154
01155 if (status != Success)
01156 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR,
01157 "invalid collection status: \"%s\"",
01158 status->getDesc());
01159 if (!item_o)
01160 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "trying to suppress a null object");
01161
01162 IDB_COLL_LOAD_DEFERRED();
01163 touch();
01164 ValueItem *item;
01165
01166 if (cache && (item = cache->get(item_o))) {
01167 int s = item->getState();
01168 if (s == removed) {
01169 if (checkFirst)
01170 return Success;
01171 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "object 0x%x has already been suppressed", item_o);
01172 }
01173 else if (s == coherent)
01174 item->setState(removed);
01175 else if (s == added)
01176 cache->suppressObject(item);
01177
01178 v_items_cnt--;
01179 return Success;
01180 }
01181
01182 Oid item_oid = item_o->getOid();
01183
01184 if (!item_oid.isValid())
01185 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "oid item of object 0x%x is invalid", item_o);
01186
01187 if (cache && (item = cache->get(item_oid))) {
01188 int s = item->getState();
01189 if (s == removed) {
01190 if (checkFirst)
01191 return Success;
01192 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "item '%s' has been already suppressed", item_oid.getString());
01193 }
01194 else if (s == coherent)
01195 item->setState(removed);
01196 else if (s == added)
01197 item->setState(removed);
01198
01199 v_items_cnt--;
01200 return Success;
01201 }
01202
01203 if (!getOidC().isValid())
01204 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "collection oid is invalid (collection has not been stored)");
01205
01206 int found, ind;
01207
01208 RPCStatus rpc_status;
01209
01210 if ((rpc_status = collectionGetByOid(db->getDbHandle(),
01211 getOidC().getOid(),
01212 item_oid.getOid(), &found, &ind)) ==
01213 RPCSuccess) {
01214 if (!found) {
01215 if (checkFirst)
01216 return Success;
01217 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR, "item '%s' not found in collection", item_oid.toString());
01218 }
01219 }
01220 else
01221 return StatusMake(IDB_COLLECTION_SUPPRESS_ERROR, rpc_status);
01222
01223 create_cache();
01224
01225 cache->insert(item_o, ValueCache::DefaultItemID, removed);
01226 v_items_cnt--;
01227 return Success;
01228 }
01229
01230 Status Collection::suppress_p(Data val, Bool, Size size)
01231 {
01232 if (status != Success)
01233 return Exception::make(IDB_COLLECTION_SUPPRESS_ERROR,
01234 "invalid collection status: \"%s\"",
01235 status->getDesc());
01236 return Exception::make(IDB_ERROR, "Collection::suppress(Data val) is not implemented");
01237 }
01238
01239
01240
01241
01242
01243 Status Collection::empty()
01244 {
01245 if (CollectionPeer::isLocked(this))
01246 return Exception::make(IDB_COLLECTION_LOCKED,
01247 "collection '%s' is locked for writing", name);
01248
01249 emptyReadCache();
01250
01251 if (cache) {
01252 cache->setState(removed);
01253 }
01254
01255 IDB_COLL_LOAD_DEFERRED();
01256 touch();
01257 if (!getOidC().isValid()) {
01258 p_items_cnt = 0;
01259 v_items_cnt = 0;
01260 top = bottom = 0;
01261 return Success;
01262 }
01263
01264 Status s;
01265 Iterator q(this, True);
01266
01267 if ((s = q.getStatus()))
01268 return s;
01269
01270 IteratorAtom qatom;
01271 int ind = 0;
01272 for (int n = 0; ; n++) {
01273 Bool found;
01274 s = q.scanNext(&found, &qatom);
01275 if (s) {
01276
01277 return s;
01278 }
01279
01280 if (!found)
01281 break;
01282
01283 if (asCollArray()) {
01284 if (!(n & 1)) {
01285 assert(qatom.type == IteratorAtom_INT32);
01286 ind = qatom.i32;
01287 continue;
01288 }
01289 }
01290 else
01291 ind = ValueCache::DefaultItemID;
01292
01293 create_cache();
01294 if (isref)
01295 cache->insert(&qatom.oid, ind, removed);
01296 else {
01297 Data _idr = 0;
01298 Offset offset = 0;
01299 Size alloc_size = 0;
01300 qatom.code(&_idr, &offset, &alloc_size);
01301 cache->insert(Value(idr->getIDR(), item_size), ind, removed);
01302 }
01303 }
01304
01305 p_items_cnt = 0;
01306 v_items_cnt = 0;
01307 top = bottom = 0;
01308 return Success;
01309 }
01310
01311
01312
01313
01314
01315 Status Collection::isIn_p(const Oid &item_oid, Bool &found,
01316 Collection::ItemId *where) const
01317 {
01318
01319
01320
01321
01322
01323
01324
01325 ValueItem *item;
01326
01327 found = False;
01328
01329 if (cache && (item = cache->get(item_oid))) {
01330 if (item->getState() != removed)
01331 found = True;
01332
01333 return Success;
01334 }
01335
01336 if (!getOidC().isValid())
01337 return Success;
01338
01339
01340 int f, ind;
01341
01342 RPCStatus rpc_status;
01343
01344 rpc_status = collectionGetByOid(db->getDbHandle(), getOidC().getOid(),
01345 item_oid.getOid(), &f, &ind);
01346
01347 found = (f ? True : False);
01348 if (found && where) *where = ind;
01349
01350 return StatusMake(IDB_COLLECTION_IS_IN_ERROR, rpc_status);
01351 }
01352
01353 Status Collection::isIn_p(const Object *item_o, Bool &found,
01354 Collection::ItemId *where) const
01355 {
01356
01357
01358
01359
01360
01361
01362 found = False;
01363
01364 if (!item_o)
01365 return Exception::make(IDB_COLLECTION_IS_IN_ERROR, "trying to check presence of a null object");
01366
01367 if (!isref)
01368 return isIn_p(item_o->getIDR() + IDB_OBJ_HEAD_SIZE, found, defaultSize,
01369 where);
01370
01371 ValueItem *item;
01372
01373 if (cache && (item = cache->get(item_o)) && item->getState() != removed) {
01374 found = True;
01375 return Success;
01376 }
01377
01378 Oid item_oid = item_o->getOid();
01379
01380 if (item_oid.isValid() && cache && (item = cache->get(item_oid)) &&
01381 item->getState() != removed) {
01382 found = True;
01383 return Success;
01384 }
01385
01386 if (!getOidC().isValid())
01387 return Success;
01388
01389 int f, ind;
01390
01391 RPCStatus rpc_status;
01392
01393 rpc_status = collectionGetByOid(db->getDbHandle(), getOidC().getOid(),
01394 item_oid.getOid(), &f, &ind);
01395
01396 found = (f ? True : False);
01397 if (found && where) *where = ind;
01398 return StatusMake(IDB_COLLECTION_IS_IN_ERROR, rpc_status);
01399 }
01400
01401 Status Collection::isIn_p(Data data, Bool &found, Size size,
01402 Collection::ItemId *where) const
01403 {
01404
01405
01406
01407
01408
01409 ((Collection *)this)->status = check(data, size, IDB_COLLECTION_IS_IN_ERROR);
01410
01411 if (status != Success)
01412 return status;
01413
01414 ValueItem *item;
01415
01416 Data item_data = make_data(data, size, True);
01417
01418 if (!item_data)
01419 return Exception::make(IDB_COLLECTION_ERROR, "data too long for collection search");
01420
01421 if (cache && (item = cache->get(item_data, item_size))) {
01422 if (item->getState() != removed)
01423 found = True;
01424 return Success;
01425 }
01426
01427 if (!getOidC().isValid())
01428 return Success;
01429
01430 int f, ind;
01431
01432 RPCStatus rpc_status;
01433
01434 rpc_status = collectionGetByValue(db->getDbHandle(),
01435 getOidC().getOid(), item_data,
01436 item_size, &f, &ind);
01437
01438 found = (f ? True : False);
01439 if (found && where) *where = ind;
01440 return StatusMake(IDB_COLLECTION_IS_IN_ERROR, rpc_status);
01441 }
01442
01443 Status Collection::isIn(const Value &v, Bool &found,
01444 Collection::ItemId *where) const
01445 {
01446 Status s = check(v, IDB_COLLECTION_ERROR);
01447 if (s)
01448 return s;
01449
01450 if (v.type == Value::tObject)
01451 return isIn_p(v.o, found, where);
01452
01453 if (v.type == Value::tObjectPtr)
01454 return isIn_p(v.o_ptr->getObject(), found, where);
01455
01456 if (v.type == Value::tOid)
01457 return isIn_p(Oid(*v.oid), found, where);
01458
01459 Size size;
01460 Data data = v.getData(&size);
01461
01462 return isIn_p(data, found, size, where);
01463 }
01464
01465 Status Collection::getStatus() const
01466 {
01467 return status;
01468 }
01469
01470 int Collection::getCount() const
01471 {
01472 if (!is_complete)
01473 (void)const_cast<Collection *>(this)->loadDeferred();
01474 return v_items_cnt;
01475 }
01476
01477 int Collection::getBottom() const
01478 {
01479 if (!is_complete)
01480 (void)const_cast<Collection *>(this)->loadDeferred();
01481 return bottom;
01482 }
01483
01484 int Collection::getTop() const
01485 {
01486 if (!is_complete)
01487 (void)const_cast<Collection *>(this)->loadDeferred();
01488 return top;
01489 }
01490
01491 Bool Collection::isEmpty() const
01492 {
01493 if (!is_complete)
01494 (void)const_cast<Collection *>(this)->loadDeferred();
01495 return (v_items_cnt == 0 ? True : False);
01496 }
01497
01498 void Collection::setName(const char *_name)
01499 {
01500 if (!is_complete)
01501 (void)const_cast<Collection *>(this)->loadDeferred();
01502 free(name);
01503 name = strdup(_name);
01504 touch();
01505 nameModified = True;
01506 }
01507
01508 void Collection::garbage()
01509 {
01510 free(name);
01511 delete cache;
01512 emptyReadCache();
01513 free(idx_data);
01514 Instance::garbage();
01515 if (collimpl)
01516 collimpl->release();
01517 }
01518
01519 Collection::~Collection()
01520 {
01521 garbageRealize();
01522 }
01523
01524 Status Collection::setValue(Data)
01525 {
01526 return Success;
01527 }
01528
01529 Status Collection::getValue(Data*) const
01530 {
01531 return Success;
01532 }
01533
01534 Status Collection::create()
01535 {
01536 return create_realize(NoRecurs);
01537 }
01538
01539 void Collection::cardCode(Data &data, Offset &offset, Size &alloc_size)
01540 {
01541
01542 if (card_oid.isValid()) {
01543 oid_code(&data, &offset, &alloc_size, card_oid.getOid());
01544 return;
01545 }
01546
01547 oid_code(&data, &offset, &alloc_size, getInvalidOid());
01548 }
01549
01550 Object *Collection::cardDecode(Database *db, Data temp, Offset &offset)
01551 {
01552 eyedbsm::Oid xoid;
01553
01554 oid_decode(temp, &offset, &xoid);
01555
01556 Oid coid(xoid);
01557
01558
01559
01560 if (!coid.isValid())
01561 return NULL;
01562
01563 Object *card;
01564
01565 Status status = db->loadObject(&coid, &card);
01566
01567 if (status) {
01568 status->print();
01569 return NULL;
01570 }
01571
01572 return card;
01573 }
01574
01575 Status Collection::codeCollImpl(Data &data, Offset &offset,
01576 Size &alloc_size)
01577 {
01578 return IndexImpl::code(data, offset, alloc_size, collimpl->getIndexImpl(), collimpl->getType());
01579 }
01580
01581 Status Collection::getImplStats(std::string &xstats, Bool dspImpl, Bool full,
01582 const char *indent)
01583 {
01584 IndexStats *stats;
01585 Status s = getImplStats(stats);
01586 if (s) return s;
01587 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01588 delete stats;
01589 return Success;
01590 }
01591
01592 void Collection::completeImplStats(IndexStats *stats) const
01593 {
01594 const IndexImpl *idximpl = collimpl->getIndexImpl();
01595 if (idximpl) {
01596 if (idximpl->getDataspace())
01597 stats->idximpl->setDataspace(idximpl->getDataspace());
01598 if (idximpl->getHashMethod())
01599 stats->idximpl->setHashMethod(idximpl->getHashMethod());
01600 }
01601 }
01602
01603 Status Collection::getIdxOid(Oid &idx1oid, Oid &idx2oid) const
01604 {
01605 idx1oid = idx1_oid;
01606 idx2oid = idx2_oid;
01607
01608 if (is_literal && !idx1oid.isValid()) {
01609 if (literal_oid.isValid()) {
01610 Object *o;
01611 Status s = db->loadObject(literal_oid, (Object *&)o);
01612 if (s) return s;
01613 idx1oid = o->asCollection()->idx1_oid;
01614 idx2oid = o->asCollection()->idx2_oid;
01615 o->release();
01616 }
01617 }
01618
01619 return Success;
01620 }
01621
01622 Status Collection::getImplStats(IndexStats *&stats)
01623 {
01624 Oid idx1oid, idx2oid;
01625 Status s = getIdxOid(idx1oid, idx2oid);
01626 if (s) return s;
01627
01628 if (idx1oid.isValid()) {
01629 RPCStatus rpc_status =
01630 collectionGetImplStats(db->getDbHandle(), collimpl->getType(),
01631 idx1oid.getOid(), (Data *)&stats);
01632 if (rpc_status)
01633 return StatusMake(rpc_status);
01634 completeImplStats(stats);
01635 return Success;
01636 }
01637
01638 stats = 0;
01639 return Success;
01640 }
01641
01642 Status Collection::simulate(const CollImpl &_collimpl, std::string &xstats,
01643 Bool dspImpl, Bool full, const char *indent)
01644 {
01645 IndexStats *stats;
01646 Status s = simulate(_collimpl, stats);
01647 if (s) return s;
01648 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01649 delete stats;
01650 return Success;
01651 }
01652
01653 Status Collection::simulate(const CollImpl &_collimpl, IndexStats *&stats)
01654 {
01655 Oid idx1oid, idx2oid;
01656 Status s = getIdxOid(idx1oid, idx2oid);
01657 if (s) return s;
01658
01659 if (idx1oid.isValid()) {
01660 Data data;
01661 Offset offset = 0;
01662 Size size = 0;
01663 Status s = IndexImpl::code(data, offset, size, _collimpl.getIndexImpl());
01664 if (s) return s;
01665 RPCStatus rpc_status =
01666 collectionSimulImplStats(db->getDbHandle(), _collimpl.getType(),
01667 idx1oid.getOid(), data, size,
01668 (Data *)&stats);
01669 return StatusMake(rpc_status);
01670 }
01671
01672 stats = 0;
01673 return Success;
01674 }
01675
01676 Status Collection::init_idr() {
01677 #ifdef INIT_IDR
01678 assert(!getIDR());
01679 Size alloc_size = 0;
01680 Offset offset = IDB_OBJ_HEAD_SIZE;
01681
01682 idr->setIDR((Size)0);
01683 Data data = 0;
01684
01685
01686 char c = locked;
01687 char_code (&data, &offset, &alloc_size, &c);
01688
01689
01690 eyedblib::int16 kk = (eyedblib::int16)item_size;
01691 int16_code (&data, &offset, &alloc_size, &kk);
01692
01693 Status s = codeCollImpl(data, offset, alloc_size);
01694 if (s)
01695 return s;
01696
01697
01698 oid_code (&data, &offset, &alloc_size, getInvalidOid());
01699
01700 oid_code (&data, &offset, &alloc_size, getInvalidOid());
01701
01702 eyedblib::int32 zero = 0;
01703
01704
01705 int32_code (&data, &offset, &alloc_size, &zero);
01706
01707 int32_code (&data, &offset, &alloc_size, &zero);
01708
01709 int32_code (&data, &offset, &alloc_size, &zero);
01710
01711 cardCode(data, offset, alloc_size);
01712
01713 inv_oid_offset = offset;
01714 oid_code(&data, &offset, &alloc_size, inv_oid.getOid());
01715 int16_code(&data, &offset, &alloc_size, &inv_item);
01716
01717 char c = codeLiteral();
01718
01719 LITERAL_OFFSET = offset;
01720 char_code (&data, &offset, &alloc_size, &c);
01721 eyedblib::int16 sz = idx_data_size;
01722 int16_code (&data, &offset, &alloc_size, &sz);
01723 buffer_code(&data, &offset, &alloc_size, idx_data, idx_data_size);
01724
01725
01726 string_code(&data, &offset, &alloc_size, name);
01727
01728 int idr_sz = offset;
01729 idr->setIDR(idr_sz, data);
01730 headerCode(type, idr_sz);
01731 #endif
01732 return Success;
01733 }
01734
01735 Status Collection::create_realize(const RecMode *rcm)
01736 {
01737 if (status != Success)
01738 return Exception::make(IDB_COLLECTION_ERROR,
01739 "invalid collection status: \"%s\"",
01740 status->getDesc());
01741
01742 if (getOidC().isValid())
01743 return Exception::make(IDB_OBJECT_ALREADY_CREATED, "%scollection %s",
01744 is_literal ? "literal " : "",
01745 getOidC().toString());
01746
01747 IDB_CHECK_WRITE(db);
01748
01749 Status s;
01750 if (!getClass()->getOid().isValid()) {
01751 s = getClass()->create();
01752 if (s) return s;
01753 }
01754
01755 #if 0
01756 Size wr_size = 0;
01757 unsigned char *temp = 0;
01758 Offset cache_offset = 0;
01759 if (!is_literal) {
01760 s = cache_compile(cache_offset, wr_size, &temp, rcm);
01761 if (s) return s;
01762 }
01763 #endif
01764
01765 #ifdef INIT_IDR
01766 assert(getIDR());
01767
01768 #else
01769 Size alloc_size = 0;
01770 Offset offset = IDB_OBJ_HEAD_SIZE;
01771
01772 idr->setIDR((Size)0);
01773 Data data = 0;
01774
01775
01776 char c = locked;
01777 char_code (&data, &offset, &alloc_size, &c);
01778
01779
01780 eyedblib::int16 kk = (eyedblib::int16)item_size;
01781 int16_code (&data, &offset, &alloc_size, &kk);
01782
01783 s = codeCollImpl(data, offset, alloc_size);
01784 if (s) return s;
01785
01786
01787 oid_code (&data, &offset, &alloc_size, getInvalidOid());
01788
01789 oid_code (&data, &offset, &alloc_size, getInvalidOid());
01790
01791 eyedblib::int32 zero = 0;
01792
01793
01794 int32_code (&data, &offset, &alloc_size, &zero);
01795
01796 int32_code (&data, &offset, &alloc_size, &zero);
01797
01798 int32_code (&data, &offset, &alloc_size, &zero);
01799
01800 cardCode(data, offset, alloc_size);
01801 #endif
01802
01803 if (is_literal) {
01804 #ifdef NEW_MASTER_OBJ
01805 Object *o = getMasterObject(true);
01806 #else
01807 Object *o = get_master_object(getMasterObject());
01808 #endif
01809 if (!inv_oid.isValid())
01810 inv_oid = o->getOid();
01811
01812 if (!o->getOid().isValid())
01813 return Exception::make(IDB_ERROR,
01814 "inner object of class '%s' containing "
01815 "collection of type '%s' has no valid oid",
01816 o->getClass()->getName(), getClass()->getName());
01817
01818 assert(inv_oid == o->getOid());
01819 }
01820
01821 #ifdef INIT_IDR
01822 Offset offset = inv_oid_offset;
01823 assert(offset);
01824 Size alloc_size = idr->getSize();
01825 Data data = idr->getIDR();
01826
01827 oid_code(&data, &offset, &alloc_size, inv_oid.getOid());
01828
01829 int16_code(&data, &offset, &alloc_size, &inv_item);
01830
01831 c = codeLiteral();
01832
01833 char_code (&data, &offset, &alloc_size, &c);
01834 eyedblib::int16 sz = idx_data_size;
01835 printf("IDX_DATA_SIZE = %d\n", idx_data_size);
01836 int16_code (&data, &offset, &alloc_size, &sz);
01837 buffer_code(&data, &offset, &alloc_size, idx_data, idx_data_size);
01838 #else
01839
01840 oid_code(&data, &offset, &alloc_size, inv_oid.getOid());
01841
01842 int16_code(&data, &offset, &alloc_size, &inv_item);
01843
01844 c = codeLiteral();
01845
01846 char_code (&data, &offset, &alloc_size, &c);
01847 eyedblib::int16 sz = idx_data_size;
01848 int16_code (&data, &offset, &alloc_size, &sz);
01849 buffer_code(&data, &offset, &alloc_size, idx_data, idx_data_size);
01850
01851
01852 string_code(&data, &offset, &alloc_size, name);
01853
01854 int idr_sz = offset;
01855 idr->setIDR(idr_sz, data);
01856 headerCode(type, idr_sz);
01857
01858
01859 #endif
01860
01861
01862 RPCStatus rpc_status;
01863
01864 rpc_status = objectCreate(db->getDbHandle(), getDataspaceID(), data, getOidC().getOid());
01865
01866 if (rpc_status != RPCSuccess)
01867 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
01868
01869 if (!getOidC().getDbid() && getOidC().getNX())
01870 abort();
01871
01872 db->cacheObject(this);
01873
01874 if (is_literal) {
01875 implModified = False;
01876 return Success;
01877 }
01878
01879
01880
01881 ObjectHeader hdr;
01882 memset(&hdr, 0, sizeof(hdr));
01883
01884 #if 1
01885 Size wr_size = 0;
01886 unsigned char *temp = 0;
01887 Offset cache_offset = 0;
01888 if (!is_literal) {
01889 s = cache_compile(cache_offset, wr_size, &temp, rcm);
01890 if (s) return s;
01891 }
01892 #endif
01893
01894 if (wr_size) {
01895
01896 short x = 0;
01897 int16_code(&temp, &cache_offset, &wr_size, &x);
01898
01899 hdr.type = type;
01900 hdr.size = wr_size;
01901
01902 object_header_code_head(temp, &hdr);
01903
01904 rpc_status = objectWrite(db->getDbHandle(), temp, getOidC().getOid());
01905 }
01906
01907 free(temp);
01908 if (!rpc_status) {
01909 delete cache;
01910 cache = 0;
01911 emptyReadCache();
01912 implModified = False;
01913 nameModified = False;
01914 modify = False;
01915 }
01916
01917 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
01918 }
01919
01920 Status Collection::update()
01921 {
01922 return update_realize(NoRecurs);
01923 }
01924
01925 Status Collection::update_realize(const RecMode *rcm)
01926 {
01927 if (status != Success)
01928 return Exception::make(IDB_COLLECTION_ERROR,
01929 "invalid collection status: \"%s\"",
01930 status->getDesc());
01931
01932 if (!getOidC().isValid())
01933 return Exception::make(IDB_COLLECTION_ERROR, "collection oid '%s' is not valid", name);
01934
01935 if (!getClass()->getOid().isValid())
01936 return Exception::make(IDB_COLLECTION_ERROR, "collection '%s' has not a valid class", name);
01937
01938
01939 Size alloc_size;
01940
01941 unsigned char *temp;
01942 Offset offset;
01943 Status _status = cache_compile(offset, alloc_size, &temp, rcm);
01944 if (_status)
01945 return _status;
01946
01947 RPCStatus rpc_status;
01948
01949 ObjectHeader hdr;
01950 memset(&hdr, 0, sizeof(hdr));
01951
01952 short c = 0;
01953 if (implModified) {
01954 c |= IDB_COLL_IMPL_CHANGED;
01955 }
01956 if (nameModified) {
01957 c |= IDB_COLL_NAME_CHANGED;
01958 }
01959 int16_code(&temp, &offset, &alloc_size, &c);
01960 if (implModified) {
01961 _status = IndexImpl::code(temp, offset, alloc_size, collimpl->getIndexImpl(), collimpl->getType());
01962 if (_status) {
01963 return _status;
01964 }
01965 }
01966
01967 if (nameModified) {
01968 string_code(&temp, &offset, &alloc_size, name);
01969 }
01970
01971 hdr.type = type;
01972 hdr.size = alloc_size;
01973 hdr.xinfo = (!inverse_valid ? IDB_XINFO_INVALID_INV : 0);
01974
01975 object_header_code_head(temp, &hdr);
01976
01977 rpc_status = objectWrite(db->getDbHandle(), temp, getOidC().getOid());
01978 free(temp);
01979 if (!rpc_status) {
01980 delete cache;
01981 cache = 0;
01982 emptyReadCache();
01983 modify = False;
01984 implModified = False;
01985 nameModified = False;
01986 }
01987
01988 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
01989 }
01990
01991 #define IDB_MAGIC_COLL ((void *)0x2e372811)
01992 #define IDB_MAGIC_COLL2 ((void *)0xe3728113)
01993
01994 Status Collection::realize(const RecMode *rcm)
01995 {
01996 if (state & Realizing)
01997 return Success;
01998
01999 CHK_OBJ(this);
02000
02001 #ifdef COLLTRACE
02002 printf("realizing %p %s %d\n", this, getOidC().toString(),
02003 CACHE_LIST_COUNT(cache));
02004 #endif
02005
02006 #ifdef COLL_OPTIM_CREATE
02007 if (is_literal && !CACHE_LIST_COUNT(cache) && !implModified) {
02008
02009 return Success;
02010 }
02011 #endif
02012
02013 if (is_literal && !literal_oid.isValid() && getUserData() != IDB_MAGIC_COLL) {
02014 #ifdef COLLTRACE
02015 printf("collection realizing master_object %p\n",
02016 getMasterObject(true));
02017 #endif
02018 assert(getMasterObject(true));
02019 void *ud = setUserData(IDB_MAGIC_COLL2);
02020 Status s = getMasterObject(true)->realize(rcm);
02021 (void)setUserData(ud);
02022 return s;
02023 }
02024
02025 Status s;
02026 IDB_COLL_LOAD_DEFERRED();
02027 state |= Realizing;
02028
02029 if (!getOidC().isValid())
02030 s = create_realize(rcm);
02031 else if (modify || collupd_noopt)
02032 s = update_realize(rcm);
02033 else
02034 s = Success;
02035
02036 state &= ~Realizing;
02037 return s;
02038 }
02039
02040 Status Collection::remove(const RecMode *rcm)
02041 {
02042 Status s;
02043
02044 #ifdef COLLTRACE
02045 printf("removing collection %s\n", getOidC().toString());
02046 #endif
02047
02048 s = loadLiteral();
02049 if (s)
02050 return s;
02051
02052 if (is_literal)
02053 return Exception::make("collection %s is a literal object: could not be removed", getOid().toString());
02054
02055 s = Object::remove();
02056
02057 if (!s) {
02058 delete cache;
02059 cache = 0;
02060 p_items_cnt = v_items_cnt = 0;
02061 }
02062
02063 return s;
02064 }
02065
02066 Status Collection::trace(FILE* fd, unsigned int flags, const RecMode *rcm) const
02067 {
02068 fprintf(fd, "%s %s = ", oid.getString(), getClass()->getName());
02069 return trace_realize(fd, INDENT_INC, flags, rcm);
02070 }
02071
02072 Status Collection::trace_contents_realize(FILE* fd, int indent, unsigned int flags, const RecMode *rcm) const
02073 {
02074
02075 char *indent_str = make_indent(indent);
02076 ValueArray array;
02077 Bool isidx = (asCollArray() || asCollList()) ? True : False;
02078
02079 Status s = getElements(array, (isidx ? True : False));
02080
02081 if (s)
02082 return s;
02083
02084 int inc = (isidx ? 2 : 1);
02085 int value_off = (isidx ? 1 : 0);
02086 int ind;
02087
02088 unsigned int cnt = array.getCount();
02089 for (int i = 0; i < cnt; i += inc) {
02090 IDB_CHECK_INTR();
02091 Value value = array[i+value_off];
02092
02093 if (isidx)
02094 ind = array[i].l;
02095
02096 if (value.type == Value::tOid) {
02097 Object *o;
02098 s = db->loadObject(value.oid, &o, rcm);
02099 if (s) {
02100 delete_indent(indent_str);
02101 return s;
02102 }
02103
02104 if (isidx)
02105 fprintf(fd, "%s[%d] = %s %s ", indent_str, ind,
02106 value.oid->getString(), o->getClass()->getName());
02107 else
02108 fprintf(fd, "%s%s %s = ", indent_str, value.oid->getString(),
02109 o->getClass()->getName());
02110 s = ObjectPeer::trace_realize(o, fd, indent + INDENT_INC, flags, rcm);
02111 if (s) {
02112 delete_indent(indent_str);
02113 return s;
02114 }
02115
02116 o->release();
02117 }
02118 else if (isidx)
02119 fprintf(fd, "%s[%d] = %s;\n", indent_str, ind, value.getString());
02120 else
02121 fprintf(fd, "%s%s;\n", indent_str, value.getString());
02122 }
02123
02124 delete_indent(indent_str);
02125 return Success;
02126 }
02127
02128 Status Collection::trace_realize(FILE* fd, int indent, unsigned int flags, const RecMode *rcm) const
02129 {
02130 IDB_CHECK_INTR();
02131
02132
02133 Status s = Success;
02134 char *indent_str = make_indent(indent);
02135
02136 if (state & Tracing) {
02137 fprintf(fd, "%s%s;\n", indent_str, oid.getString());
02138 delete_indent(indent_str);
02139 return Success;
02140 }
02141
02142 if (!is_complete) {
02143 s = const_cast<Collection *>(this)->loadDeferred();
02144 if (s) return s;
02145 }
02146
02147 const_cast<Collection *>(this)->state |= Tracing;
02148
02149 char *lastindent_str = make_indent(indent - INDENT_INC);
02150
02151 fprintf(fd, "%s { ", getClassName());
02152 if (traceRemoved(fd, indent_str))
02153 goto out;
02154 trace_flags(fd, flags);
02155 fprintf(fd, "\n");
02156
02157 if ((flags & NativeTrace) == NativeTrace) {
02158 if (rcm->getType() == RecMode_FullRecurs) {
02159 fprintf(fd, "%s%s class = { ", indent_str,
02160 getClass()->getOid().getString());
02161
02162 if (s = ObjectPeer::trace_realize(getClass(), fd, indent + INDENT_INC, flags, rcm))
02163 goto out;
02164
02165 fprintf(fd, "%s};\n", indent_str);
02166
02167 fprintf(fd, "%s%s collclass = { ", indent_str,
02168 coll_class->getOid().getString());
02169
02170 if (s = ObjectPeer::trace_realize(coll_class, fd, indent + INDENT_INC, flags, rcm))
02171 goto out;
02172
02173 fprintf(fd, "%s};\n", indent_str);
02174 } else {
02175 fprintf(fd, "%sclass = %s;\n", indent_str,
02176 getClass()->getOid().getString());
02177
02178 fprintf(fd, "%scollclass = %s;\n", indent_str,
02179 coll_class->getOid().getString());
02180
02181 fprintf(fd, "%sreference = %s;\n", indent_str, (isref ? "true" : "false"));
02182 if (isPureLiteral())
02183 fprintf(fd, "%stype = pure_literal;\n", indent_str);
02184 else if (isLiteral())
02185 fprintf(fd, "%stype = object_literal;\n", indent_str);
02186 else
02187 fprintf(fd, "%stype = object;\n", indent_str);
02188
02189 if (isLiteral())
02190 fprintf(fd, "%sliteral_oid = %s;\n", indent_str, getOidC().toString());
02191
02192 if (collimpl->getType() == CollImpl::NoIndex) {
02193 fprintf(fd, "%sidxtype = 'noindex';\n", indent_str);
02194 }
02195 else if (collimpl->getType() == CollImpl::HashIndex) {
02196 fprintf(fd, "%sidxtype = 'hasindex';\n", indent_str);
02197 }
02198 else if (collimpl->getType() == CollImpl::BTreeIndex) {
02199 fprintf(fd, "%sidxtype = 'btreeindex';\n", indent_str);
02200 }
02201
02202 if (collimpl->getIndexImpl()) {
02203 std::string hints = collimpl->getIndexImpl()->getHintsString();
02204 if (hints.size())
02205 fprintf(fd, "%shints = \"%s\";\n", indent_str,
02206 hints.c_str());
02207 }
02208
02209 if (idx1_oid.isValid())
02210 fprintf(fd, "%sidx1oid = %s;\n", indent_str,
02211 idx1_oid.toString());
02212 if (idx2_oid.isValid())
02213 fprintf(fd, "%sidx2oid = %s;\n", indent_str,
02214 idx2_oid.toString());
02215 }
02216 }
02217
02218 fprintf(fd, "%sname = \"%s\";\n", indent_str, name);
02219 fprintf(fd, "%scount = %d;\n", indent_str, v_items_cnt);
02220
02221 if (asCollArray())
02222 fprintf(fd, "%srange = [%d,%d[;\n", indent_str, bottom, top);
02223
02224 if (card)
02225 fprintf(fd, "%sconstraint = (%s);\n", indent_str, card->getString());
02226
02227 if (flags & ContentsFlag) {
02228 fprintf(fd, "%scontents = {\n", indent_str);
02229 s = trace_contents_realize(fd, indent + INDENT_INC, flags, rcm);
02230 fprintf(fd, "%s};\n", indent_str);
02231 }
02232
02233 out:
02234 const_cast<Collection *>(this)->state &= ~Tracing;
02235 fprintf(fd, "%s};\n", lastindent_str);
02236 delete_indent(indent_str);
02237 delete_indent(lastindent_str);
02238
02239 return s;
02240 }
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260 Status Collection::getElements(OidArray &oid_array) const
02261 {
02262 if (status)
02263 return Exception::make(status);
02264
02265 Status s = const_cast<Collection *>(this)->getOidElementsRealize();
02266 if (s) return s;
02267
02268 oid_array = *read_cache.oid_arr;
02269 return Success;
02270 }
02271
02272 Status Collection::getOidElementsRealize()
02273 {
02274 if (!isref)
02275 return Exception::make(IDB_COLLECTION_ERROR,
02276 "cannot get oid elements");
02277
02278 IDB_COLL_LOAD_DEFERRED();
02279
02280 if (read_cache.oid_arr && read_cache_state_oid == coherent)
02281 return Success;
02282
02283 delete read_cache.oid_arr;
02284 read_cache.oid_arr = new OidArray();
02285 if (getOidC().isValid()) {
02286 Iterator q(this);
02287 if (q.getStatus())
02288 return q.getStatus();
02289
02290 Status s = q.scan(*read_cache.oid_arr);
02291 if (s || read_cache_state_oid == coherent) return s;
02292 }
02293 else if (read_cache_state_oid == coherent)
02294 return Success;
02295
02296 if (read_cache_state_oid == coherent) {
02297 assert(CACHE_LIST_COUNT(cache) == 0);
02298 return Success;
02299 }
02300
02301 ValueItem *item;
02302 OidList *oid_list = read_cache.oid_arr->toList();
02303
02304 if (cache) {
02305 ValueCache::IdMapIterator begin = cache->getIdMap().begin();
02306 ValueCache::IdMapIterator end = cache->getIdMap().end();
02307
02308 while (begin != end) {
02309 item = (*begin).second;
02310 const Value &v = item->getValue();
02311 if (v.type == Value::tOid) {
02312 Oid item_oid = *v.oid;
02313
02314 int s = item->getState();
02315
02316 #ifdef NEW_GET_ELEMENTS
02317 if (s == removed) {
02318 if (item_oid.isValid())
02319 oid_list->suppressOid(item_oid);
02320 }
02321 else if (s == added) {
02322 oid_list->insertOidLast(item_oid);
02323 }
02324 #else
02325 if (s == removed && item_oid.isValid())
02326 oid_list->suppressOid(item_oid);
02327 else if (s == added) {
02328 if (!item_oid.isValid() || !oid_list->exists(item_oid))
02329 oid_list->insertOidLast(item_oid);
02330 }
02331 #endif
02332 }
02333 ++begin;
02334 }
02335 }
02336
02337 delete read_cache.oid_arr;
02338 read_cache.oid_arr = oid_list->toArray();
02339 delete oid_list;
02340
02341 read_cache_state_oid = coherent;
02342 return Success;
02343 }
02344
02345 Status Collection::getElements(ObjectPtrVector &obj_vect,
02346 const RecMode *rcm) const
02347 {
02348 ObjectArray obj_array;
02349 Status s = getElements(obj_array, rcm);
02350 if (s)
02351 return s;
02352 obj_array.makeObjectPtrVector(obj_vect);
02353 return Success;
02354 }
02355
02356 Status Collection::getElements(ObjectArray &obj_array,
02357 const RecMode *rcm) const
02358 {
02359 if (status)
02360 return Exception::make(status);
02361
02362 #ifdef TRY_GETELEMS_GC
02363 if (obj_array.isAutoGarbage()) {
02364 return Exception::make(IDB_ERROR,
02365 "Collection::getElements(ObjectArray &): "
02366 "ObjectArray argument cannot be in auto-garbaged mode");
02367 }
02368 #endif
02369
02370 if (!isref && !coll_class->asBasicClass() &&
02371 !coll_class->asEnumClass()) {
02372 ValueArray val_arr;
02373 Status s = getElements(val_arr, False);
02374 if (s) return s;
02375 int count = val_arr.getCount();
02376 obj_array.set(0, count);
02377 for (int n = 0; n < count; n++) {
02378 if (val_arr[n].getType() == Value::tObject)
02379 obj_array.setObjectAt(n, val_arr[n].o);
02380 else if (val_arr[n].getType() == Value::tObjectPtr)
02381 obj_array.setObjectAt(n, val_arr[n].o_ptr->getObject());
02382 else
02383 return Exception::make(IDB_ERROR, "unexpected value type");
02384 }
02385 return Success;
02386 }
02387
02388 Status s = const_cast<Collection *>(this)->getObjElementsRealize(rcm);
02389 if (s) return s;
02390
02391 obj_array = *read_cache.obj_arr;
02392 return Success;
02393 }
02394
02395 Status Collection::getObjElementsRealize(const RecMode *rcm)
02396 {
02397 if (!isref) {
02398 return Exception::make(IDB_COLLECTION_ERROR,
02399 "cannot get object elements");
02400 }
02401
02402 IDB_COLL_LOAD_DEFERRED();
02403
02404 if (read_cache.obj_arr && read_cache_state_object == coherent)
02405 return Success;
02406
02407 #ifdef TRY_GETELEMS_GC
02408 assert(!read_cache.obj_arr || read_cache.obj_arr->isAutoGarbage());
02409 assert(!read_cache.val_arr || read_cache.val_arr->isAutoObjGarbage());
02410 #endif
02411 delete read_cache.obj_arr;
02412
02413
02414
02415
02416 #ifdef TRY_GETELEMS_GC
02417 read_cache.obj_arr = new ObjectArray(true);
02418 #else
02419 read_cache.obj_arr = new ObjectArray();
02420 #endif
02421
02422 if (getOidC().isValid()) {
02423 Iterator q(this);
02424 if (q.getStatus())
02425 return q.getStatus();
02426
02427 Status s = q.scan(*read_cache.obj_arr);
02428 if (s || read_cache_state_object == coherent)
02429 return s;
02430 }
02431 else if (read_cache_state_object == coherent)
02432 return Success;
02433
02434 if (read_cache_state_object == coherent) {
02435 assert(CACHE_LIST_COUNT(cache) == 0);
02436 return Success;
02437 }
02438
02439 ValueItem *item;
02440
02441 ObjectList *obj_list = read_cache.obj_arr->toList();
02442
02443 if (cache) {
02444 ValueCache::IdMapIterator begin = cache->getIdMap().begin();
02445 ValueCache::IdMapIterator end = cache->getIdMap().end();
02446
02447 while (begin != end) {
02448 item = (*begin).second;
02449 const Value &v = item->getValue();
02450 Object *item_o = 0;
02451 if (v.type == Value::tOid) {
02452 Oid item_oid = *v.oid;
02453 if (item_oid.isValid() && db) {
02454 Status s = db->loadObject(item_oid, item_o);
02455 if (s)
02456 return s;
02457 }
02458 }
02459 else if (v.type == Value::tObject)
02460 item_o = v.o;
02461 else if (v.type == Value::tObjectPtr)
02462 item_o = v.o_ptr->getObject();
02463
02464 if (!item_o)
02465 return Exception::make(IDB_INTERNAL_ERROR, "invalid null object "
02466 "found in Collection::getObjElementsRealize()");
02467
02468 int s = item->getState();
02469
02470 if (s == removed)
02471 obj_list->suppressObject(item_o);
02472 else if (s == added) {
02473 obj_list->insertObjectLast(item_o);
02474 item_o->incrRefCount();
02475 }
02476
02477 ++begin;
02478 }
02479 }
02480
02481 #ifdef TRY_GETELEMS_GC
02482 assert(!read_cache.obj_arr || read_cache.obj_arr->isAutoGarbage());
02483 assert(!read_cache.val_arr || read_cache.val_arr->isAutoObjGarbage());
02484 #endif
02485 delete read_cache.obj_arr;
02486
02487 read_cache.obj_arr = obj_list->toArray();
02488 #ifdef TRY_GETELEMS_GC
02489 read_cache.obj_arr->setAutoGarbage(true);
02490 read_cache.obj_arr->setMustRelease(false);
02491 #endif
02492
02493 delete obj_list;
02494
02495 read_cache_state_object = coherent;
02496 return Success;
02497 }
02498
02499
02500 void Collection::emptyReadCache()
02501 {
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511 #ifdef TRY_GETELEMS_GC
02512 assert(!read_cache.obj_arr || read_cache.obj_arr->isAutoGarbage());
02513 assert(!read_cache.val_arr || read_cache.val_arr->isAutoObjGarbage());
02514 #endif
02515 delete read_cache.obj_arr;
02516
02517 delete read_cache.oid_arr;
02518 delete read_cache.val_arr;
02519 read_cache.obj_arr = 0;
02520 read_cache.oid_arr = 0;
02521 read_cache.val_arr = 0;
02522 unvalidReadCache();
02523 }
02524
02525 #define CONVERT(VALUE_ARRAY, TYPE, OFF) \
02526 do { \
02527 for (int i = (OFF); i < (VALUE_ARRAY)->value_cnt; i += (OFF)+1) \
02528 { \
02529 Value v = (VALUE_ARRAY)->values[i]; \
02530 TYPE k; \
02531 memcpy(&k, v.data, sizeof(TYPE)); \
02532 (VALUE_ARRAY)->values[i].set(k); \
02533 } \
02534 } while(0)
02535
02536 static int
02537 value_index_cmp (const void *x1, const void *x2)
02538 {
02539 Value *v1 = (Value *)x1;
02540 Value *v2 = (Value *)x2;
02541 return v1->i - v2->i;
02542 }
02543
02544 static void sortValues(ValueArray &value_array)
02545 {
02546 qsort(value_array.getValues(), value_array.getCount()/2, 2*sizeof(Value),
02547 value_index_cmp);
02548 }
02549
02550 Status Collection::getElements(ValueArray &value_array, Bool index) const
02551 {
02552 if (status)
02553 return Exception::make(status);
02554
02555 #ifdef TRY_GETELEMS_GC
02556 if (value_array.isAutoObjGarbage()) {
02557 return Exception::make(IDB_ERROR,
02558 "Collection::getElements(ValueArray &): "
02559 "ValueArray argument cannot be in auto-object-garbaged mode");
02560 }
02561 #endif
02562
02563 Status s = const_cast<Collection *>(this)->getValElementsRealize(index);
02564 if (s) return s;
02565
02566 value_array = *read_cache.val_arr;
02567 return Success;
02568 }
02569
02570 Status
02571 Collection::getValElementsRealize(Bool index)
02572 {
02573 IDB_COLL_LOAD_DEFERRED();
02574
02575 if (read_cache.val_arr &&
02576 read_cache_state_value == coherent &&
02577 read_cache_state_index == index)
02578 return Success;
02579
02580 delete read_cache.val_arr;
02581 #ifdef TRY_GETELEMS_GC
02582 read_cache.val_arr = new ValueArray(true);
02583 #else
02584 read_cache.val_arr = new ValueArray();
02585 #endif
02586
02587 if (getOidC().isValid()) {
02588 Iterator q(this, index);
02589 if (q.getStatus())
02590 return q.getStatus();
02591
02592 Status s = q.scan(*read_cache.val_arr);
02593
02594 if (s) return s;
02595 }
02596
02597 if (read_cache_state_value == coherent &&
02598 read_cache_state_index == index) {
02599 assert(CACHE_LIST_COUNT(cache) == 0);
02600
02601
02602
02603
02604
02605
02606 return Success;
02607 }
02608
02609 if (read_cache_state_value != coherent ||
02610 read_cache_state_index != index) {
02611 ValueItem *item;
02612 ValueList *value_list = read_cache.val_arr->toList();
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626 if (cache) {
02627 ValueCache::IdMapIterator begin = cache->getIdMap().begin();
02628 ValueCache::IdMapIterator end = cache->getIdMap().end();
02629
02630 while (begin != end) {
02631 item = (*begin).second;
02632 const Value &item_value = item->getValue();
02633
02634 int s = item->getState();
02635 if (s == removed) {
02636
02637
02638
02639
02640
02641 if (index)
02642 value_list->suppressPairValues(Value((int)(*begin).first),
02643 item_value);
02644 else
02645 value_list->suppressValue(item_value);
02646 }
02647 else if (s == added) {
02648 if (item_value.type == Value::tObject)
02649 item_value.o->incrRefCount();
02650 if (index)
02651 value_list->insertValueLast(Value((int)(*begin).first));
02652 value_list->insertValueLast(item_value);
02653 }
02654 ++begin;
02655 }
02656 }
02657
02658 delete read_cache.val_arr;
02659 read_cache.val_arr = value_list->toArray();
02660 #ifdef TRY_GETELEMS_GC
02661 read_cache.val_arr->setAutoObjGarbage(true);
02662 read_cache.val_arr->setMustRelease(false);
02663 #endif
02664 delete value_list;
02665
02666 read_cache_state_value = coherent;
02667 read_cache_state_index = index;
02668 }
02669
02670 if (index && (asCollArray() || asCollList()))
02671 sortValues(*read_cache.val_arr);
02672
02673 int idx = (index ? 1 : 0);
02674
02675 if (isref) {
02676
02677
02678
02679
02680
02681 return Success;
02682 }
02683
02684
02685
02686
02687
02688
02689 unsigned int value_cnt = read_cache.val_arr->getCount();
02690 for (int i = idx; i < value_cnt; i += idx+1) {
02691 makeValue(const_cast<Value&>((*read_cache.val_arr)[i]));
02692
02693
02694
02695
02696 }
02697
02698
02699 return Success;
02700 }
02701
02702 void Collection::makeValue(Value &v) {
02703 if (v.type == Value::tData &&
02704 !isref && !coll_class->asBasicClass() && !coll_class->asEnumClass()) {
02705 Database::consapp_t consapp = getDatabase()->getConsApp(coll_class);
02706 Object *o;
02707 if (consapp) {
02708 o = consapp(coll_class, 0);
02709 memcpy(o->getIDR() + IDB_OBJ_HEAD_SIZE, v.data.data, item_size);
02710 }
02711 else
02712 o = coll_class->newObj(v.data.data, True);
02713
02714 o->setDatabase(getDatabase());
02715 v.set(o);
02716 }
02717 }
02718
02719 Status Collection::failedCardinality() const
02720 {
02721 return Exception::make(IDB_CARDINALITY_CONSTRAINT_ERROR,
02722 "items count %d does not respect constraint '%s'",
02723 v_items_cnt, card->getString());
02724 }
02725
02726 Status Collection::checkCardinality() const
02727 {
02728 #ifdef CARD_TRACE
02729 printf("Collection::checkCardinality()\n");
02730 #endif
02731 if (status != Success)
02732 return Exception::make(IDB_COLLECTION_ERROR,
02733 "invalid collection status: \"%s\"",
02734 status->getDesc());
02735
02736 if (!card)
02737 return Success;
02738
02739 if (card_bottom_excl && (v_items_cnt <= card_bottom))
02740 return failedCardinality();
02741
02742 if (!card_bottom_excl && (v_items_cnt < card_bottom))
02743 return failedCardinality();
02744
02745 if (card_top == CardinalityConstraint::maxint)
02746 return Success;
02747
02748 if (card_top_excl && (v_items_cnt >= card_top))
02749 return failedCardinality();
02750
02751 if (!card_top_excl && (v_items_cnt > card_top))
02752 return failedCardinality();
02753
02754 return Success;
02755 }
02756
02757 Status Collection::realizeCardinality()
02758 {
02759 printf("Collection::realizeCardinality(%p)\n", card);
02760 if (!card)
02761 return Success;
02762
02763 if (status != Success)
02764 return Exception::make(IDB_COLLECTION_ERROR,
02765 "invalid collection status: \"%s\"",
02766 status->getDesc());
02767
02768 if (!getOidC().isValid())
02769 return Exception::make(IDB_COLLECTION_ERROR, "collection oid '%s' is not valid", name);
02770
02771 IDB_CHECK_WRITE(db);
02772
02773 Data temp = 0;
02774 Offset offset = IDB_OBJ_HEAD_SIZE;
02775 Size alloc_size = 0;
02776
02777 cardCode(temp, offset, alloc_size);
02778
02779 ObjectHeader hdr;
02780 memset(&hdr, 0, sizeof(hdr));
02781
02782 hdr.type = type;
02783 hdr.size = alloc_size;
02784 hdr.xinfo = IDB_XINFO_CARD;
02785
02786 offset = 0;
02787
02788 object_header_code(&temp, &offset, &alloc_size, &hdr);
02789
02790 RPCStatus rpc_status;
02791
02792 rpc_status = objectWrite(db->getDbHandle(), temp, getOidC().getOid());
02793
02794 free(temp);
02795
02796 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
02797 }
02798
02799 Status Collection::cache_compile(Offset &offset,
02800 Size &alloc_size,
02801 unsigned char **ptemp,
02802 const RecMode *rcm)
02803 {
02804 Status _status;
02805
02806 if (_status = checkCardinality())
02807 return _status;
02808
02809 unsigned int count = CACHE_LIST_COUNT(cache);
02810
02811 alloc_size = IDB_OBJ_HEAD_SIZE + 2 * sizeof(eyedblib::int32) +
02812 (count * (item_size + sizeof(eyedblib::int32) + sizeof(char)));
02813
02814
02815
02816
02817 offset = IDB_OBJ_HEAD_SIZE;
02818
02819 unsigned char *temp = (unsigned char *)malloc(alloc_size);
02820
02821
02822 int32_code (&temp, &offset, &alloc_size, &v_items_cnt);
02823
02824 int skip_cnt = 0;
02825 Offset list_cnt_offset = offset;
02826 eyedblib::int32 kh = count;
02827 int32_code (&temp, &offset, &alloc_size, &kh);
02828
02829 ValueItem *item;
02830
02831 if (cache) {
02832 ValueCache::IdMapIterator begin = cache->getIdMap().begin();
02833 ValueCache::IdMapIterator end = cache->getIdMap().end();
02834
02835 begin = cache->getIdMap().begin();
02836 end = cache->getIdMap().end();
02837
02838 while (begin != end) {
02839 item = (*begin).second;
02840 const Value &v = item->getValue();
02841
02842 if (isref) {
02843 Oid _oid;
02844 Object *_o = 0;
02845
02846 if (v.type == Value::tObject)
02847 _o = v.o;
02848 else if (v.type == Value::tObjectPtr)
02849 _o = v.o_ptr->getObject();
02850
02851 if (_o) {
02852 if (item->getState() == added &&
02853 rcm->getType() == RecMode_FullRecurs) {
02854 Status _status = _o->realize(rcm);
02855 if (_status) {
02856 free(temp);
02857 return _status;
02858 }
02859 }
02860 _oid = _o->getOid();
02861 }
02862 else
02863 _oid = *v.oid;
02864
02865 if (!_oid.isValid() && item->getState() == removed) {
02866 skip_cnt++;
02867 ++begin;
02868 continue;
02869 }
02870
02871 if (!_oid.isValid() && item->getState() == added)
02872 return Exception::make(IDB_COLLECTION_ERROR,
02873 "cannot insert a null oid into "
02874 "a collection: must store first "
02875 "collection elements");
02876
02877 oid_code(&temp, &offset, &alloc_size, _oid.getOid());
02878 }
02879 else {
02880 buffer_code (&temp, &offset, &alloc_size, v.getData(),
02881 item_size);
02882
02883 }
02884
02885
02886 Collection::ItemId id = item->getId();
02887 int32_code (&temp, &offset, &alloc_size, (int*)&id);
02888 char kc = (char)item->getState();
02889 char_code (&temp, &offset, &alloc_size, &kc);
02890 ++begin;
02891 }
02892 }
02893
02894 if (skip_cnt) {
02895 kh -= skip_cnt;
02896 int32_code (&temp, &list_cnt_offset, &alloc_size, &kh);
02897 }
02898
02899 *ptemp = temp;
02900
02901 return Success;
02902 }
02903
02904 Status collectionMake(Database *db, const Oid *oid, Object **o,
02905 const RecMode *rcm, const ObjectHeader *hdr,
02906 Data idr, LockMode lockmode, const Class *_class)
02907 {
02908 RPCStatus rpc_status;
02909 Data temp;
02910 Oid _oid(hdr->oid_cl);
02911
02912 if (_oid.isValid()) {
02913 Oid xoid(hdr->oid_cl);
02914 if (!_class)
02915 _class = db->getSchema()->getClass(hdr->oid_cl, True);
02916 if (!_class)
02917 return Exception::make(IDB_CLASS_NOT_FOUND, "collection class '%s'",
02918 OidGetString(&hdr->oid_cl));
02919 }
02920 else
02921 _class = 0;
02922
02923 if (!idr) {
02924 temp = (unsigned char *)malloc(hdr->size);
02925 object_header_code_head(temp, hdr);
02926
02927 rpc_status = objectRead(db->getDbHandle(), temp, 0, 0, oid->getOid(),
02928 0, lockmode, 0);
02929 } else {
02930 temp = idr;
02931 rpc_status = RPCSuccess;
02932 }
02933
02934 if (rpc_status != RPCSuccess)
02935 return StatusMake(rpc_status);
02936
02937 char locked;
02938 Object *card;
02939 int items_cnt, bottom, top;
02940 char *name;
02941 Oid idx1_oid, idx2_oid;
02942 Oid inv_oid;
02943 eyedblib::int16 inv_item = 0;
02944 Bool is_literal = False;
02945 Bool is_pure_literal = False;
02946 Data idx_data = 0;
02947 Size idx_data_size = 0;
02948 IndexImpl *idximpl = 0;
02949 int impl_type = 0;
02950 CollImpl *collimpl = 0;
02951
02952 if (ObjectPeer::isRemoved(*hdr)) {
02953 locked = 0;
02954 card = NULL;
02955 collimpl = 0;
02956 items_cnt = bottom = top = 0;
02957 name = "";
02958 } else {
02959 Offset offset = IDB_OBJ_HEAD_SIZE;
02960
02961 char_decode (temp, &offset, &locked);
02962
02963
02964 eyedblib::int16 kk;
02965 int16_decode (temp, &offset, &kk);
02966
02967 Status s = IndexImpl::decode(db, temp, offset, idximpl, &impl_type);
02968 if (s) return s;
02969
02970 if (idximpl) {
02971 collimpl = new CollImpl(idximpl);
02972 }
02973 else {
02974 collimpl = new CollImpl((CollImpl::Type)impl_type);
02975 }
02976
02977 oid_decode (temp, &offset, idx1_oid.getOid());
02978 oid_decode (temp, &offset, idx2_oid.getOid());
02979 int32_decode (temp, &offset, &items_cnt);
02980 int32_decode (temp, &offset, &bottom);
02981 int32_decode (temp, &offset, &top);
02982
02983 card = Collection::cardDecode(db, temp, offset);
02984
02985 eyedbsm::Oid se_inv_oid;
02986 oid_decode(temp, &offset, &se_inv_oid);
02987 inv_oid.setOid(se_inv_oid);
02988 int16_decode(temp, &offset, &inv_item);
02989
02990 char c;
02991
02992 LITERAL_OFFSET = offset;
02993 char_decode (temp, &offset, &c);
02994 Collection::decodeLiteral(c, is_literal, is_pure_literal);
02995
02996
02997
02998 eyedblib::int16 sz;
02999 int16_decode (temp, &offset, &sz);
03000 idx_data_size = sz;
03001 idx_data = temp+offset;
03002 offset += idx_data_size;
03003
03004 string_decode(temp, &offset, &name);
03005 }
03006
03007 #ifdef COLLTRACE
03008 printf("collection make idx_data_size=%d\n", idx_data_size);
03009 #endif
03010 if (eyedb_is_type(*hdr, _CollSet_Type))
03011 *o = (Object *)CollectionPeer::collSet
03012 (name, (Class *)_class, idx1_oid, idx2_oid, items_cnt,
03013 bottom, top, collimpl, card, is_literal, is_pure_literal, idx_data, idx_data_size);
03014
03015 else if (eyedb_is_type(*hdr, _CollBag_Type))
03016 *o = (Object *)CollectionPeer::collBag
03017 (name, (Class *)_class, idx1_oid, idx2_oid, items_cnt,
03018 bottom, top, collimpl, card, is_literal, is_pure_literal, idx_data, idx_data_size);
03019
03020 else if (eyedb_is_type(*hdr, _CollList_Type))
03021 *o = (Object *)CollectionPeer::collList
03022 (name, (Class *)_class, idx1_oid, idx2_oid, items_cnt,
03023 bottom, top, collimpl, card, is_literal, is_pure_literal, idx_data, idx_data_size);
03024
03025 else if (eyedb_is_type(*hdr, _CollArray_Type))
03026 *o = (Object *)CollectionPeer::collArray
03027 (name, (Class *)_class, idx1_oid, idx2_oid, items_cnt,
03028 bottom, top, collimpl, card, is_literal, is_pure_literal, idx_data, idx_data_size);
03029 else {
03030 if (collimpl)
03031 collimpl->release();
03032 return Exception::make(IDB_INTERNAL_ERROR, "invalid collection type: "
03033 "%p", hdr->type);
03034 }
03035
03036
03037 if (collimpl)
03038 collimpl->release();
03039 CollectionPeer::setLock((Collection *)*o, (Bool)locked);
03040
03041 if (is_literal)
03042 (*o)->asCollection()->setLiteralOid(*oid);
03043
03044 if (inv_oid.isValid())
03045 CollectionPeer::setInvOid((Collection *)*o, inv_oid, inv_item);
03046
03047 if (!idr)
03048 free(temp);
03049
03050 return Success;
03051 }
03052
03053 Status Collection::getImplementation(CollImpl *&_collimpl, Bool remote) const
03054 {
03055 if (!remote) {
03056 if (is_literal) {
03057 Status s = const_cast<Collection *>(this)->loadDeferred();
03058 if (s) return s;
03059 }
03060 _collimpl = collimpl->clone();
03061 return Success;
03062 }
03063
03064 _collimpl = 0;
03065
03066 Oid idx1oid, idx2oid;
03067 Status s = getIdxOid(idx1oid, idx2oid);
03068 if (s) return s;
03069
03070 if (idx1oid.isValid()) {
03071
03072 IndexImpl *idximpl = 0;
03073 RPCStatus rpc_status =
03074 collectionGetImplementation(db->getDbHandle(),
03075 collimpl->getType(),
03076 idx1oid.getOid(), (Data *)&idximpl);
03077 if (rpc_status)
03078 return StatusMake(rpc_status);
03079
03080 if (collimpl->getIndexImpl()) {
03081 idximpl->setHashMethod(collimpl->getIndexImpl()->getHashMethod());
03082 }
03083 if (idximpl) {
03084 _collimpl = new CollImpl(idximpl);
03085 }
03086 else {
03087 _collimpl = new CollImpl(collimpl->getType());
03088 }
03089 }
03090
03091 return Success;
03092 }
03093
03094 Status
03095 Collection::literalMake(Collection *o)
03096 {
03097 #if 1
03098 is_literal = o->isLiteral();
03099 is_pure_literal = o->isPureLiteral();
03100 #endif
03101
03102 assert(literal_oid == o->getOid());
03103 oid.invalidate();
03104 literal_oid = o->getOid();
03105
03106 #if 0
03107
03108 Status s = loadLiteral();
03109 if (s)
03110 return s;
03111
03112
03113 if (o->isLiteral() != isLiteral() || o->isPureLiteral() != isPureLiteral())
03114 printf("---------------------------- ARGH -----------------------\n");
03115 #endif
03116
03117 #ifdef COLLTRACE
03118 printf("literalMake:: literal oid is %s\n", literal_oid.toString());
03119 #endif
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133 bottom = o->bottom;
03134 top = o->top;
03135 locked = o->locked;
03136 inv_oid = o->inv_oid;
03137 inv_item = o->inv_item;
03138
03139 card = (CardinalityDescription *)CLONE(o->card);
03140 card_bottom = o->card_bottom;
03141 card_bottom_excl = o->card_bottom_excl;
03142 card_top = o->card_top;
03143 card_top_excl = o->card_top_excl;
03144 card_oid = o->card_oid;
03145
03146 if (db && db->isBackEnd()) {
03147 idx1_oid = o->idx1_oid;
03148 idx2_oid = o->idx2_oid;
03149 idx1 = o->idx1;
03150 idx2 = o->idx2;
03151 }
03152
03153
03154 delete cache;
03155
03156 cache = o->cache;
03157 if (cache)
03158 cache->setObject(this);
03159
03160 o->cache = 0;
03161 p_items_cnt = o->p_items_cnt;
03162 v_items_cnt = o->v_items_cnt;
03163 inverse_valid = o->inverse_valid;
03164 if (!implModified) {
03165 if (collimpl)
03166 collimpl->release();
03167 if (o->collimpl) {
03168 collimpl = o->collimpl->clone();
03169 }
03170 }
03171
03172
03173
03174
03175 return Success;
03176 }
03177
03178
03179
03180
03181
03182
03183 Status Collection::realizePerform(const Oid& cloid,
03184 const Oid& objoid,
03185 AttrIdxContext &idx_ctx,
03186 const RecMode *rcm)
03187 {
03188 assert(is_literal);
03189
03190 CHK_OBJ(this);
03191
03192 #ifdef COLLTRACE
03193 printf("Collection::realizePerform(%p)\n", this);
03194
03195 Object *master_obj = getMasterObject(true);
03196 printf("master_object %p\n", master_obj);
03197 if (master_obj)
03198 printf("MASTER_OBJECT %s %s [%s]\n",
03199 master_obj->getOid().toString(),
03200 master_obj->getClass()->getName(), idx_ctx.getString().c_str());
03201 #endif
03202 if (!idx_data)
03203 idx_data = idx_ctx.code(idx_data_size);
03204
03205 void *ud = setUserData(IDB_MAGIC_COLL);
03206 Status s = realize(rcm);
03207 (void)setUserData(ud);
03208 if (s)
03209 return s;
03210
03211 #ifdef COLLTRACE
03212 printf("Collection::realizePerform(-> %s, %p)\n", literal_oid.toString(),
03213 idx_data);
03214 #endif
03215
03216 Offset offset = IDB_OBJ_HEAD_SIZE;
03217 Size alloc_size = idr->getSize();
03218 Data data = idr->getIDR();
03219
03220 #if 0
03221 eyedbsm::Oid hoid;
03222 oid_decode(data, &offset, &hoid);
03223 printf("before coding %s on %p\n", Oid(hoid).toString(), data);
03224 offset = IDB_OBJ_HEAD_SIZE;
03225 printf("coding %s on %p\n", literal_oid.toString(), data);
03226 #endif
03227
03228 oid_code(&data, &offset, &alloc_size, literal_oid.getOid());
03229
03230 return Success;
03231 }
03232
03233 Status Collection::loadPerform(const Oid&, LockMode lockmode,
03234 AttrIdxContext &idx_ctx,
03235 const RecMode *rcm)
03236 {
03237 Offset offset = IDB_OBJ_HEAD_SIZE;
03238 oid_decode(idr->getIDR(), &offset, literal_oid.getOid());
03239
03240 #ifdef COLLTRACE
03241 Object *master_obj = getMasterObject(true);
03242 printf("master_object %p %s %s [%s]\n",
03243 master_obj, master_object->getOid().toString(),
03244 master_obj->getClass()->getName(),
03245 (const char *)idx_ctx.getString());
03246
03247 printf("Collection::loadPerform(%p, %s)\n", this, literal_oid.toString());
03248 #endif
03249
03250 if (!idx_data)
03251 idx_data = idx_ctx.code(idx_data_size);
03252
03253
03254 if (literal_oid.isValid())
03255 is_complete = False;
03256
03257 if (rcm == RecMode::NoRecurs) {
03258
03259
03260
03261
03262
03263 return Success;
03264 }
03265
03266 return Collection::loadDeferred(lockmode, rcm);
03267 }
03268
03269 Status
03270 Collection::loadDeferred(LockMode lockmode, const RecMode *rcm)
03271 {
03272 if (is_complete)
03273 return Success;
03274
03275 Collection *o;
03276 #ifdef COLLTRACE
03277 printf("loading deferred %p %s\n", this, literal_oid.toString());
03278 #endif
03279
03280 #ifdef COLL_OPTIM_LOAD
03281 if (!literal_oid.isValid())
03282 return Success;
03283 #endif
03284
03285 #if 1
03286 Status s = db->loadObject_realize(&literal_oid, (Object **)&o,
03287 lockmode, rcm);
03288 if (s)
03289 return s;
03290 #else
03291 Status s = db->loadObject(literal_oid, (Object *&)o, rcm);
03292 if (s)
03293 return s;
03294 #endif
03295
03296 s = literalMake(o);
03297 if (s)
03298 return s;
03299
03300
03301
03302
03303
03304 o->release();
03305 is_complete = True;
03306 return Success;
03307 }
03308
03309 Status Collection::removePerform(const Oid& cloid,
03310 const Oid& objoid,
03311 AttrIdxContext &idx_ctx,
03312 const RecMode *rcm)
03313 {
03314 #ifdef COLLTRACE
03315 printf("Collection::removePerform(%p, %s) should remove only if pure_literal %d %d\n", this,
03316 literal_oid.toString(), is_literal, is_pure_literal);
03317 #endif
03318
03319 #ifdef COLLTRACE
03320 printf("trying to remove literal collection %s [%s]\n",
03321 literal_oid.toString(),
03322 getMasterObject(true) ? getMasterObject(true)->getOid().toString() : "<no master>");
03323 #endif
03324
03325 Status s = loadLiteral();
03326 if (s)
03327 return s;
03328 assert(is_literal);
03329
03330 #ifdef COLL_OPTIM_CREATE
03331 if (!literal_oid.isValid())
03332 return Success;
03333 #endif
03334 Bool was_pure_literal = is_pure_literal;
03335
03336 is_literal = False;
03337 is_pure_literal = False;
03338
03339 s = updateLiteral();
03340 if (s)
03341 return s;
03342
03343 if (was_pure_literal) {
03344 s = db->removeObject(literal_oid, rcm);
03345 if (s)
03346 return s;
03347 }
03348
03349 literal_oid.invalidate();
03350 return Success;
03351 }
03352
03353 Status Collection::postRealizePerform(const Oid& cloid,
03354 const Oid& objoid,
03355 AttrIdxContext &idx_ctx,
03356 Bool &mustTouch,
03357 const RecMode *rcm)
03358 {
03359 mustTouch = False;
03360 if (!getOidC().isValid())
03361 return Success;
03362
03363
03364
03365
03366 #if 0
03367 #ifdef E_XDR
03368 eyedbsm::Oid xoid;
03369 eyedbsm::h2x_oid(&xoid, getOidC().getOid());
03370 #else
03371 memcpy(&xoid, getOidC().getOid());
03372 #endif
03373
03374
03375
03376 Oid dataoid = idx_ctx.getDataOid();
03377 if (!dataoid.isValid()) {
03378 dataoid = objoid;
03379 }
03380
03381 #if 1
03382 if (getenv("EYEDB_XX"))
03383 printf("not writing %s in %s [%s] at %d\n",
03384 getOidC().toString(),
03385 dataoid.toString(),
03386 objoid.toString(),
03387 idx_ctx.getOff());
03388 else if (getenv("EYEDB_ZZ"))
03389 printf("setting to NULL in %s [%s] at %d\n",
03390 dataoid.toString(),
03391 objoid.toString(),
03392 idx_ctx.getOff());
03393 else
03394 printf("writing %s in %s [%s] at %d\n",
03395 getOidC().toString(),
03396 dataoid.toString(),
03397 objoid.toString(),
03398 idx_ctx.getOff());
03399 #endif
03400
03401 if (getenv("EYEDB_YY")) {
03402 RPCStatus rpc_status =
03403 dataWrite(db->getDbHandle(), idx_ctx.getOff() ,
03404 sizeof(eyedbsm::Oid),
03405 (Data)Oid::nullOid.getOid(),
03406 dataoid.getOid());
03407
03408 if (rpc_status)
03409 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
03410 }
03411
03412 else if (!getenv("EYEDB_XX")) {
03413 RPCStatus rpc_status =
03414 dataWrite(db->getDbHandle(), idx_ctx.getOff() ,
03415 sizeof(eyedbsm::Oid),
03416 (Data)&xoid,
03417 dataoid.getOid());
03418
03419 if (rpc_status)
03420 return StatusMake(IDB_COLLECTION_ERROR, rpc_status);
03421 }
03422 #endif
03423
03424 Status s;
03425 #ifdef COLLTRACE
03426 printf("postRealizePerform(%p, idx_data = %p)\n", getUserData(), idx_data);
03427 #endif
03428
03429 if (getUserData() != IDB_MAGIC_COLL2) {
03430
03431
03432
03433
03434
03435 s = realizePerform(cloid, objoid, idx_ctx, rcm);
03436
03437 }
03438 else {
03439 #ifdef COLLTRACE
03440 printf("warning magic coll for collection %p\n", this);
03441 #endif
03442 s = realizePerform(cloid, objoid, idx_ctx, rcm);
03443 }
03444
03445 return s;
03446 }
03447
03448 Status Collection::moveElements(const Dataspace *dataspace)
03449 {
03450 OidArray oid_arr;
03451 Status s = getElements(oid_arr);
03452 if (s)
03453 return s;
03454
03455 return db->moveObjects(oid_arr, dataspace);
03456 }
03457
03458 Status Collection::getElementLocations(ObjectLocationArray &locarr)
03459 {
03460 OidArray oid_arr;
03461 Status s = getElements(oid_arr);
03462 if (s)
03463 return s;
03464
03465 return db->getObjectLocations(oid_arr, locarr);
03466 }
03467
03468 Status Collection::getDefaultDataspace(const Dataspace *&dataspace) const
03469 {
03470 RPCStatus rpc_status;
03471 if (idx1_oid.isValid()) {
03472 int dspid;
03473 rpc_status = getDefaultIndexDataspace(db->getDbHandle(),
03474 idx1_oid.getOid(),
03475 1, &dspid);
03476
03477 if (rpc_status) return StatusMake(rpc_status);
03478 return db->getDataspace(dspid, dataspace);
03479 }
03480
03481 dataspace = 0;
03482 return Success;
03483 }
03484
03485 Status Collection::setDefaultDataspace(const Dataspace *dataspace)
03486 {
03487 RPCStatus rpc_status;
03488 if (idx1_oid.isValid()) {
03489 rpc_status = setDefaultIndexDataspace(db->getDbHandle(),
03490 idx1_oid.getOid(),
03491 1, dataspace->getId());
03492
03493 if (rpc_status) return StatusMake(rpc_status);
03494 }
03495
03496 if (idx2_oid.isValid()) {
03497 rpc_status = setDefaultIndexDataspace(db->getDbHandle(),
03498 idx2_oid.getOid(),
03499 1, dataspace->getId());
03500
03501 if (rpc_status) return StatusMake(rpc_status);
03502 }
03503
03504 return Success;
03505 }
03506
03507 Bool Collection::isPartiallyStored() const
03508 {
03509 return (cache != 0 && cache->size() > 0) ? True : False;
03510 }
03511
03512 CollImpl *CollImpl::clone() const
03513 {
03514 if (idximpl) {
03515 return new CollImpl(idximpl->clone());
03516 }
03517
03518 return new CollImpl(impl_type);
03519 }
03520 }