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 <unistd.h>
00029 #include <string.h>
00030 #include <stdio.h>
00031
00032 #include <eyedbsm/eyedbsm.h>
00033 #include "BIdxBTree.h"
00034 #include "eyedbsm_p.h"
00035 #include <assert.h>
00036
00037 #include <eyedblib/machtypes.h>
00038 #include <eyedblib/rpc_lib.h>
00039 #include <eyedblib/xdr.h>
00040 #include <eyedblib/strutils.h>
00041
00042 #include <eyedblib/m_mem.h>
00043 #include "lib/m_mem_p.h"
00044
00045 #include <eyedblib/log.h>
00046
00047
00048
00049 namespace eyedbsm {
00050
00051 static void
00052 idx_new_handler()
00053 {
00054 static char message[] = "Ran out of memory\n";
00055 write(2, message, sizeof message - 1);
00056 exit(1);
00057 }
00058
00059 Status BIdx::fatal(Status s)
00060 {
00061 stat = s;
00062 statusPrint(stat, "IDX error real fatal");
00063 return stat;
00064 }
00065
00066 Status BIdx::fatal()
00067 {
00068 Status s = stat;
00069 if (s) {
00070 if (s->err == TRANSACTION_NEEDED ||
00071 s->err == RW_TRANSACTION_NEEDED)
00072 stat = Success;
00073 }
00074 return s;
00075 }
00076
00077 BIdx::BIdx(DbHandle * vh, Oid const &idx,
00078 Boolean (*precmp)(void const * p, void const * q,
00079 KeyType const * type, int & r))
00080 : Idx(True, precmp), stat(Success), dbh(vh), treeOid(idx), free(0),
00081 occupied(0), _keyType(0), tmpnode(0)
00082 {
00083 BTree tree;
00084 if (readBTree(tree))
00085 return;
00086
00087 unsigned int size;
00088 if (fatal(objectSizeGet(dbh, &size, DefaultLock, &tree.type)))
00089 return;
00090 assert(size % sizeof (KeyType) == 0);
00091 _nkeys = size / sizeof (KeyType);
00092 assert(size == _nkeys * sizeof(KeyType));
00093 if (fatal(readKeyType(_keyType, _nkeys, tree.type)))
00094 return;
00095
00096 dataSize = tree.dataSize;
00097 keySize = tree.keySize;
00098 dspid = tree.dspid;
00099 degree = tree.degree;
00100 maxchildren = tree.maxchildren;
00101 count = tree.count;
00102 tmpnode = Node::allocNode(degree);
00103 }
00104
00105 void
00106 BIdx::open(Boolean (*_precmp)(void const * p, void const * q,
00107 KeyType const * type, int & r))
00108 {
00109 precmp = _precmp;
00110 opened = True;
00111 }
00112
00113 #define MAXKEYSIZE 0x1000
00114
00115 static unsigned
00116 calKeySize(Idx::KeyType const p[], unsigned nkeys)
00117 {
00118 unsigned max = 0;
00119 for (; nkeys-- > 0; p++) {
00120 unsigned int r;
00121 if ((int)p->count < 0)
00122 r = ~0;
00123 else
00124 r = p->offset + Idx::typeSize(p->type) * p->count;
00125 if (r > max)
00126 max = r;
00127 }
00128 return max;
00129 }
00130
00131 void
00132 BIdx::kdCopy(void * kO, void * dO, void const * k, void const * d,
00133 unsigned int cnt) const
00134 {
00135 if (cnt > 1) {
00136 memmove(kO, k, keySize * cnt);
00137 memmove(dO, d, dataSize * cnt);
00138 }
00139 else {
00140 memcpy(kO, k, keySize);
00141 memcpy(dO, d, dataSize);
00142 }
00143 }
00144
00145 Status
00146 BIdx::create(unsigned int _degree, unsigned dSize,
00147 KeyType const keyType[], unsigned nkeys,
00148 short _dspid)
00149 {
00150 if (!_degree)
00151 _degree = BIDX_DEF_DEGREE;
00152 assert(nkeys > 0);
00153
00154 if (_degree > 32000) {
00155 stat = statusMake(ERROR, "BTree index: degree too large %u, "
00156 "maximum is 32000", degree);
00157 return fatal();
00158 }
00159
00160 #ifdef ESM_HIDX_REGISTER
00161 registerStart(dbh, AllOP);
00162 #endif
00163 dataSize = dSize;
00164 keySize = calKeySize(keyType, nkeys);
00165 if ((int)keySize >= MAXKEYSIZE) {
00166 stat = statusMake(ERROR, "BTree index: key size is too large %u, "
00167 "maximum is %u", keySize, MAXKEYSIZE);
00168 return fatal();
00169 }
00170
00171 if ((int)keySize < 0) {
00172 stat = statusMake(ERROR,
00173 "BTree index: variable key size is not supported");
00174 return fatal();
00175 }
00176 dspid = _dspid;
00177 degree = _degree;
00178 maxchildren = degree2MaxChildren(degree);
00179 count = 0;
00180
00181 _nkeys = nkeys;
00182 _keyType = new KeyType[_nkeys];
00183 memcpy(_keyType, keyType, _nkeys * sizeof (KeyType));
00184
00185 Node *root = Node::allocNode(degree);
00186 memset(root, 0, sizeof(*root));
00187 if (stat = objectCreate(dbh, 0, keySize * maxchildren, dspid, &root->keys))
00188 return fatal();
00189 if (stat = objectCreate(dbh, 0, dataSize * maxchildren, dspid, &root->data))
00190 return fatal();
00191
00192 root->leaf = 1;
00193 root->n = 0;
00194
00195 BTree btree;
00196 memset(&btree, 0, sizeof(btree));
00197 btree.idxtype = BTreeType;
00198 btree.count = 0;
00199 btree.dspid = dspid;
00200 btree.version = 0;
00201 btree.degree = degree;
00202 btree.maxchildren = maxchildren;
00203 btree.keySize = keySize;
00204 btree.dataSize = dataSize;
00205 tmpnode = Node::allocNode(degree);
00206 if (stat = createNode(root, &btree.root))
00207 return fatal();
00208
00209 Node::freeNode(root);
00210 if (stat = createKeyType(keyType, nkeys, &btree.type))
00211 return fatal();
00212
00213 if (stat = objectCreate(dbh, 0, sizeof btree, dspid, &treeOid))
00214 return fatal();
00215 if (stat = writeBTree(btree))
00216 return fatal();
00217
00218 #ifdef ESM_HIDX_REGISTER
00219 Register *reg;
00220 registerGet(dbh, ®);
00221 fprintf(stdout, "BIdx::create: ");
00222 registerTrace(stdout, reg);
00223 registerEnd(dbh);
00224 #endif
00225 return Success;
00226 }
00227
00228 BIdx::BIdx(DbHandle * vh, Type type, unsigned dSize,
00229 short _dspid, unsigned int _degree)
00230 : Idx(False), stat(Success), dbh(vh), free(0), occupied(0),
00231 _keyType(0), tmpnode(0)
00232 {
00233 IDB_LOG(IDB_LOG_IDX_CREATE,
00234 ("Creating BTree Index: datasz=%u\n", dSize));
00235
00236 KeyType keyType;
00237 keyType.type = type;
00238 keyType.count = 1;
00239 keyType.offset = 0;
00240
00241 create(_degree, dSize, &keyType, 1, _dspid);
00242 count = 0;
00243 if (!stat)
00244 IDB_LOG(IDB_LOG_IDX_CREATE,
00245 ("Have Created BTree Index: treeoid=%s\n",
00246 getOidString(&treeOid)));
00247 }
00248
00249 BIdx::BIdx(DbHandle * vh, unsigned dSize, KeyType const keyType[],
00250 short _dspid, unsigned int _degree, unsigned nkeys)
00251 : Idx(False), stat(Success), dbh(vh), free(0), occupied(0),
00252 _keyType(0), tmpnode(0)
00253 {
00254 create(_degree, dSize, keyType, nkeys, _dspid);
00255 count = 0;
00256 Node::freeNode(tmpnode);
00257 tmpnode = Node::allocNode(degree);
00258 }
00259
00260 int
00261 BIdx::cmp(void const * p, void const * q, unsigned char swap)
00262 {
00263 int r;
00264 for (unsigned i = 0; i < _nkeys; i++) {
00265 if (r = compare(p, q, &_keyType[i], swap))
00266 return r;
00267 }
00268 return 0;
00269 }
00270
00271 unsigned int
00272 BIdx::getCount() const
00273 {
00274 BTree tree;
00275 if (!readBTree(tree))
00276 return tree.count;
00277 return 0;
00278 }
00279
00280 short
00281 BIdx::getDefaultDspid() const
00282 {
00283 BTree tree;
00284 if (!readBTree(tree))
00285 return tree.dspid;
00286 return -1;
00287 }
00288
00289 void
00290 BIdx::setDefaultDspid(short _dspid)
00291 {
00292 BTree tree;
00293 if (!readBTree(tree)) {
00294 tree.dspid = _dspid;
00295 writeBTree(tree);
00296 }
00297 }
00298
00299 static void
00300 add(Oid *&oids, unsigned int &cnt, unsigned int &alloc_cnt,
00301 const Oid &oid)
00302 {
00303 if (cnt >= alloc_cnt) {
00304 alloc_cnt = cnt + 32;
00305 oids = (Oid *)m_realloc(oids, alloc_cnt * sizeof(Oid));
00306 }
00307
00308 oids[cnt++] = oid;
00309 }
00310
00311 static Status
00312 getObjects(const BIdx *idx, Oid *&oids, unsigned int &cnt,
00313 unsigned int &alloc_cnt, const Oid &oid)
00314 {
00315 Status s;
00316 BIdx::InCore x(const_cast<BIdx *>(idx));
00317 if (s = x.read(&oid))
00318 return s;
00319
00320 add(oids, cnt, alloc_cnt, x.node->keys);
00321 add(oids, cnt, alloc_cnt, x.node->data);
00322 add(oids, cnt, alloc_cnt, oid);
00323
00324 if (!x.node->leaf)
00325 for (unsigned i = 0; i <= x.node->n; i++)
00326 if (s = getObjects(idx, oids, cnt, alloc_cnt, x.node->c[i]))
00327 return s;
00328
00329 return Success;
00330 }
00331
00332 Status
00333 BIdx::getObjects(Oid *&oids, unsigned int &cnt) const
00334 {
00335 unsigned int alloc_cnt = 0;
00336 cnt = 0;
00337 oids = 0;
00338 BTree tree;
00339 Status s = readBTree(tree);
00340 if (s) return s;
00341 add(oids, cnt, alloc_cnt, treeOid);
00342 add(oids, cnt, alloc_cnt, tree.type);
00343 return eyedbsm::getObjects(this, oids, cnt, alloc_cnt, tree.root);
00344 }
00345
00346 Status
00347 BIdx::count_manage(int inc)
00348 {
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 count += inc;
00361 unsigned int xcount = h2x_u32(count);
00362 return objectWrite(dbh, sizeof(unsigned int), sizeof count, &xcount,
00363 &treeOid);
00364 }
00365
00366 unsigned int
00367 BIdx::getMagOrder(unsigned int degree)
00368 {
00369 if (degree <= 128)
00370 return 100000;
00371 if (degree <= 256)
00372 return 1000000;
00373
00374 return 10000000;
00375 }
00376
00377 unsigned int
00378 BIdx::getDegree(unsigned int magorder)
00379 {
00380 if (magorder <= 100000)
00381 return 128;
00382 if (magorder <= 1000000)
00383 return 256;
00384
00385 return 512;
00386 }
00387
00388 std::string
00389 BIdx::Stats::toString() const
00390 {
00391 std::string s;
00392
00393 s = std::string("Degree: ") + str_convert((long)idx->getDegree()) + "\n";
00394 s += std::string("Data Size: ") + str_convert((long)idx->getDataSize()) + "\n";
00395 s += std::string("Key Size: ") + str_convert((long)idx->getKeySize()) + "\n";
00396 s += std::string("Key Type: ") + typeString((Idx::Type)keyType) + "\n";
00397 s += std::string("Key Offset: ") + str_convert((long)keyOffset) + "\n";
00398 s += std::string("Total Object Count: ") + str_convert((long)total_object_count) + "\n";
00399 s += std::string("Total Btree Object Count: ") + str_convert((long)total_btree_object_count) + "\n";
00400 s += std::string("Total Btree Node Count: ") + str_convert((long)total_btree_node_count) + "\n";
00401 s += std::string("Btree Node Size: ") + str_convert((long)btree_node_size) + "\n";
00402 s += std::string("Btree Key Object Size: ") + str_convert((long)btree_key_object_size) + "\n";
00403 s += std::string("Btree Data Object Size: ") + str_convert((long)btree_data_object_size) + "\n";
00404 s += std::string("Total Btree Object Size: ") + str_convert(total_btree_object_size) + "\n";
00405 return s;
00406 }
00407
00408 Status
00409 BIdx::copy_realize(Idx *idx) const
00410 {
00411 Status s = Success;
00412 BIdxCursor curs(const_cast<BIdx *>(this));
00413 unsigned char *data = new unsigned char[dataSize];
00414
00415 for (;;) {
00416 Boolean found;
00417 Idx::Key key;
00418
00419 s = curs.next(&found, data, &key);
00420 if (s) goto error;
00421
00422 if (!found) break;
00423
00424 s = idx->insert(key.getKey(), data);
00425 if (s) goto error;
00426 }
00427
00428 error:
00429 delete [] data;
00430 return s;
00431 }
00432
00433 Status BIdx::move(short dspid, eyedbsm::Oid &newoid)
00434 {
00435 return reimplementToBTree(newoid, degree, dspid);
00436 }
00437
00438 Status
00439 BIdx::reimplementToHash(Oid &newoid, int key_count, int mag_order,
00440 short _dspid,
00441 const int *impl_hints,
00442 unsigned int impl_hints_cnt,
00443 hash_key_t hash_key,
00444 void *hash_data,
00445 KeyType *ktype)
00446 {
00447 HIdx hidx(dbh, (ktype ? *ktype : *_keyType), dataSize,
00448 (_dspid == DefaultDspid ? dspid : _dspid),
00449 mag_order,
00450 key_count,
00451 impl_hints, impl_hints_cnt);
00452 Status s = hidx.status();
00453 if (s) return s;
00454
00455 hidx.open();
00456 s = copy_realize(&hidx);
00457 if (s) return s;
00458 newoid = hidx.oid();
00459 return destroy();
00460 }
00461
00462 Status
00463 BIdx::reimplementToBTree(Oid &newoid, int _degree, short _dspid)
00464 {
00465 if (!_degree)
00466 _degree = BIDX_DEF_DEGREE;
00467 if (_dspid == DefaultDspid)
00468 _dspid = dspid;
00469
00470 if (_degree == degree && _dspid == dspid) {
00471 newoid = treeOid;
00472 return Success;
00473 }
00474
00475 BIdx bidx(dbh, dataSize, _keyType, _dspid, _degree, _nkeys);
00476
00477 Status s = bidx.status();
00478 if (s) return s;
00479
00480 s = copy_realize(&bidx);
00481 if (s) return s;
00482
00483 newoid = bidx.oid();
00484 return destroy();
00485 }
00486
00487 void
00488 BIdx::Stats::trace(FILE *fd) const
00489 {
00490 fprintf(fd, toString().c_str());
00491 }
00492
00493 Status
00494 BIdx::getStats(std::string& stats) const
00495 {
00496 Stats st;
00497 Status s = getStats(st);
00498 if (s) return s;
00499 stats = st.toString();
00500 return Success;
00501 }
00502
00503 Status
00504 BIdx::getStats(BIdx::Stats &stats) const
00505 {
00506 stats.idx = this;
00507 stats.keyType = _keyType[0].type;
00508 stats.keyOffset = _keyType[0].offset;
00509 stats.total_object_count = getCount();
00510
00511 Oid *oids = 0;
00512 Status s = getObjects(oids, stats.total_btree_object_count);
00513 delete [] oids;
00514 if (s) return s;
00515
00516 stats.total_btree_node_count = (stats.total_btree_object_count - 2) / 3;
00517 stats.btree_node_size = Node::nodeSize(this);
00518 stats.btree_key_object_size = dataSize * maxchildren;
00519 stats.btree_data_object_size = keySize * maxchildren;
00520
00521 stats.total_btree_object_size = sizeof(BTree) + sizeof(KeyType) * _nkeys +
00522 (stats.btree_key_object_size +
00523 stats.btree_data_object_size +
00524 stats.btree_node_size) * stats.total_btree_node_count;
00525
00526 return Success;
00527 }
00528 }