Line data Source code
1 :
2 : /* Copyright (c) 2014, 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/debug.h> // className
23 : #include <lunchbox/log.h> // LBTHROW
24 : #include <lunchbox/types.h>
25 : #include <boost/noncopyable.hpp>
26 :
27 : #include <boost/type_traits.hpp>
28 : #include <iostream>
29 : #include <set>
30 : #include <stdexcept>
31 : #include <string>
32 : #include <vector>
33 :
34 : namespace lunchbox
35 : {
36 : namespace detail { class PersistentMap; }
37 :
38 : /**
39 : * Unified interface to save key-value pairs in a persistent store.
40 : *
41 : * Example: @include tests/persistentMap.cpp
42 : */
43 : class PersistentMap : public boost::noncopyable
44 : {
45 : public:
46 : /**
47 : * Construct a new persistent map.
48 : *
49 : * Depending on the URI scheme an implementation backend is chosen. If no
50 : * URI is given, a default one is selected. Available implementations are:
51 : * * leveldb://path (if LUNCHBOX_USE_LEVELDB is defined)
52 : * * skv://path_to_config#pdsname (if LUNCHBOX_USE_SKV is defined)
53 : *
54 : * @param uri the storage backend and destination.
55 : * @throw std::runtime_error if no suitable implementation is found.
56 : * @throw std::runtime_error if opening the leveldb failed.
57 : * @version 1.9.2
58 : */
59 : LUNCHBOX_API PersistentMap( const std::string& uri = std::string( ));
60 :
61 : /**
62 : * Construct a persistent map using an URI. See other ctor for details.
63 : * @version 1.9.2
64 : */
65 : LUNCHBOX_API explicit PersistentMap( const URI& uri );
66 :
67 : /** Destruct the persistent map. @version 1.9.2 */
68 : LUNCHBOX_API ~PersistentMap();
69 :
70 : /**
71 : * @return true if an implementation for the given URI is available.
72 : * @version 1.9.2
73 : */
74 : LUNCHBOX_API static bool handles( const URI& uri );
75 :
76 : /**
77 : * Insert or update a value in the database.
78 : *
79 : * @param key the key to store the value.
80 : * @param value the value stored at the key.
81 : * @return true on success, false otherwise
82 : * @throw std::runtime_error if the value is not copyable
83 : * @version 1.9.2
84 : */
85 9 : template< class V > bool insert( const std::string& key, const V& value )
86 9 : { return _insert( key, value, boost::has_trivial_assign< V >( )); }
87 :
88 : /**
89 : * Insert or update a vector of values in the database.
90 : *
91 : * @param key the key to store the value.
92 : * @param value the values stored at the key.
93 : * @return true on success, false otherwise
94 : * @throw std::runtime_error if the vector values are not copyable
95 : * @version 1.9.2
96 : */
97 : template< class V >
98 9 : bool insert( const std::string& key, const std::vector< V >& values )
99 9 : { return _insert( key, values, boost::has_trivial_assign< V >( )); }
100 :
101 : /**
102 : * Insert or update a set of values in the database.
103 : *
104 : * @param key the key to store the value.
105 : * @param value the values stored at the key.
106 : * @return true on success, false otherwise
107 : * @throw std::runtime_error if the set values are not copyable
108 : * @version 1.9.2
109 : */
110 : template< class V >
111 3 : bool insert( const std::string& key, const std::set< V >& values )
112 3 : { return insert( key, std::vector<V>( values.begin(), values.end( ))); }
113 :
114 : /**
115 : * Retrieve a value for a key.
116 : *
117 : * @param key the key to retreive.
118 : * @return the value, or an empty string if the key is not available.
119 : * @version 1.9.2
120 : */
121 : LUNCHBOX_API std::string operator [] ( const std::string& key ) const;
122 :
123 : /**
124 : * Retrieve a value as a vector for a key.
125 : *
126 : * @param key the key to retreive.
127 : * @return the values, or an empty vector if the key is not available.
128 : * @version 1.9.2
129 : */
130 : template< class V > std::vector< V > getVector( const std::string& key );
131 :
132 : /**
133 : * Retrieve a value as a set for a key.
134 : *
135 : * @param key the key to retreive.
136 : * @return the values, or an empty set if the key is not available.
137 : * @version 1.9.2
138 : */
139 : template< class V > std::set< V > getSet( const std::string& key );
140 :
141 : /** @return true if the key exists. @version 1.9.2 */
142 : LUNCHBOX_API bool contains( const std::string& key ) const;
143 :
144 : private:
145 : detail::PersistentMap* const _impl;
146 :
147 : LUNCHBOX_API bool _insert( const std::string& key, const void* data,
148 : const size_t size );
149 :
150 :
151 : // Enables map.insert( "foo", "bar" ); bar is a char[4]. The funny braces
152 : // declare v as a "const ref to array of four chars", not as a "const array
153 : // to four char refs". Long live Bjarne!
154 : template< size_t N > bool
155 6 : _insert( const std::string& k, char const (& v)[N], const boost::true_type&)
156 : {
157 6 : return _insert( k, (void*)v, N - 1 ); // strip '0'
158 : }
159 :
160 : template< class V >
161 : bool _insert( const std::string& k, const V& v, const boost::true_type& )
162 : {
163 : if( boost::is_pointer< V >::value )
164 : LBTHROW( std::runtime_error( "Can't insert pointers" ));
165 : return _insert( k, &v, sizeof( V ));
166 : }
167 :
168 : template< class V >
169 : bool _insert( const std::string&, const V& v, const boost::false_type& )
170 : { LBTHROW( std::runtime_error( "Can't insert non-POD " + className( v ))); }
171 :
172 : template< class V >
173 9 : bool _insert( const std::string& key, const std::vector< V >& values,
174 : const boost::true_type& )
175 9 : { return _insert( key, values.data(), values.size() * sizeof( V )); }
176 : };
177 :
178 : template<> inline
179 3 : bool PersistentMap::_insert( const std::string& k, const std::string& v,
180 : const boost::false_type& )
181 : {
182 3 : return _insert( k, v.data(), v.length( ));
183 : }
184 :
185 : template< class V > inline
186 12 : std::vector< V > PersistentMap::getVector( const std::string& key )
187 : {
188 12 : const std::string& value = (*this)[ key ];
189 12 : return std::vector< V >( reinterpret_cast< const V* >( value.data( )),
190 24 : reinterpret_cast< const V* >( value.data() + value.size( )));
191 : }
192 :
193 : template< class V > inline
194 3 : std::set< V > PersistentMap::getSet( const std::string& key )
195 : {
196 3 : const std::string& value = (*this)[ key ];
197 3 : return std::set< V >( reinterpret_cast< const V* >( value.data( )),
198 3 : reinterpret_cast< const V* >( value.data() +
199 6 : value.size( )));
200 : }
201 :
202 :
203 : // inline std::ostream& operator << ( std::ostream& os, const PersistentMap& m )
204 : }
205 :
206 : #endif //LUNCHBOX_PERSISTENTMAP_H
|