BIdxDelete.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 #include        <string.h>
00029 #include        <assert.h>
00030 
00031 #include        <eyedbsm/eyedbsm.h>
00032 #include        <eyedbsm/BIdx.h>
00033 #include        "BIdxBTree.h"
00034 #include        "IdxP.h"
00035 
00036 namespace eyedbsm {
00037 
00038   static Boolean
00039   look(BIdx::InCore const * x, void const * key, void const * data, unsigned * ip)
00040   {
00041     unsigned i;
00042     for (i = 0; i < x->node->n; i++) {
00043       int r;
00044       if ((r = x->cmp(i, key, data, OP1_SWAP)) == 0) {
00045         *ip = i;
00046         return True;
00047       }
00048       else if (r > 0)   {
00049         *ip = i;
00050         return False;
00051       }
00052     }
00053     *ip = i;
00054     return False;
00055   }
00056 
00057   static void
00058   kdcCopy(BIdx::InCore * x, unsigned xp, BIdx::InCore const * y, unsigned yp)
00059   {
00060     x->kdCopy(xp, y, yp);
00061     x->node->c[xp] = y->node->c[yp];
00062   }
00063 
00064   static Status
00065   merge(BIdx::InCore * x, unsigned const i, BIdx::InCore * y, BIdx::InCore * z)
00066   {
00067     Status s;
00068     unsigned j;
00069 
00070     y->node->n++;
00071     y->kdCopy(y->node->n - 1, x, i);
00072 
00073     for (j = i; j < x->node->n - 1; j++)
00074       x->kdCopy(j, x, j + 1);
00075     for (j = i + 1; j < x->node->n; j++)
00076       x->node->c[j] = x->node->c[j + 1];
00077     x->node->n--;
00078     if (s = x->write())
00079       return s;
00080 
00081     unsigned const yn = y->node->n;
00082     y->node->n += z->node->n;
00083     for (j = 0; j < z->node->n; j++)
00084       kdcCopy(y, yn + j, z, j);
00085     y->node->c[yn + j] = z->node->c[j];
00086     return z->destroy();
00087   }
00088 
00089   /*
00090    *    Case 3a (move a key left)
00091    */
00092   static void
00093   moveLeft(BIdx::InCore * to, BIdx::InCore * middle, unsigned const middlep, BIdx::InCore * from)
00094   {
00095     unsigned i;
00096     to->node->n++;
00097     to->kdCopy(to->node->n - 1, middle, middlep);
00098     to->node->c[to->node->n] = from->node->c[0];
00099 
00100     middle->kdCopy(middlep, from, 0);
00101 
00102     for (i = 1; i < from->node->n; i++)
00103       kdcCopy(from, i - 1, from, i);
00104     from->node->c[i - 1] = from->node->c[i];
00105     from->node->n--;
00106   }
00107 
00108   /*
00109    *    Case 3a (move a key right)
00110    */
00111   static void
00112   moveRight(BIdx::InCore * to, BIdx::InCore * middle, unsigned const middlep, BIdx::InCore * from)
00113   {
00114     unsigned j;
00115     to->node->c[to->node->n + 1] = to->node->c[to->node->n];
00116     for (j = to->node->n++; j > 0; j--)
00117       kdcCopy(to, j, to, j - 1);
00118     to->kdCopy(0, middle, middlep - 1);
00119     to->node->c[0] = from->node->c[from->node->n];
00120 
00121     middle->kdCopy(middlep - 1, from, from->node->n - 1);
00122     from->node->n--;
00123   }
00124 
00125   Status
00126   change(BIdx::InCore * old, BIdx::InCore * newV, Boolean * write)
00127   {
00128     if (*write) {
00129       *write = False;
00130       Status s;
00131       if (s = old->write())
00132         return s;
00133     }
00134     *old = *newV;
00135     return Success;
00136   }
00137 
00138   static Status
00139   bTreeDelete(BIdx * idx, BIdx::InCore x, void const * key, void const * data,
00140               Boolean * found)
00141   {
00142     unsigned writeBackPos;
00143     BIdx::InCore writeBackNode(idx);
00144     unsigned i;
00145     Status s;
00146     Boolean here;
00147     enum { KEY, FIRST, LAST } status = KEY; // what to delete
00148     BIdx::InCore y(idx);
00149     BIdx::InCore z(idx);
00150     Boolean writeX = False;
00151     unsigned int degree = idx->getDegree();
00152     while (!x.node->leaf) {
00153       if (status != KEY) {
00154         here = False;
00155         i = (status == FIRST) ? 0 : x.node->n;
00156       }
00157       else
00158         here = look(&x, key, data, &i);
00159                 
00160       if (here) {
00161         if (s = y.read(&x.node->c[i]))
00162           return s;
00163         if (y.node->n >= (unsigned)degree) {
00164           writeBackNode = x;
00165           writeBackPos = i;
00166           status = LAST;
00167           if (s = change(&x, &y, &writeX))
00168             return s;
00169         }
00170         else {
00171           if (s = z.read(&x.node->c[i + 1]))
00172             return s;
00173           if (z.node->n >= (unsigned)degree) {
00174             writeBackNode = x;
00175             writeBackPos = i;
00176             status = FIRST;
00177             if (s = change(&x, &z, &writeX))
00178               return s;
00179           }
00180           else {
00181             if (s = merge(&x, i, &y, &z))
00182               return s;
00183             writeX = True;
00184             x = y;
00185           }
00186         }
00187       }
00188       else {
00189         if (s = y.read(&x.node->c[i]))
00190           return s;
00191         if (y.node->n != (unsigned)degree - 1) {
00192           if (s = change(&x, &y, &writeX))
00193             return s;
00194         }
00195         else {
00196           if (i > 0 && (s = z.read(&x.node->c[i - 1])))
00197             return s;
00198           if (i > 0 && z.node->n >= (unsigned)degree) {
00199             moveRight(&y, &x, i, &z);
00200             if (s = z.write())
00201               return s;
00202             if (s = x.write())
00203               return s;
00204             x = y;
00205           }
00206           else {
00207             if (i != x.node->n && (s = z.read(&x.node->c[i + 1])))
00208               return s;
00209             if (i != x.node->n && z.node->n >= (unsigned)degree) {
00210               moveLeft(&y, &x, i, &z);
00211               if ((s = z.write()) || (s = x.write()))
00212                 return s;
00213               x = y;
00214             }
00215             else if (i == x.node->n) {
00216               if (s = merge(&x, i - 1, &z, &y))
00217                 return s;
00218               x = z;
00219             }
00220             else {
00221               if (s = merge(&x, i, &y, &z))
00222                 return s;
00223               x = y;
00224             }
00225           }
00226           writeX = True;
00227         }
00228       }
00229     }
00230 
00231     if (status == KEY)
00232       here = look(&x, key, data, &i);
00233     else {
00234       here = True;
00235       i = (status == FIRST) ? 0 : x.node->n - 1;
00236       writeBackNode.kdCopy(writeBackPos, &x, i);
00237       if (s = writeBackNode.write())
00238         return s;
00239     }
00240         
00241     if (here) {
00242       for (; i < x.node->n - 1; i++)
00243         x.kdCopy(i, &x, i + 1);
00244       x.node->n--;
00245       if (s = x.write())
00246         return s;
00247     }
00248     else if (writeX && (s = x.write()))
00249       return s;
00250     if (found)
00251       *found = here;
00252     return Success;
00253   }
00254 
00255   Status BIdx::remove(const void *key, const void *data, unsigned int datasz, Boolean *found)
00256   {
00257     return statusMake(NOT_YET_IMPLEMENTED, "BIdx::remove(const void *key, const void *data, unsigned int datasz, Boolean *found)");
00258   }
00259 
00260   Status BIdx::remove(void const * key, void const * data, Boolean * found)
00261   {
00262     if (stat)
00263       return stat;
00264 
00265     IdxLock lockx(dbh, treeOid);
00266     Status s = lockx.lock();
00267     if (s)
00268       return s;
00269 
00270     BIdx::InCore x(this);
00271     BTree tree;
00272     if (stat = readBTree(tree))
00273       return fatal();
00274     if (s = x.read(&tree.root))
00275       return s;
00276     if (s = bTreeDelete(this, x, key, data, found))
00277       return s;
00278     if (x.node->n == 0 && !x.node->leaf) {
00279       tree.root = x.node->c[0];
00280       if (stat = x.destroy())
00281         return stat;
00282       if (stat = writeBTree(tree))
00283         return fatal();
00284     }
00285 
00286     return count_manage(-1);
00287 
00288   }
00289 }

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