BIdxBTree.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 <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 //#define ESM_HIDX_REGISTER
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, &reg);
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       BTree tree;
00351       Status s = objectRead(dbh, 0, sizeof tree, &tree,
00352       DefaultLock, 0, &treeOid);
00353       if (s) return s;
00354       unsigned int o_count = tree.count;
00355 
00356       tree.count += inc;
00357       return objectWrite(dbh, 0, sizeof tree, &tree, &treeOid);
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 }

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