Lunchbox  1.12.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
persistentMap.h
1 
2 /* Copyright (c) 2014-2015, Stefan.Eilemann@epfl.ch
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License version 2.1 as published
6  * by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11  * details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  */
17 
18 #ifndef LUNCHBOX_PERSISTENTMAP_H
19 #define LUNCHBOX_PERSISTENTMAP_H
20 
21 #include <lunchbox/api.h>
22 #include <lunchbox/bitOperation.h> // byteswap()
23 #include <lunchbox/debug.h> // className
24 #include <lunchbox/log.h> // LBTHROW
25 #include <lunchbox/types.h>
26 #include <servus/uri.h>
27 
28 #include <boost/foreach.hpp>
29 #include <boost/lexical_cast.hpp>
30 #include <boost/noncopyable.hpp>
31 #include <boost/type_traits.hpp>
32 
33 #include <iostream>
34 #include <set>
35 #include <stdexcept>
36 #include <string>
37 #include <vector>
38 
39 namespace lunchbox
40 {
41 namespace detail { class PersistentMap; }
42 
48 class PersistentMap : public boost::noncopyable
49 {
50 public:
64  LUNCHBOX_API explicit PersistentMap( const std::string& uri =std::string());
65 
70  LUNCHBOX_API explicit PersistentMap( const servus::URI& uri );
71 
73  LUNCHBOX_API ~PersistentMap();
74 
79  LUNCHBOX_API static bool handles( const servus::URI& uri );
80 
94  LUNCHBOX_API size_t setQueueDepth( const size_t depth );
95 
105  template< class V > bool insert( const std::string& key, const V& value )
106  { return _insert( key, value, boost::has_trivial_assign< V >( )); }
107 
117  template< class V >
118  bool insert( const std::string& key, const std::vector< V >& values )
119  { return _insert( key, values, boost::has_trivial_assign< V >( )); }
120 
130  template< class V >
131  bool insert( const std::string& key, const std::set< V >& values )
132  { return insert( key, std::vector<V>( values.begin(), values.end( ))); }
133 
141  LUNCHBOX_API std::string operator [] ( const std::string& key ) const;
142 
150  template< class V > V get( const std::string& key ) const
151  { return _get< V >( key ); }
152 
160  template< class V > std::vector< V > getVector( const std::string& key )
161  const;
162 
170  template< class V > std::set< V > getSet( const std::string& key ) const;
171 
182  LUNCHBOX_API bool fetch( const std::string& key, size_t sizeHint = 0 ) const;
183 
185  LUNCHBOX_API bool contains( const std::string& key ) const;
186 
188  LUNCHBOX_API bool flush();
189 
191  LUNCHBOX_API void setByteswap( const bool swap );
192 
193 private:
194  detail::PersistentMap* const _impl;
195 
196  LUNCHBOX_API bool _insert( const std::string& key, const void* data,
197  const size_t size );
198  LUNCHBOX_API bool _swap() const;
199 
200 
201  // Enables map.insert( "foo", "bar" ); bar is a char[4]. The funny braces
202  // declare v as a "const ref to array of four chars", not as a "const array
203  // to four char refs". Long live Bjarne!
204  template< size_t N > bool
205  _insert( const std::string& k, char const (& v)[N], const boost::true_type&)
206  {
207  return _insert( k, (void*)v, N - 1 ); // strip '0'
208  }
209 
210  template< class V >
211  bool _insert( const std::string& k, const V& v, const boost::true_type& )
212  {
213  if( boost::is_pointer< V >::value )
214  LBTHROW( std::runtime_error( "Can't insert pointers" ));
215  return _insert( k, &v, sizeof( V ));
216  }
217 
218  template< class V >
219  bool _insert( const std::string&, const V& v, const boost::false_type& )
220  { LBTHROW( std::runtime_error( "Can't insert non-POD " + className( v ))); }
221 
222  template< class V >
223  bool _insert( const std::string& key, const std::vector< V >& values,
224  const boost::true_type& )
225  { return _insert( key, values.data(), values.size() * sizeof( V )); }
226 
227  template< class V > V _get( const std::string& k ) const
228  {
229  if( !boost::has_trivial_assign< V >( ))
230  LBTHROW( std::runtime_error( "Can't retrieve non-POD " +
231  className( V( ))));
232  if( boost::is_pointer< V >::value )
233  LBTHROW( std::runtime_error( "Can't retrieve pointers" ));
234 
235  const std::string& value = (*this)[ k ];
236  if( value.size() != sizeof( V ))
237  LBTHROW( std::runtime_error( std::string( "Wrong value size " ) +
238  boost::lexical_cast< std::string >( value.size( )) +
239  " for type " + className( V( ))));
240 
241  V v( *reinterpret_cast< const V* >( value.data( )));
242  if( _swap( ))
243  byteswap( v );
244  return v;
245  }
246 };
247 
248 template<> inline
249 bool PersistentMap::_insert( const std::string& k, const std::string& v,
250  const boost::false_type& )
251 {
252  return _insert( k, v.data(), v.length( ));
253 }
254 
255 template< class V > inline
256 std::vector< V > PersistentMap::getVector( const std::string& key ) const
257 {
258  const std::string& value = (*this)[ key ];
259  std::vector< V > vector( reinterpret_cast< const V* >( value.data( )),
260  reinterpret_cast< const V* >( value.data() + value.size( )));
261  if( _swap() && sizeof( V ) != 1 )
262  {
263  BOOST_FOREACH( V& elem, vector )
264  byteswap( elem );
265  }
266  return vector;
267 }
268 
269 template< class V > inline
270 std::set< V > PersistentMap::getSet( const std::string& key ) const
271 {
272  std::string value = (*this)[ key ];
273  V* const begin = reinterpret_cast< V* >(
274  const_cast< char * >( value.data( )));
275  V* const end = begin + value.size() / sizeof( V );
276 
277  if( _swap() && sizeof( V ) != 1 )
278  for( V* i = begin; i < end; ++i )
279  byteswap( *i );
280 
281  return std::set< V >( begin, end );
282 }
283 
284 }
285 
286 #endif //LUNCHBOX_PERSISTENTMAP_H
LUNCHBOX_API size_t setQueueDepth(const size_t depth)
Set the maximum number of asynchronous outstanding write operations.
Defines export visibility macros for library Lunchbox.
Basic type definitions not provided by the operating system.
LUNCHBOX_API PersistentMap(const std::string &uri=std::string())
Construct a new persistent map.
void byteswap(T &value)
Swap the byte order of the given value.
LUNCHBOX_API bool flush()
Flush outstanding operations to the backend storage.
std::string className(const T *object)
Print the RTTI name of the given class.
Definition: debug.h:74
LUNCHBOX_API ~PersistentMap()
Destruct the persistent map.
Unified interface to save key-value pairs in a persistent store.
Definition: persistentMap.h:48
bool insert(const std::string &key, const std::set< V > &values)
Insert or update a set of values in the database.
LUNCHBOX_API bool fetch(const std::string &key, size_t sizeHint=0) const
Asynchronously retrieve a value which to be read later.
bool insert(const std::string &key, const V &value)
Insert or update a value in the database.
static LUNCHBOX_API bool handles(const servus::URI &uri)
LUNCHBOX_API std::string operator[](const std::string &key) const
Retrieve a value for a key.
std::set< V > getSet(const std::string &key) const
Retrieve a value as a set for a key.
LUNCHBOX_API void setByteswap(const bool swap)
Enable or disable endianness conversion on reads.
std::vector< V > getVector(const std::string &key) const
Retrieve a value as a vector for a key.
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
LUNCHBOX_API bool contains(const std::string &key) const
bool insert(const std::string &key, const std::vector< V > &values)
Insert or update a vector of values in the database.
This file contains logging classes.
#define LBTHROW(exc)
Log a std::exception if topic LOG_EXCEPTION is set before throwing exception.
Definition: log.h:218