BIdxIncore.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 <eyedblib/thread.h>
00028 #include        <stdlib.h>
00029 #include        <string.h>
00030 #include        <assert.h>
00031 #include <iostream>
00032 
00033 #include <eyedbsm/eyedbsm.h>
00034 #include        "BIdxBTree.h"
00035 #include <eyedblib/m_mem.h>
00036 #include "lib/m_mem_p.h"
00037 
00038 //#define USE_CACHE
00039 //#define USE_CACHE_CHECK
00040 //#define USE_CACHE_T1
00041 //#define USE_CACHE_TRACE
00042 
00043 #define NOMEMZERO
00044 
00045 namespace eyedbsm {
00046 
00047   Status
00048   BIdx::InCore::create()
00049   {
00050 #ifdef USE_CACHE
00051     if (oid.nx) {
00052       if (node_b) {
00053         node = node_b;
00054         node_b = 0;
00055       }
00056 
00057       if (keys_b) {
00058         keys = keys_b;
00059         keys_b = 0;
00060       }
00061 
00062       if (data_b) {
00063         data = data_b;
00064         data_b = 0;
00065       }
00066     }
00067 #ifdef USE_CACHE_TRACE
00068     cout << "InCore::create(" << getOidString(&oid);
00069 #endif
00070 #endif
00071     if (idx->stat = objectCreate(idx->dbh, keys,
00072                                  idx->keySize * idx->maxchildren,
00073                                  idx->dspid, &node->keys))
00074       return idx->fatal();
00075     if (idx->stat = objectCreate(idx->dbh, data,
00076                                  idx->dataSize * idx->maxchildren,
00077                                  idx->dspid, &node->data))
00078       return idx->fatal();
00079     if (idx->stat = idx->createNode(node, &oid))
00080       return idx->fatal();
00081 
00082 #ifdef USE_CACHE_TRACE
00083     cout << " => " << getOidString(&oid) << ")\n";
00084 #endif
00085     return idx->stat;
00086   }
00087 
00088   Status
00089   BIdx::InCore::destroy()
00090   {
00091     if (idx->stat = objectDelete(idx->dbh, idx->keySize * idx->maxchildren, &node->keys))
00092       return idx->fatal();
00093     if (idx->stat = objectDelete(idx->dbh, idx->dataSize * idx->maxchildren, &node->data))
00094       return idx->fatal();
00095     if (idx->stat = objectDelete(idx->dbh, Node::nodeSize(idx), &oid))
00096       return idx->fatal();
00097     return idx->stat;
00098   }
00099 
00100   BIdx::InCore&
00101   BIdx::InCore::operator=(InCore const & y)
00102   {
00103     if (this != &y) {
00104 #ifdef USE_CACHE_TRACE
00105       cout << "InCore::operator=(InCore const &, " <<
00106         "node=" << node << ", node_b=" << node_b <<
00107         ", y.node=" << y.node << ", y.node_b=" << y.node_b << ")\n";
00108 #endif
00109       assert(idx == y.idx); 
00110 
00111 #ifdef USE_CACHE
00112       if ((node && node == y.node) ||
00113           (node && node == y.node_b) ||
00114           (node_b && node_b == y.node) ||
00115           (node_b && node_b == y.node_b))
00116         cout << "BIdx::InCore::operator=(): strange...!\n";
00117 #endif
00118 
00119       // changed the 16/04/02
00120       if (node != y.node) {
00121 #ifdef USE_CACHE
00122         if (node_b) {
00123           node = node_b;
00124           node_b = 0;
00125         }
00126 
00127         if (node_b != y.node &&
00128             node_b != y.node_b &&
00129             node != y.node_b)
00130 #endif
00131           Node::freeNode(node);
00132       }
00133 
00134 #ifdef USE_CACHE
00135       node_b = 0;
00136 #endif
00137       node = Node::copyNode(idx, y.node);
00138       //cout << "copy this=" << this << ", from=" << &y << ", " << getOidString(&oid) << " -> " << getOidString(&y.oid) << "\n";
00139       oid = y.oid;
00140 #ifdef USE_CACHE
00141       if (keys_b) {
00142         keys = keys_b;
00143         keys_b = 0;
00144       }
00145       if (data_b) {
00146         data = data_b;
00147         data_b = 0;
00148       }
00149 #endif
00150       memcpy(keys, y.keys, idx->keySize * idx->maxchildren);
00151       memcpy(data, y.data, idx->dataSize * idx->maxchildren);
00152     }
00153     return *this;
00154   }
00155 
00156   struct BIdx::Space
00157   {
00158     void * keys;
00159     void * data;
00160     Space * next;
00161     friend class InCore;
00162     Space(BIdx * idx, Space * n)
00163       : next(n), keys(new char[idx->keySize * idx->maxchildren]), data(new char[idx->dataSize * idx->maxchildren])
00164     {
00165     }
00166     ~Space() { delete [] (char **)keys; delete [] (char **)data; }
00167   };
00168 
00169   BIdx::~BIdx()
00170   {
00171     delete [] _keyType;
00172     Space *p;
00173 
00174     for (; p = free; delete p)
00175       free = p->next;
00176     for (; p = occupied; delete p)
00177       occupied = p->next;
00178 
00179     Node::freeNode(tmpnode);
00180   }
00181 
00182   static void
00183   getSpace(BIdx * idx, BIdx::Space * * free, BIdx::Space * * occupied, void * * keys, void * * data)
00184   {
00185     BIdx::Space * p = *free;
00186     if (p) {
00187       *free = p->next;
00188       p->next = *occupied;
00189       *occupied = p;
00190     }
00191     else
00192       *occupied = p = new BIdx::Space(idx, *occupied);
00193     *keys = p->keys;
00194     *data = p->data;
00195   }
00196 
00197   BIdx::InCore::InCore(InCore const & y) : idx(y.idx)
00198   {
00199 #ifdef USE_CACHE
00200     keys_b = data_b = 0;
00201     node_b = 0;
00202 #endif
00203 #ifdef USE_CACHE_TRACE
00204     cout << "InCore::InCore(InCore const &)\n";
00205 #endif
00206     getSpace(idx, &idx->free, &idx->occupied, &keys, &data);
00207     node = Node::copyNode(idx, y.node);
00208     oid = y.oid;
00209     memcpy(keys, y.keys, idx->keySize * idx->maxchildren);
00210     memcpy(data, y.data, idx->dataSize * idx->maxchildren);
00211   }
00212 
00213   BIdx::InCore::InCore(BIdx * b) : idx(b)
00214   {
00215 #ifdef USE_CACHE
00216     keys_b = data_b = 0;
00217     node_b = 0;
00218 #endif
00219     getSpace(idx, &idx->free, &idx->occupied, &keys, &data);
00220     /*
00221      *  The initializations below are just to shutup dbx/purify.
00222      *  The illegal value are to provoke an error if we forget to overwrite thes values.
00223      */
00224     node = Node::allocNode(idx);
00225     node->leaf = 2; // illegal value
00226     node->n = b->maxchildren + 2; // illegal value
00227 
00228     oid = Oid::nullOid;
00229 #ifndef NOMEMZERO
00230     memset(keys, 0, idx->keySize * idx->maxchildren);
00231     memset(data, 0, idx->dataSize * idx->maxchildren);
00232 #endif
00233   }
00234 
00235   BIdx::InCore::~InCore()
00236   {
00237     Space * p = idx->occupied;
00238 #ifdef USE_CACHE
00239     if (node_b)
00240       node = node_b;
00241     if (keys_b)
00242       keys = keys_b;
00243     if (data_b)
00244       data = data_b;
00245 #endif
00246     p->keys = keys;
00247     p->data = data;
00248     idx->occupied = p->next;
00249     p->next = idx->free;
00250     idx->free = p;
00251     Node::freeNode(node);
00252     //  delete [] (char *)keys; delete [] (char *)data;
00253   }
00254 
00255   Status
00256   BIdx::InCore::read(Oid const * oidp)
00257   {
00258 #ifdef USE_CACHE_TRACE
00259     if (oid.nx && memcmp(&oid, oidp, sizeof(oid))) {
00260       cout << "HORROR: changing oid in read " << getOidString(&oid) << " vs. "<< getOidString(oidp) << "\n";
00261     }
00262 #endif
00263     oid = *oidp;
00264 
00265 #ifdef USE_CACHE
00266     Status se;
00267     void *xdata = 0;
00268     if (idx->stat = objectReadCache(idx->dbh, 0, &xdata, DefaultLock,
00269                                     &oid))
00270       return idx->fatal();
00271 #ifdef USE_CACHE_TRACE
00272     cout << "Reading node xdata = " << xdata << "\n";
00273 #endif
00274     if (xdata) {
00275 #ifdef USE_CACHE_TRACE
00276       cout << "CHECK: this=" << this << ", node_b=" << node_b << ", node=" << node << "\n";
00277 #endif
00278 
00279 #ifdef USE_CACHE
00280       if (!node_b) // added the 16/04/02
00281         node_b = node;
00282       else
00283         cout << "BIdx::InCore::read(): strange\n";
00284 #endif
00285 
00286 #ifdef USE_CACHE_TRACE
00287       cout << "have read from cache " << getOidString(&oid) << "\n";
00288 #endif
00289 #ifdef USE_CACHE_CHECK
00290 
00291       if (idx->stat = idx->readNode(node, oid))
00292         return idx->fatal();
00293       assert(!memcmp(node, xdata, Node::nodeSize(idx)));
00294 #endif
00295       node = (Node *)xdata;
00296     }
00297     else if (idx->stat = idx->readNode(node, oid))
00298       return idx->fatal();
00299 
00300     if (idx->stat = objectReadCache(idx->dbh, 0, &xdata, DefaultLock,
00301                                     &node->keys))
00302       return idx->fatal();
00303 #ifdef USE_CACHE_TRACE
00304     cout << "Reading keys xdata = " << xdata << "\n";
00305 #endif
00306     if (xdata) {
00307       if (!keys_b) // added the 16/04/02
00308         keys_b = keys;
00309 #ifdef USE_CACHE_CHECK
00310       if (idx->stat = objectRead(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00311         return idx->fatal();
00312       assert(!memcmp(keys, xdata, idx->keySize * idx->maxchildren));
00313 #endif
00314       keys = xdata;
00315     }
00316     else if (idx->stat = objectRead(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00317       return idx->fatal();
00318     if (idx->stat = objectReadCache(idx->dbh, 0, &xdata, DefaultLock,
00319                                     &node->data))
00320       return idx->fatal();
00321 #ifdef USE_CACHE_TRACE
00322     cout << "Reading data xdata = " << xdata << "\n";
00323 #endif
00324     if (xdata) {
00325       if (!data_b) // added the 16/04/02
00326         data_b = data;
00327 #ifdef USE_CACHE_CHECK
00328       if (idx->stat = objectRead(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00329         return idx->fatal();
00330       assert(!memcmp(data, xdata, idx->dataSize * idx->maxchildren));
00331 #endif
00332       data = xdata;
00333     }
00334     else if (idx->stat = objectRead(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00335       return idx->fatal();
00336     return idx->stat;
00337 
00338 #else
00339 
00340     if (idx->stat = idx->readNode(node, oid))
00341       return idx->fatal();
00342 
00343     if (idx->stat = objectRead(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00344       return idx->fatal();
00345     if (idx->stat = objectRead(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00346       return idx->fatal();
00347     return idx->stat;
00348 #endif
00349   }
00350 
00351   //
00352   // this routine can be improved a lot in insertion process:
00353   // 1. if btreeSplitChild has not been called, it is not necessary to write
00354   //    back to the database the entire node (which sizeof is 2068). Only leaf
00355   //    and n fields must be written
00356   // 2. only a part of keys and data could be written back to database according
00357   //    what has been shifted with kdCopy. In average, only half of the 2 objects
00358   //    must be written.
00359 
00360   Status
00361   BIdx::InCore::write()
00362   {
00363 #if 0
00364     Node tmpnode;
00365     if (idx->stat = objectRead(idx->dbh, sizeof tmpnode, &tmpnode, &oid))
00366       return idx->fatal();
00367     printf("nodes %sdiffer\n", memcmp(&tmpnode, &node, sizeof(node)) ?
00368            "" : "DO NOT ");
00369     printf("nodes %sreally differ\n", memcmp(tmpnode->c, node->c, sizeof(Oid) * (NCHILDREN+2)) ?
00370            "" : "DO NOT ");
00371 #endif
00372 
00373 #ifdef USE_CACHE
00374     if (node_b) {
00375 #ifdef USE_CACHE_TRACE
00376       cout << "writing node cache this=" << this << ", " << node << ", " << getOidString(&oid) << "\n";
00377 #endif
00378       if (idx->stat = objectWriteCache(idx->dbh, 0, node, &oid))
00379         return idx->fatal();
00380 #ifdef USE_CACHE_CHECK
00381       void *xdata = 0;
00382       if (idx->stat = objectReadCache(idx->dbh, 0, &xdata, DefaultLock,
00383                                       &oid))
00384         return idx->fatal();
00385 #ifdef USE_CACHE_TRACE
00386       cout << "xdata = " << xdata << "\n";
00387 #endif
00388       assert(!memcmp(node, xdata, Node::nodeSize(idx)));
00389       if (idx->stat = idx->readNode(node_b, oid))
00390         return idx->fatal();
00391       assert(!memcmp(node, node_b, Node::nodeSize(idx)));
00392 #endif
00393     }
00394     else if (idx->stat = writeNode(node, oid))
00395       return idx->fatal();
00396 
00397     if (keys_b) {
00398 #ifdef USE_CACHE_TRACE
00399       cout << "writing keys cache " << keys_b << "\n";
00400 #endif
00401 #ifdef USE_CACHE_T1
00402       if (idx->stat = objectWrite(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00403         return idx->fatal();
00404 #else
00405       if (idx->stat = objectWriteCache(idx->dbh, 0, keys, &node->keys))
00406         return idx->fatal();
00407 #endif
00408     }
00409     else if (idx->stat = objectWrite(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00410       return idx->fatal();
00411 
00412     if (data_b) {
00413 #ifdef USE_CACHE_TRACE
00414       cout << "writing data cache " << keys_b << "\n";
00415 #endif
00416 #ifdef USE_CACHE_T1
00417       if (idx->stat = objectWrite(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00418         return idx->fatal();
00419 #else
00420       if (idx->stat = objectWriteCache(idx->dbh, 0, data, &node->data))
00421         return idx->fatal();
00422 #endif
00423     }
00424     else if (idx->stat = objectWrite(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00425       return idx->fatal();
00426 
00427 #else
00428 
00429     if (idx->stat = idx->writeNode(node, oid))
00430       return idx->fatal();
00431 
00432     if (idx->stat = objectWrite(idx->dbh, idx->keySize * idx->maxchildren, keys, &node->keys))
00433       return idx->fatal();
00434     if (idx->stat = objectWrite(idx->dbh, idx->dataSize * idx->maxchildren, data, &node->data))
00435       return idx->fatal();
00436 #endif
00437 
00438     return idx->stat;
00439   }
00440 
00441   int
00442   BIdx::InCore::cmp(unsigned i, void const * kIn, void const * dIn,
00443                     unsigned char bswap) const
00444   {
00445     int const r = idx->cmp(k(i), kIn, bswap);
00446     return (r) ? r : memcmp(d(i), dIn, idx->dataSize);
00447   }
00448 
00449   unsigned int BIdx::Node::nodeSize(const BIdx *idx)
00450   {
00451     return sizeof(Node) + idx->maxchildren * sizeof(Oid);
00452   }
00453 
00454   unsigned int BIdx::Node::nodeSize(unsigned int maxchildren)
00455   {
00456     return sizeof(Node) + maxchildren * sizeof(Oid);
00457   }
00458 
00459   BIdx::Node *BIdx::Node::allocNode(BIdx *idx)
00460   {
00461 #ifdef NOMEMZERO
00462     return (Node *)m_malloc(nodeSize(idx));
00463 #else
00464     return (Node *)m_calloc(nodeSize(idx), 1);
00465 #endif
00466   }
00467 
00468   BIdx::Node *BIdx::Node::allocNode(unsigned int degree)
00469   {
00470 #ifdef NOMEMZERO
00471     return (Node *)m_malloc(nodeSize(degree2MaxChildren(degree)));
00472 #else
00473     return (Node *)m_calloc(nodeSize(degree2MaxChildren(degree)), 1);
00474 #endif
00475   }
00476 
00477   BIdx::Node *BIdx::Node::copyNode(BIdx *idx, Node *from)
00478   {
00479     Node *node = allocNode(idx);
00480     memcpy(node, from, nodeSize(idx));
00481     return node;
00482   }
00483 
00484   void BIdx::Node::freeNode(Node *node)
00485   {
00486     ::free(node);
00487   }
00488 }

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