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