Iterator.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021   Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 //
00026 // MIND: error sur le `_count'
00027 // la methode getCount() ne marche que pour le queryLangCreate()
00028 // pour les autres types de queries, le _count n'est pas mis a jour.
00029 //
00030 // a corriger!
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 //#define TRACK_BUG
00040 
00041 namespace eyedbsm {
00042   extern Boolean backend;
00043 }
00044 namespace eyedb {
00045 
00046 #define TRY_GETELEMS_GC
00047 
00048   //
00049   // this method initializes a few OQL built-in functions in the
00050   // opened database.
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     //  qid = new int[1];
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                 // added True the 2/3/00
00107                 if (status = subclasses[i]->getExtent(extent, True))
00108                   break;
00109 
00110                 // added extent->getCount() the 2/3/00
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           status = Exception::make(IDB_ITERATOR_ERROR,
00187           "cannot iterate on a non persistent "
00188           "collection");
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         #ifdef TRY_GETELEMS_GC
00391         avalue.setAutoObjGarbage(valarray.isAutoObjGarbage());
00392         #endif
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; // true of false ?
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; // true of false ?
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         /*if (!oid_array[i].isValid())
00538           obj_x[i] = 0;
00539           else*/ 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     //  delete[] qid;
00614     free(qid);
00615 #endif
00616 
00617     //
00618     delete schinfo;
00619   }
00620 }

Generated on Mon Dec 22 18:15:56 2008 for eyedb by  doxygen 1.5.3