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 <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
00039
00040
00041
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
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
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
00222
00223
00224 node = Node::allocNode(idx);
00225 node->leaf = 2;
00226 node->n = b->maxchildren + 2;
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
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)
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)
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)
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
00353
00354
00355
00356
00357
00358
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 }