libmoost
/home/mhx/git/github/libmoost/include/moost/kvds/detail/kvds_kch_linux.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 
00029 
00030 
00031 
00032 
00033 #ifndef MOOST_KVDS_KVDSKCH_LINUX_HPP__
00034 #define MOOST_KVDS_KVDSKCH_LINUX_HPP__
00035 
00036 #include <cstdlib>
00037 #include <cstring>
00038 #include <stdexcept>
00039 #include <sstream>
00040 #include <limits>
00041 
00042 #include <boost/scoped_array.hpp>
00043 
00044 #if defined (_STDINT_H)
00045 #define STDINT_H_3C996A98_ABAB_4d71_AC4B_633055150696
00046 #undef _STDINT_H
00047 #endif
00048 
00049 #include <kchashdb.h>
00050 
00051 #ifdef STDINT_H_3C996A98_ABAB_4d71_AC4B_633055150696
00052 #undef STDINT_H_3C996A98_ABAB_4d71_AC4B_633055150696
00053 #if !defined (_STDINT_H)
00054 #define _STDINT_H
00055 #endif
00056 #else
00057 #undef _STDINT_H
00058 #endif
00059 
00060 #include <boost/cast.hpp>
00061 
00062 #include "../ikvds.hpp"
00063 
00064 namespace moost { namespace kvds {
00065 
00066    class KvdsKch : public IKvds
00067    {
00068    public:
00069       typedef kyotocabinet::HashDB store_type;
00070 
00071       KvdsKch() : bOpen_(false), pcursor_(0)
00072       {
00073       }
00074 
00075       ~KvdsKch()
00076       {
00077          try
00078          {
00079             close();
00080          }
00081          catch(...) { /* ignore */ }
00082       }
00083 
00084       void open (char const dsname [], bool newdb = false)
00085       {
00086          if(bOpen_) { throw std::runtime_error("The store is already open"); }
00087 
00088          uint32_t const OMODE = (newdb ? kyotocabinet::HashDB::OTRUNCATE : 0)
00089             | (kyotocabinet::HashDB::OWRITER | kyotocabinet::HashDB::OREADER | kyotocabinet::HashDB::OCREATE);
00090 
00091          bOpen_ = db_.open(dsname, OMODE);
00092 
00093          if(!bOpen_)
00094          {
00095             throw_kch_exception("Failed to open KCH file");
00096          }
00097       }
00098 
00099       void save() { /* nothing to do, fully persisted storage */ }
00100 
00101       void close()
00102       {
00103          release_cursor();
00104 
00105          if(bOpen_)
00106          {
00107             if (!db_.close())
00108                 throw_kch_exception();
00109             bOpen_ = false;
00110          }
00111       }
00112 
00116       store_type & get_store() { return db_; }
00117 
00118    private:
00119       bool set_cursor()
00120       {
00121          release_cursor();
00122          pcursor_ = db_.cursor();
00123          // move to first record if there is one
00124          bool ok = true;
00125          if (!pcursor_->jump())
00126          {
00127             release_cursor();
00128             ok = false;
00129          }
00130          return ok;
00131       }
00132 
00133       void release_cursor()
00134       {
00135          delete pcursor_;
00136          pcursor_ = 0;
00137       }
00138 
00139       void throw_kch_exception(const std::string& msg) const
00140       {
00141          throw std::runtime_error(msg + ": " + db_.error().name());
00142       }
00143 
00144       void throw_kch_exception() const
00145       {
00146          throw_kch_exception("ERROR");
00147       }
00148 
00149       void assert_data_store_open() const
00150       {
00151          assert(bOpen_);
00152       }
00153 
00154    public: // IKvds interface implementation
00155 
00156       bool put(
00157          void const * pkey, size_t const ksize,
00158          void const * pval, size_t const vsize
00159          )
00160       {
00161          assert_data_store_open();
00162          return db_.set(static_cast<const char*>(pkey), ksize, static_cast<const char*>(pval), vsize);
00163       }
00164 
00165       bool get(
00166          void const * pkey, size_t const ksize,
00167          void * pval, size_t & vsize
00168          )
00169       {
00170          assert_data_store_open();
00171 
00172          int32_t const esize = db_.get((char *)pkey, ksize, (char *)pval, vsize);
00173 
00174          bool found = (esize >= 0);
00175 
00176          if(found)
00177          {
00178             vsize = std::min(vsize, (size_t) esize);
00179          }
00180          else { vsize = 0; }
00181 
00182          return found;
00183       }
00184 
00185       bool all(
00186          void const * pkey, size_t const ksize,
00187          void * pval, size_t & vsize
00188          )
00189       {
00190          assert_data_store_open();
00191 
00192          bool found = false;
00193          size_t esize = 0;
00194 
00195          if(siz(pkey, ksize, esize))
00196          {
00197             if(esize <= vsize)
00198             {
00199                found = get(
00200                   pkey, ksize,
00201                   pval, esize
00202                   );
00203             }
00204 
00205             vsize = esize;
00206          }
00207          else { vsize = 0; }
00208 
00209 
00210          return found;
00211       }
00212 
00213       bool add(
00214          void const * pkey, size_t const ksize,
00215          void const * pval, size_t const vsize
00216          )
00217       {
00218          assert_data_store_open();
00219          return db_.append(static_cast<const char*>(pkey), ksize, static_cast<const char*>(pval), vsize);
00220       }
00221 
00222       bool xst(
00223          void const * pkey, size_t const ksize
00224          )
00225       {
00226          size_t size; 
00227          return siz(pkey, ksize, size) > 0;
00228       }
00229 
00230       bool del(
00231          void const * pkey, size_t const ksize
00232          )
00233       {
00234          assert_data_store_open();
00235          return db_.remove(static_cast<const char*>(pkey), ksize);
00236       }
00237 
00238       bool clr()
00239       {
00240          assert_data_store_open();
00241          return db_.clear();
00242       }
00243 
00244       bool beg()
00245       {
00246          assert_data_store_open();
00247          return bOpen_ && set_cursor();
00248       }
00249 
00250       bool nxt(
00251          void * pkey, size_t & ksize
00252          )
00253       {
00254          assert(bOpen_);
00255 
00256          bool found = false;;
00257 
00258          if (pcursor_)
00259          {
00260             size_t size;
00261             boost::scoped_array<char> pk(pcursor_->get_key(&size)); // alloc'd via new []
00262 
00263             if (size <= ksize)
00264             {
00265                memcpy(pkey, pk.get(), size);
00266                found = true;
00267                if (!pcursor_->step())
00268                   release_cursor();
00269             }
00270 
00271             ksize = size;
00272          }
00273          else
00274          {
00275             ksize = 0;
00276          }
00277 
00278          return found;
00279       }
00280 
00281       bool end()
00282       {
00283          return 0 == pcursor_;
00284       }
00285 
00286       bool siz(
00287          void const * pkey, size_t const ksize,
00288          size_t & vsize
00289          )
00290       {
00291          assert_data_store_open();
00292 
00293          boost::scoped_array<char> pval(db_.get(static_cast<const char*>(pkey), ksize, &vsize)); // alloc'd via new []
00294          return (bool)pval; // true if set else false
00295       }
00296 
00297       bool cnt(boost::uint64_t & cnt)
00298       {
00299          assert_data_store_open();
00300          cnt = db_.count();
00301          return cnt < boost::uint64_t(-1);
00302       }
00303 
00304       bool nil(bool & isnil)
00305       {
00306          boost::uint64_t icnt = 0;
00307          bool ok = cnt(icnt);
00308          if(ok) { isnil = (0 == icnt); }
00309          return ok;
00310       }
00311 
00312 private:
00313       store_type db_;
00314       bool bOpen_;
00315       kyotocabinet::HashDB::Cursor* pcursor_;
00316    };
00317 
00318 }}
00319 
00320 #endif // MOOST_KVDS_KVDSKCH_LINUX_HPP__