libmoost
|
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__