IceDB.h
Go to the documentation of this file.
1 // **********************************************************************
2 //
3 // Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
4 //
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
7 //
8 // **********************************************************************
9 
10 #ifndef ICE_DB_H
11 #define ICE_DB_H
12 
13 #include <Ice/Initialize.h>
14 #include <Ice/InputStream.h>
15 #include <Ice/OutputStream.h>
16 #include <IceUtil/Exception.h>
17 #include <IceUtil/FileUtil.h>
18 
19 #include <lmdb.h>
20 
21 #ifndef ICE_DB_API
22 #if defined(ICE_STATIC_LIBS)
23 #define ICE_DB_API /**/
24 #elif defined(ICE_DB_API_EXPORTS)
25 #define ICE_DB_API ICE_DECLSPEC_EXPORT
26 #else
27 #define ICE_DB_API ICE_DECLSPEC_IMPORT
28 #endif
29 #endif
30 
31 //
32 // Automatically link IceDB37[D|++11|++11D].lib with Visual C++
33 //
34 #if !defined(ICE_BUILDING_ICE_DB) && defined(ICE_DB_API_EXPORTS)
35 #define ICE_BUILDING_ICE_DB
36 #endif
37 
38 #if defined(_MSC_VER) && !defined(ICE_BUILDING_ICE_DB)
39 #pragma comment(lib, ICE_LIBNAME("IceDB"))
40 #endif
41 
42 namespace IceDB
43 {
44 
45  const size_t maxKeySize = 511;
46 
47  //
48  // LMDBException wraps an error condition (and error code)
49  // returned by LMDB
50  //
51  class ICE_DB_API LMDBException : public IceUtil::Exception
52  {
53  public:
54  LMDBException(const char*, int, int);
55 #ifndef ICE_CPP11_COMPILER
56  virtual ~LMDBException() throw();
57 #endif
58 
59  virtual std::string ice_id() const;
60  virtual void ice_print(std::ostream&) const;
61 #ifndef ICE_CPP11_MAPPING
62  virtual LMDBException* ice_clone() const;
63 #endif
64  virtual void ice_throw() const;
65 
66  int error() const;
67 
68  private:
69  const int _error;
70  static const char* _name;
71  };
72 
73  //
74  // KeyTooLongException is thrown if we attempt to marshal a
75  // key with a marshaled representation longer than maxKeySize.
76  //
77  class ICE_DB_API KeyTooLongException : public IceUtil::Exception
78  {
79  public:
80  KeyTooLongException(const char*, int, size_t);
81 #ifndef ICE_CPP11_COMPILER
82  virtual ~KeyTooLongException() throw();
83 #endif
84 
85  virtual std::string ice_id() const;
86  virtual void ice_print(std::ostream&) const;
87 #ifndef ICE_CPP11_MAPPING
88  virtual KeyTooLongException* ice_clone() const;
89 #endif
90  virtual void ice_throw() const;
91 
92  private:
93  const size_t _size;
94  static const char* _name;
95  };
96 
97  //
98  // The creation of an Env fails with BadEnvException when this
99  // Env's max key size is smaller than maxKeySize.
100  //
101  class ICE_DB_API BadEnvException : public IceUtil::Exception
102  {
103  public:
104  BadEnvException(const char*, int, size_t);
105 #ifndef ICE_CPP11_COMPILER
106  virtual ~BadEnvException() throw();
107 #endif
108 
109  virtual std::string ice_id() const;
110  virtual void ice_print(std::ostream&) const;
111 #ifndef ICE_CPP11_MAPPING
112  virtual BadEnvException* ice_clone() const;
113 #endif
114  virtual void ice_throw() const;
115 
116  private:
117  const size_t _size;
118  static const char* _name;
119  };
120 
121  //
122  // Codec reads and writes T to/from MDB_val
123  //
124  // Partial specializations of this template must provide:
125  //
126  // Read [out] T from [in] MDB_val using [in] context C
127  // static void read(T& , const MDB_val&, const C&);
128  //
129  // Write [in] T into [out] MDB_val using [in] context C
130  // [out] H& holds the memory for MDB_val.mv_data.
131  // static void write(const T&, MDB_val&, H&, const C&);
132  //
133  // Write [in] T into [in/out] MDB_val using [in] context C
134  // [in] MDB_val contains the destination array
135  // write returns true on success, and false if the provided
136  // array is too small.
137  // On failure, MDB_val.mv_size contains the marshaled key
138  // size if known, and 0 if not know.
139  // static bool write(const T&, MDB_val&, H&, const C&);
140  //
141  template <typename T, typename C, typename H>
142  struct Codec;
143 
145  {
146  public:
147  explicit Env(const std::string&, MDB_dbi = 0, size_t = 0, unsigned int = 0);
148  ~Env();
149 
150  void close();
151 
152  MDB_env* menv() const;
153 
154  private:
155  // Not implemented: class is not copyable
156  Env(const Env&);
157  void operator=(const Env&);
158 
159  MDB_env* _menv;
160  };
161 
163  {
164  public:
165  virtual ~Txn();
166 
167  void commit();
168  void rollback();
169 
170  MDB_txn* mtxn() const;
171 
172  protected:
173  explicit Txn(const Env&, unsigned int);
174 
175  MDB_txn* _mtxn;
176 
177  private:
178  // Not implemented: class is not copyable
179  Txn(const Txn&);
180  void operator=(const Txn&);
181  };
182 
183  class ICE_DB_API ReadOnlyTxn : public Txn
184  {
185  public:
186  virtual ~ReadOnlyTxn();
187 
188  explicit ReadOnlyTxn(const Env&);
189 
190  void reset();
191  void renew();
192  };
193 
194  class ICE_DB_API ReadWriteTxn : public Txn
195  {
196  public:
197  virtual ~ReadWriteTxn();
198 
199  explicit ReadWriteTxn(const Env&);
200  };
201 
203  {
204  public:
205  void clear(const ReadWriteTxn&);
206  MDB_dbi mdbi() const;
207 
208  virtual ~DbiBase();
209 
210  protected:
211  DbiBase(const Txn&, const std::string&, unsigned int, MDB_cmp_func*);
212  DbiBase();
213 
214  // default copy ctor and assignment operator are OK
215 
216  bool get(const Txn&, MDB_val*, MDB_val*) const;
217  void put(const ReadWriteTxn&, MDB_val*, MDB_val*, unsigned int);
218  bool find(const Txn&, MDB_val*) const;
219  bool del(const ReadWriteTxn&, MDB_val*, MDB_val*);
220 
221  private:
222  MDB_dbi _mdbi;
223  };
224 
225  template <typename K, typename D, typename C, typename H>
226  class Dbi : public DbiBase
227  {
228  public:
229  Dbi(const Txn& txn,
230  const std::string& name,
231  const C& ctx,
232  unsigned int flags = 0,
233  MDB_cmp_func* cmp = 0) :
234  DbiBase(txn, name, flags, cmp), _marshalingContext(ctx)
235  {
236  }
237 
238  Dbi()
239  {
240  }
241 
242  bool
243  get(const Txn& txn, const K& key, D& data) const
244  {
245  unsigned char kbuf[maxKeySize];
246  MDB_val mkey = {maxKeySize, kbuf};
247 
248  if (Codec<K, C, H>::write(key, mkey, _marshalingContext))
249  {
250  MDB_val mdata;
251  if (DbiBase::get(txn, &mkey, &mdata))
252  {
253  Codec<D, C, H>::read(data, mdata, _marshalingContext);
254  return true;
255  }
256  }
257  return false;
258  }
259 
260  void
261  put(const ReadWriteTxn& txn, const K& key, const D& data, unsigned int flags = 0)
262  {
263  unsigned char kbuf[maxKeySize];
264  MDB_val mkey = {maxKeySize, kbuf};
265 
266  if (Codec<K, C, H>::write(key, mkey, _marshalingContext))
267  {
268  H hdata;
269  MDB_val mdata;
270  Codec<D, C, H>::write(data, mdata, hdata, _marshalingContext);
271  DbiBase::put(txn, &mkey, &mdata, flags);
272  }
273  else
274  {
275  throw KeyTooLongException(__FILE__, __LINE__, mkey.mv_size);
276  }
277  }
278 
279  bool
280  find(const Txn& txn, const K& key) const
281  {
282  unsigned char kbuf[maxKeySize];
283  MDB_val mkey = {maxKeySize, kbuf};
284  if (Codec<K, C, H>::write(key, mkey, _marshalingContext))
285  {
286  return DbiBase::find(txn, &mkey);
287  }
288  else
289  {
290  return false;
291  }
292  }
293 
294  bool
295  del(const ReadWriteTxn& txn, const K& key, const D& data)
296  {
297  unsigned char kbuf[maxKeySize];
298  MDB_val mkey = {maxKeySize, kbuf};
299  if (Codec<K, C, H>::write(key, mkey, _marshalingContext))
300  {
301  H hdata;
302  MDB_val mdata;
303  Codec<D, C, H>::write(data, mdata, hdata, _marshalingContext);
304  return DbiBase::del(txn, &mkey, &mdata);
305  }
306  else
307  {
308  return false;
309  }
310  }
311 
312  bool
313  del(const ReadWriteTxn& txn, const K& key)
314  {
315  unsigned char kbuf[maxKeySize];
316  MDB_val mkey = {maxKeySize, kbuf};
317  if (Codec<K, C, H>::write(key, mkey, _marshalingContext))
318  {
319  return DbiBase::del(txn, &mkey, 0);
320  }
321  else
322  {
323  return false;
324  }
325  }
326 
327  C
329  {
330  return _marshalingContext;
331  }
332 
333  private:
334  C _marshalingContext;
335  };
336 
338  {
339  public:
340  void close();
341 
342  MDB_cursor* mcursor() const;
343 
344  virtual ~CursorBase();
345 
346  protected:
347  CursorBase(MDB_dbi dbi, const Txn& txn, bool);
348 
349  bool get(MDB_val*, MDB_val*, MDB_cursor_op);
350  void put(MDB_val*, MDB_val*, unsigned int);
351  bool find(MDB_val*);
352  bool find(MDB_val*, MDB_val*);
353  void del(unsigned int);
354  void renew(const ReadOnlyTxn&);
355 
356  private:
357  // Not implemented: class is not copyable
358  CursorBase(const CursorBase&);
359  void operator=(const CursorBase&);
360 
361  MDB_cursor* _mcursor;
362  const bool _readOnly;
363  };
364 
365  template <typename K, typename D, typename C, typename H>
366  class Cursor : public CursorBase
367  {
368  public:
369  Cursor(const Dbi<K, D, C, H>& dbi, const ReadOnlyTxn& txn) :
370  CursorBase(dbi.mdbi(), txn, true), _marshalingContext(dbi.marshalingContext())
371  {
372  }
373 
374  Cursor(const Dbi<K, D, C, H>& dbi, const ReadWriteTxn& txn) :
375  CursorBase(dbi.mdbi(), txn, false), _marshalingContext(dbi.marshalingContext())
376  {
377  }
378 
379  Cursor(const Dbi<K, D, C, H>& dbi, const Txn& txn) :
380  CursorBase(dbi.mdbi(), txn, dynamic_cast<const ReadOnlyTxn*>(&txn) != 0),
381  _marshalingContext(dbi.marshalingContext())
382  {
383  }
384 
385  bool
386  get(K& key, D& data, MDB_cursor_op op)
387  {
388  MDB_val mkey, mdata;
389  if (CursorBase::get(&mkey, &mdata, op))
390  {
393  return true;
394  }
395  return false;
396  }
397 
398  bool
399  find(const K& key)
400  {
401  unsigned char kbuf[maxKeySize];
402  MDB_val mkey = {maxKeySize, kbuf};
404  {
405  return CursorBase::find(&mkey);
406  }
407  else
408  {
409  return false;
410  }
411  }
412 
413  bool
414  find(const K& key, D& data)
415  {
416  unsigned char kbuf[maxKeySize];
417  MDB_val mkey = {maxKeySize, kbuf};
419  {
420  MDB_val mdata;
421  if (CursorBase::find(&mkey, &mdata))
422  {
424  return true;
425  }
426  }
427  return false;
428  }
429 
430  protected:
432  };
433 
434  template <typename K, typename D, typename C, typename H>
435  class ReadWriteCursor : public Cursor<K, D, C, H>
436  {
437  public:
438  ReadWriteCursor(const Dbi<K, D, C, H>& dbi, const ReadWriteTxn& txn) :
439  Cursor<K, D, C, H>(dbi, txn)
440  {
441  }
442 
443  void
444  put(const K& key, const D& data, unsigned int flags = 0)
445  {
446  unsigned char kbuf[maxKeySize];
447  MDB_val mkey = {maxKeySize, kbuf};
448  if (Codec<K, C, H>::write(key, mkey, this->_marshalingContext))
449  {
450  H hdata;
451  MDB_val mdata;
452  Codec<D, C, H>::write(data, mdata, hdata, this->_marshalingContext);
453  CursorBase::put(&mkey, &mdata, flags);
454  }
455  else
456  {
457  throw KeyTooLongException(__FILE__, __LINE__, mkey.mv_size);
458  }
459  }
460 
461  void
462  del(unsigned int flags = 0)
463  {
464  CursorBase::del(flags);
465  }
466  };
467 
468  template <typename K, typename D, typename C, typename H>
469  class ReadOnlyCursor : public Cursor<K, D, C, H>
470  {
471  public:
472  ReadOnlyCursor(const Dbi<K, D, C, H>& dbi, const ReadOnlyTxn& txn) :
473  Cursor<K, D, C, H>(dbi, txn)
474  {
475  }
476 
477  void
478  renew(const ReadOnlyTxn& txn)
479  {
480  CursorBase::renew(txn);
481  }
482  };
483 
484  //
485  // Partial specialization of Codec for Ice encoding
486  //
487  struct IceContext
488  {
490  Ice::EncodingVersion encoding;
491  };
492 
493  template <typename T>
494  struct Codec<T, IceContext, Ice::OutputStream>
495  {
496  static void
497  read(T& t, const MDB_val& val, const IceContext& ctx)
498  {
499  std::pair<const Ice::Byte*, const Ice::Byte*> p(
500  static_cast<const Ice::Byte*>(val.mv_data),
501  static_cast<const Ice::Byte*>(val.mv_data) + val.mv_size);
502  Ice::InputStream in(ctx.communicator, ctx.encoding, p);
503  in.read(t);
504  }
505 
506  static void
507  write(const T& t, MDB_val& val, Ice::OutputStream& holder, const IceContext& ctx)
508  {
509  holder.initialize(ctx.communicator, ctx.encoding);
510  holder.write(t);
511  val.mv_size = holder.b.size();
512  val.mv_data = &holder.b[0];
513  }
514 
515  static bool
516  write(const T& t, MDB_val& val, const IceContext& ctx)
517  {
518  const size_t limit = val.mv_size;
519  std::pair<Ice::Byte*, Ice::Byte*> p(reinterpret_cast<Ice::Byte*>(val.mv_data),
520  reinterpret_cast<Ice::Byte*>(val.mv_data) + limit);
521  Ice::OutputStream stream(ctx.communicator, ctx.encoding, p);
522  stream.write(t);
523  val.mv_size = stream.b.size();
524  return stream.b.size() > limit ? false : true;
525  }
526  };
527 
528  //
529  // Returns computed mapSize in bytes.
530  // When the input parameter is <= 0, returns a platform-dependent default
531  // (currently 0 on Windows and 100 MB on other platforms).
532  // Otherwise, returns input parameter * 1 MB.
533  //
534 
535  ICE_DB_API size_t getMapSize(int);
536 
537 } // namespace IceDB
538 
539 #endif
IceDB::Cursor::Cursor
Cursor(const Dbi< K, D, C, H > &dbi, const ReadWriteTxn &txn)
Definition: IceDB.h:374
IceDB::Codec
Definition: IceDB.h:142
IceDB::DbiBase
Definition: IceDB.h:202
IceDB
Definition: IceDB.h:42
IceDB::DbiBase::get
bool get(const Txn &, MDB_val *, MDB_val *) const
IceDB::ReadWriteTxn
Definition: IceDB.h:194
IceDB::IceContext::encoding
Ice::EncodingVersion encoding
Definition: IceDB.h:490
IceDB::CursorBase::find
bool find(MDB_val *)
IceDB::Dbi::del
bool del(const ReadWriteTxn &txn, const K &key)
Definition: IceDB.h:313
IceDB::maxKeySize
const size_t maxKeySize
Definition: IceDB.h:45
IceDB::Dbi::marshalingContext
C marshalingContext() const
Definition: IceDB.h:328
ICE_DB_API
#define ICE_DB_API
Definition: IceDB.h:27
IceDB::CursorBase::renew
void renew(const ReadOnlyTxn &)
IceDB::Cursor::find
bool find(const K &key, D &data)
Definition: IceDB.h:414
IceDB::Cursor
Definition: IceDB.h:366
IceDB::ReadOnlyTxn
Definition: IceDB.h:183
IceDB::CursorBase::del
void del(unsigned int)
IceDB::getMapSize
ICE_DB_API size_t getMapSize(int)
IceDB::Dbi::find
bool find(const Txn &txn, const K &key) const
Definition: IceDB.h:280
IceDB::Dbi::Dbi
Dbi(const Txn &txn, const std::string &name, const C &ctx, unsigned int flags=0, MDB_cmp_func *cmp=0)
Definition: IceDB.h:229
IceInternal::Handle<::Ice::Communicator >
IceDB::Cursor::get
bool get(K &key, D &data, MDB_cursor_op op)
Definition: IceDB.h:386
IceDB::ReadOnlyCursor
Definition: IceDB.h:469
IceDB::IceContext::communicator
Ice::CommunicatorPtr communicator
Definition: IceDB.h:489
IceDB::Dbi::put
void put(const ReadWriteTxn &txn, const K &key, const D &data, unsigned int flags=0)
Definition: IceDB.h:261
IceDB::ReadWriteCursor::put
void put(const K &key, const D &data, unsigned int flags=0)
Definition: IceDB.h:444
IceDB::Env
Definition: IceDB.h:144
IceDB::ReadOnlyCursor::renew
void renew(const ReadOnlyTxn &txn)
Definition: IceDB.h:478
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
IceDB::DbiBase::put
void put(const ReadWriteTxn &, MDB_val *, MDB_val *, unsigned int)
IceDB::Codec< T, IceContext, Ice::OutputStream >::read
static void read(T &t, const MDB_val &val, const IceContext &ctx)
Definition: IceDB.h:497
armarx::read
void read(auto &eigen, auto *table)
Definition: FTSensorCalibrationGuiWidgetController.cpp:503
IceDB::Cursor::Cursor
Cursor(const Dbi< K, D, C, H > &dbi, const Txn &txn)
Definition: IceDB.h:379
IceDB::CursorBase::get
bool get(MDB_val *, MDB_val *, MDB_cursor_op)
IceDB::ReadWriteCursor
Definition: IceDB.h:435
IceDB::IceContext
Definition: IceDB.h:487
IceDB::Dbi
Definition: IceDB.h:226
IceDB::DbiBase::find
bool find(const Txn &, MDB_val *) const
IceDB::Dbi::get
bool get(const Txn &txn, const K &key, D &data) const
Definition: IceDB.h:243
Ice
Definition: DBTypes.cpp:63
IceDB::ReadOnlyCursor::ReadOnlyCursor
ReadOnlyCursor(const Dbi< K, D, C, H > &dbi, const ReadOnlyTxn &txn)
Definition: IceDB.h:472
magic_enum::detail::find
constexpr std::size_t find(string_view str, char_type c) noexcept
Definition: magic_enum.hpp:309
IceDB::DbiBase::del
bool del(const ReadWriteTxn &, MDB_val *, MDB_val *)
IceDB::Txn
Definition: IceDB.h:162
IceDB::Codec< T, IceContext, Ice::OutputStream >::write
static void write(const T &t, MDB_val &val, Ice::OutputStream &holder, const IceContext &ctx)
Definition: IceDB.h:507
IceDB::Txn::_mtxn
MDB_txn * _mtxn
Definition: IceDB.h:175
armarx::aron::write
requires data::isWriter< WriterT > void write(WriterT &aron_w, const Eigen::Matrix< EigenT, rows, cols, options > &input, typename WriterT::ReturnType &ret, const armarx::aron::Path &aron_p=armarx::aron::Path())
Definition: eigen.h:138
IceDB::Dbi::del
bool del(const ReadWriteTxn &txn, const K &key, const D &data)
Definition: IceDB.h:295
IceDB::CursorBase
Definition: IceDB.h:337
IceDB::Cursor::Cursor
Cursor(const Dbi< K, D, C, H > &dbi, const ReadOnlyTxn &txn)
Definition: IceDB.h:369
IceDB::Dbi::Dbi
Dbi()
Definition: IceDB.h:238
IceDB::BadEnvException
Definition: IceDB.h:101
IceDB::Codec< T, IceContext, Ice::OutputStream >::write
static bool write(const T &t, MDB_val &val, const IceContext &ctx)
Definition: IceDB.h:516
T
float T
Definition: UnscentedKalmanFilterTest.cpp:38
IceDB::ReadWriteCursor::del
void del(unsigned int flags=0)
Definition: IceDB.h:462
IceDB::KeyTooLongException
Definition: IceDB.h:77
IceDB::LMDBException
Definition: IceDB.h:51
IceDB::ReadWriteCursor::ReadWriteCursor
ReadWriteCursor(const Dbi< K, D, C, H > &dbi, const ReadWriteTxn &txn)
Definition: IceDB.h:438
IceDB::Cursor::find
bool find(const K &key)
Definition: IceDB.h:399
IceDB::CursorBase::put
void put(MDB_val *, MDB_val *, unsigned int)
IceDB::Cursor::_marshalingContext
C _marshalingContext
Definition: IceDB.h:431