BIdxSearch.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    Authors: Stuart Pook
00022             Eric Viara <viara@sysra.com>
00023 */
00024 
00025 #include <eyedbconfig.h>
00026 
00027 #include        <stdlib.h>
00028 
00029 #include <eyedbsm/eyedbsm.h>
00030 #include        <BIdxBTree.h>
00031 #include        <assert.h>
00032 
00033 namespace eyedbsm {
00034   extern Boolean backend_interrupt;
00035 
00036   class BIdxChain
00037   {
00038     BIdxChain * _next;
00039     BIdx * const idx;
00040     BIdxChain(BIdxChain const &);
00041     BIdxChain & operator=(BIdxChain const &);
00042   public:
00043     BIdxChain * const prev;
00044     unsigned i;
00045     BIdx::InCore blk;
00046 
00047     BIdxChain(BIdx * b, BIdxChain * p) : blk(b), idx(b), prev(p), _next(0)  { }
00048     ~BIdxChain() {  if (_next) delete _next; }
00049 
00050     BIdxChain * next() { return (_next) ? _next : (_next = new BIdxChain(idx, this));}
00051   };
00052 
00053 
00054   static Status
00055   findFirst(Oid oid, BIdxChain * chain, BIdxChain * * last)
00056   {
00057     Status s;
00058     while ((s = chain->blk.read(&oid)) == 0 && !chain->blk.node->leaf) {
00059       chain->i = 0;
00060       oid = chain->blk.node->c[0];
00061       chain = chain->next();
00062     }
00063     chain->i = 0;
00064     if (chain->blk.node->n == 0)
00065       *last = 0;
00066     else
00067       *last = chain;
00068     return s;
00069   }
00070 
00071   static Status
00072   bTreeSearchAny(void const * key, Oid oid, BIdx::InCore * x, unsigned * ip, unsigned int *found_cnt, Boolean found_any)
00073   {
00074     *found_cnt = 0;
00075     for (;;) {
00076       if (backend_interrupt)
00077         return statusMake(BACKEND_INTERRUPTED, "");
00078       Status s;
00079       unsigned i;
00080       if (s = x->read(&oid))
00081         return s;
00082       for (i = 0; i < x->node->n && x->cmp(i, key, OP1_SWAP) < 0; i++)
00083         ;
00084       if ((i < x->node->n && x->cmp(i, key, OP1_SWAP) == 0)) {
00085         *ip = i;
00086         (*found_cnt)++;
00087         if (found_any)
00088           return Success;
00089       }
00090       if (x->node->leaf) {
00091         return Success;
00092       }
00093       oid = x->node->c[i];
00094     }
00095 
00096     return eyedbsm::Success;
00097   }
00098 
00099   Status
00100   BIdx::search(void const * key, unsigned int *found_cnt)
00101   {
00102     return searchPerform(key, found_cnt, eyedbsm::False, 0);
00103   }
00104 
00105   Status
00106   BIdx::searchAny(void const * key, Boolean * found, void * data)
00107   {
00108     unsigned int found_cnt;
00109     Status s = searchPerform(key, &found_cnt, eyedbsm::True, data);
00110     if (s)
00111       return s;
00112     *found = (found_cnt != 0) ? eyedbsm::True : eyedbsm::False;
00113     return eyedbsm::Success;
00114   }
00115 
00116   Status
00117   BIdx::searchPerform(void const * key, unsigned int * found_cnt, Boolean found_any, void * data)
00118   {
00119 #if 1
00120     BIdxCursor curs(this, key, key, False, False);
00121 
00122     *found_cnt = 0;
00123     for (;;) {
00124       eyedbsm::Boolean found;
00125       eyedbsm::Status s = curs.next(&found, data);
00126       if (s)
00127         return s;
00128 
00129       if (!found)
00130         break;
00131 
00132       (*found_cnt)++;
00133 
00134       if (found_any)
00135         return eyedbsm::Success;
00136       }
00137 
00138     return eyedbsm::Success;
00139 #else
00140     BTree tree;
00141     if (stat = readBTree(tree))
00142       return fatal();
00143     BIdx::InCore x(this);
00144     unsigned i;
00145     Status s;
00146 #if 0
00147     if (!(s = bTreeSearchAny(key, tree.root, &x, &i, found_cnt, found_any))) {
00148       if (i < x.node->n && cmp(key, x.k(i), OP2_SWAP) == 0) {
00149         *found = True;
00150         if (data)
00151           memcpy(data, x.d(i), dataSize);
00152       }
00153       else
00154         *found = False;
00155     }
00156 #else
00157     if (!(s = bTreeSearchAny(key, tree.root, &x, &i, found_cnt, found_any))) {
00158       if (*found_cnt && data) {
00159           memcpy(data, x.d(i), dataSize);
00160       }
00161     }
00162 #endif
00163     return s;
00164 #endif
00165   }
00166 
00167   static Status
00168   bTreeSearchFirst(void const * key, Oid oid, BIdxChain * c, BIdxChain * * last)
00169   {
00170     Boolean exact = False;
00171     for (;;) {
00172       Status s;
00173       if (s = c->blk.read(&oid))
00174         return s;
00175       int r;
00176       for (c->i = 0; c->i < c->blk.node->n && (r = c->blk.cmp(c->i, key, OP1_SWAP)) < 0; c->i++)
00177         ;
00178       if (c->blk.node->leaf) {
00179         if (!exact || (c->i < c->blk.node->n && r == 0))
00180           *last = c;
00181         return Success;
00182       }
00183       if (c->i < c->blk.node->n && r == 0) {
00184         *last = c;
00185         exact = True;
00186       }
00187       oid = c->blk.node->c[c->i];
00188       c = c->next();
00189     }
00190   }
00191 
00192   static void *
00193   copyKey(int n, void const * key)
00194   {
00195     if (key == 0)
00196       return 0;
00197     return memcpy(new char[n], key, n);
00198   }
00199         
00200   BIdxCursor::BIdxCursor
00201   (
00202    BIdx * idxIn,
00203    void const * sKeyIn,
00204    void const * eKeyIn,
00205    Boolean sExclusiveIn,
00206    Boolean eExclusiveIn,
00207    Boolean (*_user_cmp)(const void *key, void *cmp_arg),
00208    void *_cmp_arg
00209    )
00210   {
00211     idx = idxIn;
00212     sKey = copyKey(idx->keySize, sKeyIn);
00213     eKey = copyKey(idx->keySize, (eKeyIn == defaultSKey) ? sKeyIn : eKeyIn);
00214     sExclusive = sExclusiveIn;
00215     eExclusive = eExclusiveIn;
00216     chainFirst = chain = 0;
00217     user_cmp = _user_cmp;
00218     cmp_arg = _cmp_arg;
00219   }
00220 
00221   static Status
00222   nextBIdxChain(BIdxChain * cp, BIdxChain * * out)
00223   {
00224     cp->i++;
00225     if (!cp->blk.node->leaf)
00226       while (!cp->blk.node->leaf) {
00227         BIdxChain * p = cp->next();
00228         Status s;
00229         if (s = p->blk.read(&cp->blk.node->c[cp->i]))
00230           return s;
00231         cp = p;
00232         cp->i = 0;
00233       }
00234     else if (cp->i >= cp->blk.node->n)
00235       while ((cp = cp->prev) && cp->i == cp->blk.node->n)
00236         ;
00237     *out = cp;
00238     return Success;
00239   }             
00240 
00241   Status BIdxCursor::next(Boolean *found, DataBuffer &data, Idx::Key *key)
00242   {
00243     return statusMake(NOT_YET_IMPLEMENTED, "BIdxCursor::next(Boolean *found, DataBuffer &data, Idx::Key *key)");
00244   }
00245 
00246   Status
00247   BIdxCursor::next(unsigned int *found_cnt, Idx::Key *key)
00248   {
00249     *found_cnt = 0;
00250     // for now !
00251     return statusMake(ERROR, "cannot use this type of cursor on non data_grouped_by_key hash index");
00252   }
00253 
00254   Status
00255   BIdxCursor::next(Boolean * found, void * data, Idx::Key * key)
00256   {
00257     *found = False;
00258     for (;;) {
00259       if (backend_interrupt)
00260         return statusMake(BACKEND_INTERRUPTED, "");
00261       Status s;
00262       if (chain) {
00263         if (s = nextBIdxChain(chain, &chain))
00264           return s;
00265       }
00266       else {
00267         BIdx::BTree tree;
00268         if (idx->stat = idx->readBTree(tree))
00269           return idx->fatal();
00270         chainFirst = new BIdxChain(idx, 0);
00271         Status s;
00272         if (sKey) {
00273           if (s = bTreeSearchFirst(sKey, tree.root, chainFirst, &chain))
00274             return s;
00275           if (chain->i == chain->blk.node->n)
00276             if (s = nextBIdxChain(chain, &chain))
00277               return s;
00278         }
00279         else if (s = findFirst(tree.root, chainFirst, &chain))
00280           return s;
00281       }
00282       int r;
00283       while (chain && sKey &&
00284              ((r = idx->cmp(sKey, chain->blk.k(chain->i), OP2_SWAP)) > 0 ||
00285               (r == 0 && sExclusive)))
00286         if (s = nextBIdxChain(chain, &chain))
00287           return s;
00288 
00289       if (!chain ||
00290           (eKey && ((r = idx->cmp(eKey, chain->blk.k(chain->i), OP2_SWAP)) < 0 ||
00291                     (r == 0 && eExclusive)))) {
00292         *found = False;
00293         return Success;
00294       }
00295 
00296       // EV: added 13/12/01
00297       if (idx->precmp) {
00298         void const * sk = sKey ? sKey : eKey;
00299         if (sk && idx->precmp(sk, chain->blk.k(chain->i),
00300                               &idx->_keyType[0], r)) {
00301           //printf("skipping entry\n");
00302           if (!sKey)
00303             continue;
00304           *found = False;
00305           return Success;
00306         }
00307       }
00308       // end added
00309 
00310       if (user_cmp && !user_cmp(chain->blk.k(chain->i), cmp_arg))
00311         continue;
00312 
00313       *found = True;
00314 #if 0
00315       if (key)
00316         key->setKey(chain->blk.k(chain->i), -idx->keySize, *idx->_keyType);
00317 #else
00318       if (key)
00319         key->setKey(chain->blk.k(chain->i), idx->keySize, *idx->_keyType);
00320 #endif
00321 
00322       if (data)
00323         memcpy(data, chain->blk.d(chain->i), idx->dataSize);
00324       return Success;   
00325     }
00326   }
00327 
00328   BIdxCursor::~BIdxCursor()
00329   {
00330     delete [] (char **)sKey;
00331     delete [] (char **)eKey;
00332     delete chainFirst;
00333   }
00334 
00335   char const BIdxCursor::defaultSKey[] = "";
00336 }

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