Idx.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   Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #include <eyedblib/thread.h>
00027 #include <eyedbsm/eyedbsm.h>
00028 #include <eyedbsm/Idx.h>
00029 #include <stdlib.h>
00030 #include <eyedblib/xdr.h>
00031 #include <eyedbsm/xdr.h>
00032 #include <assert.h>
00033 
00034 #include <iostream>
00035 #include <eyedblib/log.h>
00036 #include <eyedblib/machtypes.h>
00037 #include <eyedblib/rpc_lib.h>
00038 #include <eyedblib/m_mem.h>
00039 #include "lib/m_mem_p.h"
00040 
00041 #include <fstream>
00042 
00043 namespace eyedbsm {
00044 
00045   Idx::Idx(Boolean _opened,
00046            Boolean (*_precmp)(void const * p, void const * q,
00047                               KeyType const * type, int & r))
00048   {
00049     opened = _opened;
00050     precmp = _precmp;
00051   }
00052 
00053   Status
00054   Idx::make(DbHandle *dbh, const Oid &oid, Idx *&idx)
00055   {
00056     unsigned int idxtype;
00057     idx = 0;
00058     Status s = objectRead(dbh, 0, sizeof(unsigned int), &idxtype,
00059                           DefaultLock, 0, 0, &oid);
00060     if (s) return s;
00061 
00062     idxtype = x2h_u32(idxtype);
00063 
00064     if (idxtype == HashType) {
00065       idx = new HIdx(dbh, &oid);
00066       return Success;
00067     }
00068 
00069     if (idxtype == BTreeType) {
00070       idx = new BIdx(dbh, oid);
00071       return Success;
00072     }
00073 
00074     return statusMake(ERROR, "object %s is not a valid index [%x]",
00075                       getOidString(&oid), idxtype);
00076   }
00077 
00078   Status
00079   Idx::checkOpened() const
00080   {
00081     if (!opened)
00082       return statusMake(ERROR, "index %s is not opened",
00083                         getOidString(&oid()));
00084     return Success;
00085   }
00086 
00087   Idx::Key::Key(int sz)
00088   {
00089     size = sz;
00090     key = (size ? m_malloc(size) : 0);
00091   }
00092 
00093   void Idx::Key::setKey(void *k, int sz, const KeyType &keyType)
00094   {
00095 #if 1
00096     Boolean no_x2h;
00097     if (sz < 0) {no_x2h = True; sz = -sz;}
00098     else no_x2h = False;
00099 #endif
00100     if (sz > size) {
00101       free(key);
00102       size = sz;
00103       key = m_malloc(sz);
00104       assert(key);
00105     }
00106 
00107 #if 1
00108     if (no_x2h)
00109       memcpy(key, k, sz);
00110     else
00111 #endif
00112       x2h(key, k, keyType, sz);
00113   }
00114 
00115   Idx::Key::~Key()
00116   {
00117     free(key);
00118   }
00119 
00120   unsigned int
00121   Idx::computeCount()
00122   {
00123     IdxCursor *curs;
00124 
00125     if (asHIdx())
00126       curs = new HIdxCursor(asHIdx(), 0, 0, False, False);
00127     else
00128       curs = new BIdxCursor(asBIdx(), 0, 0, False, False);
00129 
00130     unsigned int count = 0;
00131 
00132     for (;;)
00133       {
00134         Boolean found;
00135         Oid oid;
00136         curs->next(&found, &oid, 0);
00137 
00138         if (!found)
00139           break;
00140 
00141         count++;
00142       }
00143 
00144     delete curs;
00145     return count;
00146   }
00147 
00148   using namespace std;
00149 
00150   static ofstream DEVNULL("/dev/null");
00151 
00152 #define mkcmp(type, x2h) \
00153 inline static int \
00154 cmp(type const * p, type const * q, unsigned i, unsigned char bswap) \
00155 { \
00156         for (; i-- > 0; p++, q++) { \
00157                 type _p, _q; \
00158                 eyedblib_mcp(&_p, p, sizeof(_p)); \
00159                 eyedblib_mcp(&_q, q, sizeof(_q)); \
00160                 if (bswap & OP1_SWAP) _p = x2h(_p); \
00161                 if (bswap & OP2_SWAP) _q = x2h(_q); \
00162                 if (_p > _q) \
00163                         return 1; \
00164                 else if (_p < _q) \
00165                         return -1; \
00166         } \
00167         return 0; \
00168 }
00169 
00170   mkcmp(unsigned char, x2h_nop)
00171     mkcmp(signed char, x2h_nop)
00172     mkcmp(eyedblib::int16, x2h_16)
00173     mkcmp(eyedblib::uint16, x2h_u16)
00174     mkcmp(eyedblib::int32, x2h_32)
00175     mkcmp(eyedblib::uint32, x2h_u32)
00176     mkcmp(eyedblib::int64, x2h_64)
00177     mkcmp(eyedblib::uint64, x2h_u64)
00178     mkcmp(eyedblib::float32, x2h_f32)
00179     mkcmp(eyedblib::float64, x2h_f64)
00180     //mkcmp(Oid)
00181 #undef mkcmp
00182 
00183 
00184     static inline void const *
00185   fpos_(void const * p, int offset)
00186   {
00187     return (char const *)p + offset;
00188   }
00189 
00190   static inline void *
00191   fpos_(void * p, int offset)
00192   {
00193     return (char *)p + offset;
00194   }
00195 
00196   //
00197   // Improvment?
00198   // is this switch really necessary !?
00199   // in fact, yes! Because comparison is not bit per bit comparison but a
00200   // typed comparison: 'x < y' has not the same implementation for float or int
00201   //
00202 
00203   static Boolean offset_cmp = getenv("EYEDBNOIDXOFF") ? True : False;
00204 
00205   int
00206   Idx::compare(void const * p, void const * q, KeyType const * type,
00207                unsigned char bswap) const
00208   {
00209     // EV: added 13/12/01
00210     if (!offset_cmp && precmp) {
00211       int r;
00212       if (precmp(p, q, type, r))
00213         return r;
00214     }
00215     // end added
00216 
00217     p = fpos_(p, type->offset);
00218     q = fpos_(q, type->offset);
00219 
00220     switch (type->type)
00221       {
00222       case tChar:
00223         return memcmp(p, q, type->count);
00224 
00225       case tInt32:
00226         return cmp((eyedblib::int32 const *)p, (eyedblib::int32 const *)q, type->count, bswap);
00227 
00228       case tInt64:
00229         return cmp((eyedblib::int64 const *)p, (eyedblib::int64 const *)q, type->count, bswap);
00230 
00231       case tInt16:
00232         return cmp((eyedblib::int16 const *)p, (eyedblib::int16 const *)q, type->count, bswap);
00233 
00234       case tFloat32:
00235         return cmp((eyedblib::float32 const *)p, (eyedblib::float32 const *)q, type->count, bswap);
00236 
00237       case tFloat64:
00238         return cmp((eyedblib::float64 const *)p, (eyedblib::float64 const *)q, type->count, bswap);
00239 
00240       case tSignedChar:
00241         return cmp((signed char const *)p, (signed char const *)q, type->count, bswap);
00242 
00243       case tUnsignedChar:
00244         return cmp((unsigned char const *)p, (unsigned char const *)q, type->count, bswap);
00245 
00246       case tUnsignedInt16:
00247         return cmp((eyedblib::uint16 const *)p, (eyedblib::uint16 const *)q, type->count, bswap);
00248 
00249       case tUnsignedInt32:
00250         return cmp((eyedblib::uint32 const *)p, (eyedblib::uint32 const *)q, type->count, bswap);
00251 
00252       case tUnsignedInt64:
00253         return cmp((eyedblib::uint64 const *)p, (eyedblib::uint64 const *)q, type->count, bswap);
00254 
00255       case tOid:
00256         if (!bswap)
00257           return memcmp(p, q, type->count * sizeof(Oid));
00258         else {
00259           assert(type->count == 1);
00260           Oid poid, qoid;
00261           eyedblib_mcp(&poid, p, sizeof(poid));
00262           eyedblib_mcp(&qoid, q, sizeof(qoid));
00263           if (bswap & OP1_SWAP) x2h_oid(&poid, &poid);
00264           if (bswap & OP2_SWAP) x2h_oid(&qoid, &qoid);
00265           return memcmp(&poid, &qoid, sizeof(Oid));
00266         }
00267 
00268       case tString:
00269         return strncmp((char const *)p, (char const *)q, type->count);
00270 
00271       default:
00272         assert(0);
00273       }
00274     return 0;
00275   }
00276 
00277   void
00278   Idx::h2x(void *xkey, const void *hkey, const KeyType &type)
00279   {
00280     if (type.offset)
00281       memcpy((char *)xkey, (char *)hkey, type.offset);
00282 
00283     xkey = fpos_(xkey, type.offset);
00284     hkey = fpos_(hkey, type.offset);
00285     //printf("h2x(%s[%d])\n", typeString(type.type), type.count);
00286 
00287     switch (type.type)
00288       {
00289       case tInt32:
00290       case tFloat32:
00291       case tUnsignedInt32:
00292         h2x_32_cpy(xkey, hkey);
00293         break;
00294 
00295       case tInt64:
00296       case tFloat64:
00297       case tUnsignedInt64:
00298         h2x_64_cpy(xkey, hkey);
00299         break;
00300 
00301       case tInt16:
00302       case tUnsignedInt16:
00303         h2x_16_cpy(xkey, hkey);
00304         break;
00305 
00306       case tOid:
00307         {
00308           Oid hoid;
00309           memcpy(&hoid, hkey, sizeof(hoid));
00310           h2x_oid((Oid *)xkey, &hoid); // 2nd arg need to be aligned !
00311         }
00312         break;
00313 
00314       default:
00315         printf("ERROR TYPE = %d\n", type.type);
00316         assert(0);
00317       }
00318   }
00319 
00320   void
00321   Idx::x2h(void *hkey, const void *xkey, const KeyType &type,
00322            unsigned int size)
00323   {
00324     if (type.offset)
00325       memcpy((char *)hkey, (char *)xkey, type.offset);
00326 
00327     hkey = fpos_(hkey, type.offset);
00328     xkey = fpos_(xkey, type.offset);
00329     //printf("x2h(%s[%d])+%d\n", typeString(type.type), type.count, type.offset);
00330 
00331     Oid hoid;
00332     switch (type.type)
00333       {
00334       case tInt32:
00335       case tFloat32:
00336       case tUnsignedInt32:
00337         x2h_32_cpy(hkey, xkey);
00338         break;
00339 
00340       case tInt64:
00341       case tFloat64:
00342       case tUnsignedInt64:
00343         x2h_64_cpy(hkey, xkey);
00344         break;
00345 
00346       case tInt16:
00347       case tUnsignedInt16:
00348         x2h_16_cpy(hkey, xkey);
00349         break;
00350 
00351       case tOid:
00352         x2h_oid(&hoid, (const Oid *)xkey); // 1st arg need to be aligned !
00353         memcpy(hkey, &hoid, sizeof(hoid));
00354         break;
00355 
00356       default:
00357         memcpy(hkey, xkey, size - type.offset);
00358         break;
00359       }
00360   }
00361 
00362   const char *
00363   Idx::typeString(Type type)
00364   {
00365     switch (type) {
00366     case tChar:
00367       return "tChar";
00368 
00369     case tUnsignedChar:
00370       return "tUnsignedChar";
00371 
00372     case tSignedChar:
00373       return "tSignedChar";
00374 
00375     case tInt16:
00376       return "tInt16";
00377 
00378     case tUnsignedInt16:
00379       return "tUnsignedInt16";
00380 
00381     case tInt32:
00382       return "tInt32";
00383 
00384     case tUnsignedInt32:
00385       return "tUnsignedInt32";
00386 
00387     case tInt64:
00388       return "tInt64";
00389 
00390     case tUnsignedInt64:
00391       return "tUnsignedInt64";
00392 
00393     case tFloat32:
00394       return "tFloat32";
00395 
00396     case tFloat64:
00397       return "tFloat64";
00398 
00399     case tOid:
00400       return "tOid";
00401 
00402     case tString:
00403       return "tString";
00404 
00405     default:
00406       fprintf(stderr, "%s line %d: unknown index type %d\n", __FILE__, __LINE__, int(type));
00407       abort();
00408       return 0;
00409     }
00410   }
00411 
00412   size_t
00413   Idx::typeSize(Type type)
00414   {
00415     switch (type) {
00416     case tChar:
00417       return sizeof(char);
00418 
00419     case tUnsignedChar:
00420       return sizeof(unsigned char);
00421 
00422     case tSignedChar:
00423       return sizeof(signed char);
00424 
00425     case tInt16:
00426       return sizeof(eyedblib::int16);
00427 
00428     case tUnsignedInt16:
00429       return sizeof(eyedblib::uint16);
00430 
00431     case tInt32:
00432       return sizeof(eyedblib::int32);
00433 
00434     case tUnsignedInt32:
00435       return sizeof(eyedblib::uint32);
00436 
00437     case tInt64:
00438       return sizeof(eyedblib::int64);
00439 
00440     case tUnsignedInt64:
00441       return sizeof(eyedblib::uint64);
00442 
00443     case tFloat32:
00444       return sizeof(eyedblib::float32);
00445 
00446     case tFloat64:
00447       return sizeof(eyedblib::float64);
00448 
00449     case tOid:
00450       return sizeof(Oid);
00451 
00452     case tString:
00453       return sizeof(char);
00454       /*
00455         fprintf(stderr, "%s line %d: not yet supported string type in index\n", __FILE__, __LINE__);
00456         abort();
00457         return 0;
00458       */
00459 
00460     default:
00461       fprintf(stderr, "%s line %d: unknown index type %d\n", __FILE__, __LINE__, int(type));
00462       abort();
00463       return 0;
00464     }
00465   }
00466 
00467   void DataBuffer::setData(void *_data, unsigned int _datasz)
00468   {
00469     static const unsigned int INCRSZ = 512;
00470     datasz = _datasz;
00471 
00472     if (datasz > allocsz) {
00473       allocsz = datasz + INCRSZ;
00474       delete [] data;
00475       data = new unsigned char[allocsz];
00476     }
00477 
00478     memcpy(data, _data, datasz);
00479   }
00480 }

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