libmoost
/home/mhx/git/github/libmoost/include/moost/kvds/kvds.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 
00029 #include <cassert>
00030 #include <stdexcept>
00031 #include <vector>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 
00035 #include "ikvds.hpp"
00036 #include "kvds_integral_type.hpp"
00037 
00038 #ifndef MOOST_KVDS_KVDS_HPP__
00039 #define MOOST_KVDS_KVDS_HPP__
00040 
00041 namespace moost { namespace kvds {
00042 
00043    typedef boost::shared_ptr<IKvds> ikvds_ptr_t;
00044 
00050 
00052 
00054 
00055    template <
00056       typename keyT, // the type of the key
00057       typename valT, // the type of the value
00058 
00059       // policy for serialising the key -- default is to treat it as an integeral type
00060       template <typename> class KvdsTypeKey = KvdsIntegralType,
00061 
00062       // policy for serialising the value -- default is to treat it as an integeral type
00063       template <typename> class KvdsTypeVal = KvdsIntegralType
00064    >
00065    class Kvds
00066    {
00067       template <typename kvdsT> friend class KvdsKeyIterator;
00068 
00069    public:
00070       typedef keyT key_type;
00071       typedef valT val_type;
00072       typedef std::vector<val_type> kvds_values_t;
00073 
00075       typedef std::pair<key_type, val_type> value_type;
00076       typedef val_type data_type;
00077 
00078    private:
00079       typedef KvdsTypeKey<key_type> kvds_key_t;
00080       typedef KvdsTypeVal<val_type> kvds_val_t;
00081       typedef KvdsTypeKey<key_type const> kvds_key_const_t;
00082       typedef KvdsTypeVal<val_type const> kvds_val_const_t;
00083 
00084    public:
00085       Kvds(ikvds_ptr_t ikvds_ptr) :
00086          ikvds_ptr_(ikvds_ptr)
00087          {
00088             assert(ikvds_ptr_); // catch it in debug!
00089             if(!ikvds_ptr_) { throw std::runtime_error("Datastore cannot be initialised with a null ikvds"); }
00090          }
00091 
00092          bool put(kvds_key_const_t const & key, kvds_val_const_t const & val) const
00093          {
00094             return ikvds_ptr_->put(
00095                &key, key.size(),
00096                &val, val.size()
00097                );
00098          }
00099 
00100          bool put(kvds_key_const_t const & key, kvds_values_t const & vals) const
00101          {
00102             typename kvds_val_const_t::vector_type kvds_val_vector(vals);
00103 
00104             return ikvds_ptr_->put(
00105                &key, key.size(),
00106                &kvds_val_vector, kvds_val_vector.size()
00107                );
00108          }
00109 
00110          bool get(kvds_key_const_t const & key, kvds_val_t val) const
00111          {
00112             bool found = ikvds_ptr_->get(
00113                &key, key.size(),
00114                &val, val.size()
00115                );
00116 
00117             *val; // Reassemble val
00118 
00119             return found;
00120          }
00121 
00122          bool get(kvds_key_const_t const & key, kvds_values_t & vals, size_t const count) const
00123          {
00124             vals.resize(count);
00125             typename kvds_val_t::vector_type kvds_val_vector(vals);
00126 
00127             size_t esize = kvds_val_vector.size();
00128 
00129             bool found = esize > 0 ? ikvds_ptr_->get(&key, key.size(), &kvds_val_vector, esize) : false;
00130 
00131             if(found)
00132             {
00133                if(esize < kvds_val_vector.size())
00134                {
00135                   // read less than the buffer size so before we must resize buffer
00136                   kvds_val_vector.resize(esize);
00137                }
00138 
00139                *kvds_val_vector; // Reassemble vals
00140             }
00141 
00142             return found;
00143          }
00144 
00145          bool get(kvds_key_const_t const & key, kvds_values_t & vals) const
00146          {
00147             typename kvds_val_t::vector_type kvds_val_vector(vals);
00148 
00149             bool found = false;
00150             size_t esize = 0;
00151 
00152             if(ikvds_ptr_->siz(&key, key.size(), esize))
00153             {
00154                kvds_val_vector.resize(esize);
00155 
00156                found = ikvds_ptr_->all(&key, key.size(), &kvds_val_vector, esize);
00157 
00158                if(found)
00159                {
00160                   *kvds_val_vector; // Reassemble vals
00161                }
00162             }
00163 
00164             return found;
00165          }
00166 
00167          bool insert(value_type const & kvp) // Just to be more STL map like
00168          {
00169             return put(kvp.first, kvp.second);
00170          }
00171 
00172          bool add(kvds_key_const_t const & key, kvds_val_const_t const & val) const
00173          {
00174             return ikvds_ptr_->add(
00175                &key, key.size(),
00176                &val, val.size()
00177                );
00178          }
00179 
00180          bool exists(kvds_key_const_t const & key) const
00181          {
00182             return ikvds_ptr_->xst(&key, key.size());
00183          }
00184 
00185          bool erase(kvds_key_const_t const & key) const
00186          {
00187             return ikvds_ptr_->del(&key, key.size());
00188          }
00189 
00190          bool clear() const
00191          {
00192             return ikvds_ptr_->clr();
00193          }
00194 
00195          bool size(kvds_key_const_t const & key, size_t & size) const
00196          {
00197             bool found = ikvds_ptr_->siz(&key, key.size(), size);
00198 
00199             if(found && (0 != (size % sizeof(typename kvds_values_t::value_type))))
00200             {
00201                throw std::runtime_error("value type boundary error");
00202             }
00203 
00204             size /= sizeof(typename kvds_values_t::value_type);
00205 
00206             return found;
00207          }
00208 
00209          size_t size(kvds_key_const_t const & key) const
00210          {
00211             size_t size = 0;
00212 
00213             if(!this->size(key, size))
00214             {
00215                throw std::runtime_error("item not found");
00216             }
00217 
00218             return size;
00219          }
00220 
00221          bool count(boost::uint64_t & cnt) const
00222          {
00223             return ikvds_ptr_->cnt(cnt);
00224          }
00225 
00226          boost::uint64_t size() const // Just to be more STL like
00227          {
00228             boost::uint64_t cnt = 0;
00229 
00230             if(!count(cnt))
00231             {
00232                 throw std::runtime_error("size not available");
00233             }
00234 
00235             return cnt;
00236          }
00237 
00238          bool empty() const
00239          {
00240             bool isnil = false;
00241 
00242             if(!ikvds_ptr_->nil(isnil))
00243             {
00244                 throw std::runtime_error("empty state is not available");
00245             }
00246 
00247             return isnil;
00248          }
00249 
00251          IKvds & get_ikvds() const
00252          {
00254             if(!ikvds_ptr_) { throw std::runtime_error("Invalid kvds interface"); }
00255             return *ikvds_ptr_;
00256          }
00257 
00258          ikvds_ptr_t get_ikvds_ptr() const
00259          {
00261             return ikvds_ptr_;
00262          }
00263 
00264    private:
00278 
00279       class Iow // Indexed object wrapper (needs no external visibility!)
00280       {
00281       public:
00282          Iow(
00283             Kvds & kvds,
00284             kvds_key_const_t const & key
00285             ) : kvds_(kvds), key_(key), val_(val_type()) {}
00286 
00287          Iow & operator = (val_type const & val)
00288          {
00289             val_ = val;
00290 
00291             if(!kvds_.put(key_, val_))
00292             {
00293                throw std::runtime_error("Write to datastore failed");
00294             }
00295 
00296             return *this;
00297          }
00298 
00299          val_type & operator * () { return val_; }
00300 
00301          operator val_type const () { return val_; }
00302 
00303       private:
00304          Kvds & kvds_;
00305          kvds_key_const_t const & key_;
00306          val_type val_;
00307       };
00308    public:
00311       Iow operator [](kvds_key_const_t const & key)
00312       {
00313          Iow iow(*this, key);
00314 
00315          if(!get(key, *iow))
00316          {
00317             // It doesn't exist, create one
00318             iow = val_type();
00319          }
00320 
00321          return iow;
00322       }
00323 
00324    private:
00325       ikvds_ptr_t ikvds_ptr_;
00326    };
00327 
00328 }}
00329 
00330 #endif /// MOOST_KVDS_KVDS_HPP__