libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 00029 00030 00031 00032 00033 00034 00035 00040 00041 #include <cstdlib> 00042 #include <cstring> 00043 #include <stdexcept> 00044 #include <fstream> 00045 #include <vector> 00046 #include <map> 00047 00048 #include <boost/type_traits.hpp> 00049 #include <boost/static_assert.hpp> 00050 #include <boost/cast.hpp> 00051 00052 #include "ikvds.hpp" 00053 00054 #ifndef MOOST_KVDS_KVDSMEM_HPP__ 00055 #define MOOST_KVDS_KVDSMEM_HPP__ 00056 00057 namespace moost { namespace kvds { 00058 00059 typedef std::vector<char> byte_array_t; 00060 00062 00063 template <typename T> 00064 class KvdsMem : public IKvds 00065 { 00066 public: 00067 typedef T store_type; 00068 typedef typename T::key_type key_type; 00069 typedef typename T::mapped_type val_type; 00070 00071 KvdsMem() : itr_(store_.end()){} 00072 ~KvdsMem() 00073 { 00074 if(!dsname_.empty()) 00075 { 00076 close(); 00077 } 00078 } 00079 00080 void open (char const dsname [], bool newdb = false) 00081 { 00082 if(!dsname_.empty()) { throw std::runtime_error("The store is already open"); } 00083 00084 dsname_ = dsname; 00085 00086 if(newdb) 00087 { 00088 // Truncate database if it already exists 00089 std::ofstream(dsname_.c_str(), std::ios::binary | std::ios::trunc); 00090 } 00091 else 00092 { 00093 std::ifstream in(dsname_.c_str(), std::ios::binary); 00094 in.exceptions(std::ios::badbit); 00095 00096 try 00097 { 00098 if(in.is_open()) // Failure to open is fine, this could be a new store 00099 { 00100 key_type key; 00101 00102 while(in) 00103 { 00104 size_t key_size = 0; 00105 in.read(reinterpret_cast<char *>(&key_size), sizeof(key_size)); 00106 00107 if(key_size > 0) 00108 { 00109 key.resize(key_size / sizeof(typename key_type::value_type)); 00110 in.read(reinterpret_cast<char *>(&key[0]), boost::numeric_cast<std::streamsize>(key_size)); 00111 00112 size_t val_size = 0; 00113 in.read(reinterpret_cast<char *>(&val_size), sizeof(val_size)); 00114 00115 if(val_size > 0) 00116 { 00117 val_type & val = store_[key]; 00118 val.resize(val_size / sizeof(typename val_type::value_type)); 00119 00120 if(in) 00121 { 00122 in.read(reinterpret_cast<char *>(&val[0]), boost::numeric_cast<std::streamsize>(val_size)); 00123 } 00124 } 00125 } 00126 } 00127 } 00128 } 00129 catch(...) 00130 { 00131 dsname_.clear(); // On close, ensure we don't save bad data and cause potential corruption! 00132 throw; 00133 } 00134 } 00135 } 00136 00137 00138 void save() 00139 { 00140 if(!dsname_.empty()) 00141 { 00142 std::ofstream out(dsname_.c_str(), std::ios::binary); 00143 out.exceptions(std::ios::badbit | std::ios::failbit); 00144 00145 for(typename store_type::const_iterator itr = store_.begin() ; itr != store_.end() ; ++itr) 00146 { 00147 size_t key_size = itr->first.size(); 00148 out.write(reinterpret_cast<char const *>(&key_size), sizeof(key_size)); 00149 out.write(reinterpret_cast<char const *>(&itr->first[0]), boost::numeric_cast<std::streamsize>(key_size)); 00150 00151 size_t val_size = itr->second.size(); 00152 out.write(reinterpret_cast<char const *>(&val_size), sizeof(val_size)); 00153 out.write(reinterpret_cast<char const *>(&itr->second[0]), boost::numeric_cast<std::streamsize>(val_size)); 00154 } 00155 00156 dsname_.clear(); 00157 } 00158 } 00159 00160 void close() 00161 { 00162 save(); 00163 } 00164 00165 private: 00166 std::string dsname_; 00167 00168 private: 00170 BOOST_STATIC_ASSERT((boost::is_same<key_type, byte_array_t>::value)); 00171 BOOST_STATIC_ASSERT((boost::is_same<val_type, byte_array_t>::value)); 00172 00173 public: 00177 store_type & get_store() { return store_; } 00178 00179 public: 00180 bool put( 00181 void const * pkey, size_t const ksize, 00182 void const * pval, size_t const vsize 00183 ) 00184 { 00185 key_type key(ksize); 00186 memcpy (&key[0], pkey, ksize); 00187 00188 val_type & vt = store_[key]; 00189 00190 vt.resize(vsize); 00191 memcpy (&vt[0], pval, vsize); 00192 00193 return true; 00194 } 00195 00196 bool get( 00197 void const * pkey, size_t const ksize, 00198 void * pval, size_t & vsize 00199 ) 00200 { 00201 key_type key(ksize); 00202 memcpy (&key[0], pkey, ksize); 00203 00204 typename store_type::const_iterator itr = store_.find(key); 00205 00206 bool found = itr != store_.end(); 00207 00208 if(found) 00209 { 00210 vsize = std::min(vsize, itr->second.size()); 00211 memcpy(pval, &itr->second[0], vsize); 00212 } 00213 else { vsize = 0; } 00214 00215 return found; 00216 } 00217 00218 bool add( 00219 void const * pkey, size_t const ksize, 00220 void const * pval, size_t const vsize 00221 ) 00222 { 00223 key_type key(ksize); 00224 memcpy (&key[0], pkey, ksize); 00225 00226 val_type & vt = store_[key]; 00227 00228 size_t const osize = vt.size(); 00229 vt.resize(osize + vsize); 00230 memcpy (&vt[osize], pval, vsize); 00231 00232 return true; 00233 } 00234 00235 bool all( 00236 void const * pkey, size_t const ksize, 00237 void * pval, size_t & vsize 00238 ) 00239 { 00240 bool found = false; 00241 size_t esize = 0; 00242 00243 if(siz(pkey, ksize, esize)) 00244 { 00245 if(esize <= vsize) 00246 { 00247 found = get( 00248 pkey, ksize, 00249 pval, esize 00250 ); 00251 } 00252 00253 vsize = esize; 00254 } 00255 else { vsize = 0; } 00256 00257 return found; 00258 } 00259 00260 bool xst( 00261 void const * pkey, size_t const ksize 00262 ) 00263 { 00264 key_type key(ksize); 00265 memcpy (&key[0], pkey, ksize); 00266 return store_.find(key) != store_.end(); 00267 } 00268 00269 bool del( 00270 void const * pkey, size_t const ksize 00271 ) 00272 { 00273 bool removed = false; 00274 00275 key_type key(ksize); 00276 memcpy (&key[0], pkey, ksize); 00277 00278 typename store_type::iterator itr = store_.find(key); 00279 00280 if(itr != store_.end()) 00281 { 00282 store_.erase(itr); 00283 removed = true; 00284 } 00285 00286 return removed; 00287 } 00288 00289 bool clr() 00290 { 00291 store_.clear(); 00292 return true; 00293 } 00294 00295 bool beg() 00296 { 00297 itr_ = store_.begin(); 00298 return true; 00299 } 00300 00301 bool nxt( 00302 void * pkey, size_t & ksize 00303 ) 00304 { 00305 bool found = false; 00306 00307 if(itr_ != store_.end()) 00308 { 00309 size_t const size = itr_->first.size(); 00310 00311 if(size <= ksize) 00312 { 00313 memcpy(pkey, &itr_->first[0], size); 00314 ++itr_; 00315 found = true; 00316 } 00317 00318 ksize = size; 00319 } 00320 else 00321 { 00322 ksize = 0; 00323 } 00324 00325 return found; 00326 } 00327 00328 bool end() 00329 { 00330 return itr_ == store_.end(); 00331 } 00332 00333 bool siz( 00334 void const * pkey, size_t const ksize, 00335 size_t & vsize 00336 ) 00337 00338 { 00339 key_type key(ksize); 00340 memcpy (&key[0], pkey, ksize); 00341 00342 typename store_type::const_iterator itr = store_.find(key); 00343 00344 bool found = itr != store_.end(); 00345 00346 if(itr != store_.end()) 00347 { 00348 vsize = itr->second.size(); 00349 } 00350 00351 return found; 00352 } 00353 00354 bool cnt(boost::uint64_t & cnt) 00355 { 00356 cnt = store_.size(); 00357 return true; 00358 } 00359 00360 bool nil(bool & isnil) 00361 { 00362 isnil = store_.empty(); 00363 return true; 00364 } 00365 00366 private: 00367 store_type store_; 00368 typename store_type::const_iterator itr_; 00369 00370 }; 00371 00373 typedef KvdsMem<std::map<byte_array_t, byte_array_t> > KvdsMemMap; 00374 00375 }} 00376 00377 #endif /// MOOST_KVDS_KVDSMEM_HPP__