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