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
00027
00028
00029
00030
00031
00032
00033 #include "eyedb_p.h"
00034 #include "api_lib.h"
00035 #include <assert.h>
00036 #include "Attribute_p.h"
00037 #include "eyedblib/butils.h"
00038
00039
00040
00041 namespace eyedbsm {
00042 extern Boolean backend;
00043 }
00044 namespace eyedb {
00045
00046 #define TRY_GETELEMS_GC
00047
00048
00049
00050
00051
00052 Status
00053 Iterator::initDatabase(Database *db)
00054 {
00055 assert(0);
00056 return 0;
00057 }
00058
00059 void Iterator::init(Database *_db)
00060 {
00061 curatom = 0;
00062 readatom = 0;
00063 buff_len = 64;
00064 _count = 0;
00065 schinfo = 0;
00066 #ifdef IDB_VECT
00067 buffatom = idbNewVect(IteratorAtom, buff_len);
00068 #else
00069 assert(0);
00070 buffatom = new IteratorAtom[buff_len];
00071 #endif
00072 memset(buffatom, 0, sizeof(IteratorAtom) * buff_len);
00073
00074 state = True;
00075 db = _db;
00076 curqid = 0;
00077 nqids = 1;
00078
00079 qid = (int *)calloc(1, sizeof(int));
00080 *qid = 0;
00081 }
00082
00083 Iterator::Iterator(Class *cls, Bool subclass)
00084 {
00085 init(cls->getDatabase());
00086
00087 if (db)
00088 {
00089 Collection *extent;
00090 if (subclass)
00091 {
00092 #define SUBCLASS_OPTIM
00093 #ifdef SUBCLASS_OPTIM
00094 Class **subclasses;
00095 unsigned int subclass_count;
00096
00097 if (status = cls->getSubClasses(subclasses, subclass_count))
00098 return;
00099
00100 free(qid);
00101 qid = (int *)calloc(subclass_count, sizeof(int));
00102 nqids = 0;
00103
00104 for (int i = 0; i < subclass_count; i++)
00105 {
00106
00107 if (status = subclasses[i]->getExtent(extent, True))
00108 break;
00109
00110
00111 if (extent && extent->getCount())
00112 {
00113 status = StatusMake
00114 (queryCollectionCreate(db->getDbHandle(),
00115 extent->getOid().getOid(), False, &qid[nqids++]));
00116 if (status)
00117 break;
00118 }
00119 }
00120 #else
00121 const LinkedList *_class = db->getSchema()->getClassList();
00122 free(qid);
00123 qid = (int *)calloc(_class->getCount(), sizeof(int));
00124 nqids = 0;
00125
00126 Class *cl;
00127 LinkedListCursor c(_class);
00128
00129 while (c.getNext((void *&)cl))
00130 {
00131 Bool is;
00132 if (status = cls->isSuperClassOf(cl, &is))
00133 break;
00134
00135 if (is)
00136 {
00137 if (status = cl->getExtent(extent))
00138 break;
00139
00140 if (extent)
00141 {
00142 status = StatusMake
00143 (queryCollectionCreate(db->getDbHandle(),
00144 extent->getOid().getOid(), False, &qid[nqids++]));
00145 if (status)
00146 break;
00147 }
00148 }
00149 }
00150 #endif
00151 }
00152 else
00153 {
00154 if (status = cls->getExtent(extent))
00155 return;
00156 if (extent)
00157 status = StatusMake
00158 (queryCollectionCreate(db->getDbHandle(),
00159 extent->getOid().getOid(), False, &qid[0]));
00160 else
00161 status = Success;
00162 }
00163 }
00164 else
00165 status = Exception::make(IDB_ITERATOR_ERROR,
00166 "database is not set for class query on '%s'", cls->getName());
00167 }
00168
00169 Iterator::Iterator(const Collection *coll, Bool index)
00170 {
00171 init((Database *)coll->getDatabase());
00172
00173 (void)const_cast<Collection *>(coll)->loadDeferred();
00174
00175 if (coll->isRemoved())
00176 {
00177 status = Exception::make(IDB_OBJECT_REMOVE_ERROR,
00178 "object '%s' is removed.",
00179 coll->getOid().toString());
00180 return;
00181 }
00182
00183 if (!coll->getOidC().isValid())
00184 {
00185
00186
00187
00188
00189
00190 status = Success;
00191 return;
00192 }
00193
00194 if (db)
00195 status = StatusMake
00196 (queryCollectionCreate
00197 (db->getDbHandle(), coll->getOidC().getOid(), index, &qid[0]));
00198 else
00199 status = Exception::make(IDB_ITERATOR_ERROR,
00200 "database is not set for collection "
00201 "query on '%s'", coll->getName());
00202
00203 if (!status)
00204 _count = coll->getCount();
00205 }
00206
00207 Iterator::Iterator(Database *_db, const Attribute *agritem, int ind,
00208 Data start, Data end, Bool sexcl, Bool eexcl,
00209 int x_size)
00210 {
00211 init(_db);
00212
00213 if (db)
00214 status = StatusMake
00215 (queryAttributeCreate(db->getDbHandle(),
00216 agritem->getClassOwner()->getOid().getOid(),
00217 agritem->getNum(), ind, start, end,
00218 sexcl, eexcl, x_size, &qid[0]));
00219 else
00220 status = Exception::make(IDB_ITERATOR_ERROR, "database is not set for attribute query");
00221 }
00222
00223 Iterator::Iterator(Database *_db, const Attribute *agritem, int ind,
00224 Data start, int x_size)
00225 {
00226 init(_db);
00227
00228 if (db)
00229 status = StatusMake
00230 (queryAttributeCreate(db->getDbHandle(),
00231 agritem->getClassOwner()->getOid().getOid(),
00232 agritem->getNum(), ind, start, start,
00233 False, False, x_size, &qid[0]));
00234 else
00235 status = Exception::make(IDB_ITERATOR_ERROR, "database is not set for attribute query");
00236 }
00237
00238 Status Iterator::getStatus() const
00239 {
00240 return status;
00241 }
00242
00243 Status Iterator::scanNext(Bool &found, Oid &oid)
00244 {
00245 return scanNext(&found, &oid);
00246 }
00247
00248 Status Iterator::scanNext(Bool *found, Oid *oid)
00249 {
00250 *found = False;
00251
00252 if (status)
00253 return status;
00254
00255 IDB_CHECK_INTR();
00256
00257 for (;;)
00258 {
00259 Status s;
00260 IteratorAtom atom;
00261 s = scanNext(found, &atom);
00262 if (s)
00263 return s;
00264
00265 if (*found)
00266 {
00267 if (atom.type == IteratorAtom_OID)
00268 {
00269 *oid = atom.oid;
00270 break;
00271 }
00272 }
00273 else
00274 break;
00275 }
00276
00277 return Success;
00278 }
00279
00280 Status Iterator::scanNext(Bool *found, Value *value)
00281 {
00282 return scanNext(*found, *value);
00283 }
00284
00285 Status Iterator::scanNext(Bool &found, Value &value)
00286 {
00287 #define MAXDEPTH 64
00288 Value *lists[MAXDEPTH];
00289 int depth = 0;
00290
00291 for (;;) {
00292 IteratorAtom atom;
00293 status = scanNext(&found, &atom);
00294
00295 if (status || !found)
00296 return status;
00297
00298 #ifndef NEW_ITER_ATOM
00299 if (atom.type == IteratorAtom_LISTSEP) {
00300 if (atom.open) {
00301 Value *list = new Value(new LinkedList(), Value::tList);
00302 if (depth-1 >= 0)
00303 lists[depth-1]->list->insertObjectLast(list);
00304 lists[depth++] = list;
00305 continue;
00306 }
00307 else if (!--depth) {
00308 value = *lists[0];
00309 delete lists[0];
00310 return Success;
00311 }
00312 }
00313 else
00314 #endif
00315 {
00316 Value *avalue = atom.toValue();
00317 if (depth)
00318 lists[depth-1]->list->insertObjectLast(avalue);
00319 else {
00320 value = *avalue;
00321 delete avalue;
00322 return Success;
00323 }
00324 }
00325 }
00326 }
00327
00328 Status Iterator::scanNext(Bool *found, IteratorAtom *atom)
00329 {
00330 *found = False;
00331
00332 if (status)
00333 return status;
00334
00335 if (!state)
00336 return Success;
00337
00338 IDB_CHECK_INTR();
00339
00340 for (;;) {
00341 if (curatom >= readatom) {
00342 if (!qid[curqid]) {
00343 state = False;
00344 return Success;
00345 }
00346
00347 status = StatusMake(queryScanNext(db->getDbHandle(), qid[curqid], buff_len, &readatom, buffatom));
00348 if (status) {
00349 state = False;
00350 return status;
00351 }
00352 curatom = 0;
00353 }
00354
00355 assert(readatom <= buff_len);
00356 if (readatom)
00357 break;
00358 else {
00359 curqid++;
00360 if (curqid >= nqids) {
00361 state = False;
00362 return Success;
00363 }
00364 }
00365 }
00366
00367 *atom = buffatom[curatom];
00368 #ifndef TRACK_BUG
00369 buffatom[curatom++].garbage();
00370 #else
00371 curatom++;
00372 #endif
00373 *found = True;
00374 return status;
00375 }
00376
00377 #define INCR 512
00378
00379 Status Iterator::scan(ValueArray &valarray, unsigned int max,
00380 unsigned int start)
00381 {
00382 int alloc = 0;
00383 Value *values = 0;
00384 int count, n;
00385
00386 for (count = 0, n = 0; count < max; n++) {
00387 Bool found = False;
00388 Value avalue;
00389
00390
00391
00392
00393
00394
00395 Status s = scanNext(found, avalue);
00396
00397 if (s)
00398 return s;
00399
00400 if (!found)
00401 break;
00402
00403 if (n < start)
00404 continue;
00405
00406 if (count >= alloc) {
00407 int nalloc = alloc + INCR;
00408 Value *v = new Value[nalloc];
00409 for (int i = 0; i < alloc; i++)
00410 v[i] = values[i];
00411
00412 delete [] values;
00413 values = v;
00414 alloc = nalloc;
00415 }
00416
00417 #ifdef TRY_GETELEMS_GC
00418 values[count].setAutoObjGarbage(valarray.isAutoObjGarbage());
00419 #endif
00420
00421 values[count++] = avalue;
00422 }
00423
00424 valarray.set(values, count, False);
00425 return Success;
00426 }
00427
00428 Status Iterator::scan(int *count, IteratorAtom **atom_array)
00429 {
00430 *count = 0;
00431 int alloc = 0;
00432 *atom_array = 0;
00433 for (;;)
00434 {
00435 Bool found = False;
00436 IteratorAtom qatom;
00437 Status s = scanNext(&found, &qatom);
00438 if (s)
00439 return s;
00440 if (!found)
00441 break;
00442 if (*count >= alloc)
00443 {
00444 int nalloc = alloc + 512;
00445 #ifdef IDB_VECT
00446 IteratorAtom *tmp = idbNewVect(IteratorAtom, nalloc);
00447 #else
00448 assert(0);
00449 IteratorAtom *tmp = new IteratorAtom[nalloc];
00450 #endif
00451 if (*atom_array)
00452 {
00453 for (int i = 0; i < alloc; i++)
00454 tmp[i] = (*atom_array)[i];
00455
00456 #ifdef IDB_VECT
00457 idbFreeVect(*atom_array, IteratorAtom, alloc);
00458 #else
00459 assert(0);
00460 delete[] (*atom_array);
00461 #endif
00462 }
00463 *atom_array = tmp;
00464 alloc = nalloc;
00465 }
00466 (*atom_array)[(*count)++] = qatom;
00467 qatom.garbage();
00468 }
00469
00470 return Success;
00471 }
00472
00473 Status Iterator::scanNext(Bool &found, Object *&o,
00474 const RecMode *rcm)
00475 {
00476 return scanNext(&found, &o, rcm);
00477 }
00478
00479 Status Iterator::scanNext(Bool *found, Object **o, const RecMode *rcm)
00480 {
00481 Oid oid;
00482
00483 *found = False;
00484
00485 IDB_CHECK_INTR();
00486
00487 Status s = scanNext(found, &oid);
00488
00489 if (s)
00490 return s;
00491
00492 if (*found)
00493 return db->loadObject(&oid, o, rcm);
00494
00495 return Success;
00496 }
00497
00498 Status Iterator::scan(ObjectPtrVector &obj_vect, const RecMode *rcm)
00499 {
00500 ObjectArray obj_array;
00501 Status s = scan(obj_array, rcm);
00502 if (s)
00503 return s;
00504 obj_array.makeObjectPtrVector(obj_vect);
00505 return Success;
00506 }
00507
00508 Status Iterator::scan(ObjectPtrVector &obj_vect, unsigned int max,
00509 unsigned int start, const RecMode *rcm)
00510 {
00511 ObjectArray obj_array;
00512 Status s = scan(obj_array, max, start, rcm);
00513 if (s)
00514 return s;
00515 obj_array.makeObjectPtrVector(obj_vect);
00516 return Success;
00517 }
00518
00519 Status Iterator::scan(ObjectArray &obj_array, const RecMode *rcm)
00520 {
00521 return scan(obj_array, ~0, 0, rcm);
00522 }
00523
00524 Status Iterator::scan(ObjectArray &obj_array, unsigned int max,
00525 unsigned int start, const RecMode *rcm)
00526 {
00527 OidArray oid_array;
00528
00529 status = scan(oid_array, max, start);
00530 if (status)
00531 return status;
00532
00533 int count = oid_array.getCount();
00534 Object **obj_x = (Object **)malloc(count * sizeof(Object *));
00535 for (int i = 0; i < count; i++)
00536 {
00537
00538
00539 if (status = db->loadObject(&oid_array[i], &obj_x[i], rcm))
00540 {
00541 for (int j = 0; j < i; j++)
00542 obj_x[j]->release();
00543 free(obj_x);
00544 return status;
00545 }
00546 }
00547
00548 obj_array.set(obj_x, count);
00549 free(obj_x);
00550 return Success;
00551 }
00552
00553 Status Iterator::scan(OidArray &oid_array, unsigned int max,
00554 unsigned int start)
00555 {
00556 int alloc = 0;
00557 Oid *oid_x = 0;
00558 int count, n;
00559
00560 for (count = 0, n = 0; count < max; n++)
00561 {
00562 Bool found = False;
00563 Oid _oid;
00564 Status s = scanNext(&found, &_oid);
00565
00566 if (s)
00567 return s;
00568
00569 if (!found)
00570 break;
00571
00572 if (n < start)
00573 continue;
00574
00575 if (count >= alloc)
00576 {
00577 int nalloc = alloc + 512;
00578 oid_x = (Oid *)realloc(oid_x, nalloc * sizeof(Oid));
00579 alloc = nalloc;
00580 }
00581
00582 oid_x[count++] = _oid;
00583 }
00584
00585 if (oid_x)
00586 {
00587 oid_array.set(oid_x, count);
00588 free(oid_x);
00589 }
00590
00591 return Success;
00592 }
00593
00594 Iterator::~Iterator()
00595 {
00596 if (db)
00597 {
00598 for (int n = 0; n < nqids; n++)
00599 if (qid[n])
00600 queryDelete(db->getDbHandle(), qid[n]);
00601 }
00602
00603 #ifndef TRACK_BUG
00604 if (buffatom)
00605 {
00606 #ifdef IDB_VECT
00607 idbFreeVect(buffatom, IteratorAtom, buff_len);
00608 #else
00609 assert(0);
00610 delete [] buffatom;
00611 #endif
00612 }
00613
00614 free(qid);
00615 #endif
00616
00617
00618 delete schinfo;
00619 }
00620 }