libmoost
/home/mhx/git/github/libmoost/include/moost/kvds/detail/kvds_tch_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_KVDSTCH_LINUX_HPP__
00034 #define MOOST_KVDS_KVDSTCH_LINUX_HPP__
00035 
00036 #include <cstdlib>
00037 #include <cstring>
00038 #include <stdexcept>
00039 #include <sstream>
00040 #include <limits>
00041 
00042 #if defined (_STDINT_H)
00043 #define STDINT_H_A5C236B9_2336_44a8_AF40_BCA7EA04E940
00044 #undef _STDINT_H
00045 #endif
00046 
00047 #include <tchdb.h>
00048 
00049 #ifdef STDINT_H_A5C236B9_2336_44a8_AF40_BCA7EA04E940
00050 #undef STDINT_H_A5C236B9_2336_44a8_AF40_BCA7EA04E940
00051 #if !defined (_STDINT_H)
00052 #define _STDINT_H
00053 #endif
00054 #else
00055 #undef _STDINT_H
00056 #endif
00057 
00058 #include <boost/cast.hpp>
00059 
00060 #include "../ikvds.hpp"
00061 
00062 namespace moost { namespace kvds {
00063 
00065 
00066    class KvdsTch : public IKvds
00067    {
00068    public:
00069       typedef TCHDB * store_type;
00070 
00071       KvdsTch() :
00072          pdb_(0), bOpen_(false), pitr_(0), pitr_size_(0)
00073       {
00074          pdb_ = tchdbnew();
00075       }
00076 
00077       ~KvdsTch()
00078       {
00079          try
00080          {
00081             close();
00082 
00083             if(pdb_)
00084             {
00085                tchdbdel(pdb_);
00086                pdb_ = 0;
00087             }
00088 
00089             free(pitr_);
00090          }
00091          catch(...) { /* ignore */ }
00092       }
00093 
00094       void open (char const dsname [], bool newdb = false)
00095       {
00096          if(bOpen_) { throw std::runtime_error("The store is already open"); }
00097 
00098          int const OMODE = (newdb ? HDBOTRUNC : 0) | (HDBOWRITER | HDBOREADER | HDBOCREAT);
00099 
00100          bOpen_ = tchdbopen(pdb_, dsname, OMODE);
00101 
00102          if(!bOpen_)
00103          {
00104             throw_tcexception(tchdbecode(pdb_), "Failed to open TCH file");
00105          }
00106       }
00107 
00108       void save() { /* nothihng to do, fully persisted storage */ }
00109 
00110       void close()
00111       {
00112          if(bOpen_ && pdb_)
00113          {
00114             tchdbclose(pdb_);
00115             bOpen_ = false;
00116          }
00117       }
00118 
00122       store_type & get_store() { return pdb_; }
00123 
00124    private:
00125       void assert_data_store_open() const
00126       {
00127          if(!pdb_) { throw std::runtime_error("Datastore is not open"); }
00128       }
00129 
00130       void throw_tcexception(int ecode, char const * msg = "Unexpected error")
00131       {
00132          std::stringstream oss;
00133          oss
00134             << msg << ": " << tchdberrmsg(ecode);
00135 
00136          throw std::runtime_error(oss.str());
00137       }
00138 
00139       void set_next_itr()
00140       {
00141          free(pitr_);
00142          pitr_ =  tchdbiternext(pdb_, &pitr_size_);
00143       }
00144 
00145    public: // IKvds interface implementation
00146 
00147       bool put(
00148          void const * pkey, size_t const ksize,
00149          void const * pval, size_t const vsize
00150          )
00151       {
00152          assert_data_store_open();
00153          return tchdbput(pdb_, pkey, ksize, pval, vsize);
00154       }
00155 
00156       bool get(
00157          void const * pkey, size_t const ksize,
00158          void * pval, size_t & vsize
00159          )
00160       {
00161          assert_data_store_open();
00162 
00163          int const esize = tchdbget3(pdb_, pkey, ksize, pval, boost::numeric_cast<int>(vsize));
00164          bool found = (esize >= 0);
00165 
00166          if(found)
00167          {
00168             vsize = std::min(vsize, (size_t) esize);
00169          }
00170          else
00171          {
00172             vsize = 0;
00173          }
00174 
00175          return found;
00176       }
00177 
00178       bool add(
00179          void const * pkey, size_t const ksize,
00180          void const * pval, size_t const vsize
00181          )
00182       {
00183          assert_data_store_open();
00184          return tchdbputcat(pdb_, pkey, ksize, pval, vsize);
00185       }
00186 
00187       bool all(
00188          void const * pkey, size_t const ksize,
00189          void * pval, size_t & vsize
00190          )
00191       {
00192          assert_data_store_open();
00193 
00194          bool found = false;
00195          size_t esize = 0;
00196 
00197          if(siz(pkey, ksize, esize))
00198          {
00199             if(esize <= vsize)
00200             {
00201                found = get(
00202                   pkey, ksize,
00203                   pval, esize
00204                   );
00205             }
00206 
00207             vsize = esize;
00208          }
00209          else { vsize = 0; }
00210 
00211 
00212          return found;
00213       }
00214 
00215       bool xst(
00216          void const * pkey, size_t const ksize
00217          )
00218       {
00219          size_t size; 
00220          return siz(pkey, ksize, size) > 0;
00221       }
00222 
00223       bool del(
00224          void const * pkey, size_t const ksize
00225          )
00226       {
00227          assert_data_store_open();
00228          return tchdbout(pdb_, pkey, ksize);
00229       }
00230 
00231       bool clr()
00232       {
00233          assert_data_store_open();
00234          return tchdbvanish(pdb_);
00235       }
00236 
00237       bool beg()
00238       {
00239          assert_data_store_open();
00240          bool bOk = tchdbiterinit(pdb_);
00241 
00242          if(bOk)
00243          {
00244             set_next_itr();
00245          }
00246 
00247          return bOk;
00248       }
00249 
00250       bool nxt(
00251          void * pkey, size_t & ksize
00252          )
00253       {
00254          assert_data_store_open();
00255 
00256          bool found = false;;
00257 
00258          if((pitr_) && (pitr_size_ >= 0))
00259          {
00260             size_t const size = pitr_size_;
00261 
00262             if(size <= ksize)
00263             {
00264                memcpy(pkey, pitr_, size);
00265                set_next_itr();
00266                found = true;
00267             }
00268 
00269             ksize = size;
00270          }
00271          else
00272          {
00273             ksize = 0;
00274          }
00275 
00276          return found;
00277       }
00278 
00279       bool end()
00280       {
00281          return 0 == pitr_;
00282       }
00283 
00284       bool siz(
00285          void const * pkey, size_t const ksize,
00286          size_t & vsize
00287          )
00288       {
00289          assert_data_store_open();
00290 
00291          int size = tchdbvsiz(pdb_, pkey, ksize);
00292          bool found = size >= 0;
00293          if(found) { vsize = size; }
00294          return found;
00295       }
00296 
00297       bool cnt(boost::uint64_t & cnt)
00298       {
00299          assert_data_store_open();
00300          cnt = tchdbrnum(pdb_);
00301          return true;
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 pdb_;
00314       bool bOpen_;
00315       void * pitr_;
00316       int pitr_size_;
00317    };
00318 
00319 }}
00320 
00321 #endif // MOOST_KVDS_KVDSTCH_LINUX_HPP__