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 #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
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
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;
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 }