Add first version
[ric-plt/sdl.git] / include / sdl / syncstorage.hpp
1 /*
2    Copyright (c) 2018-2019 Nokia.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17 #ifndef SHAREDDATALAYER_SYNCSTORAGE_HPP_
18 #define SHAREDDATALAYER_SYNCSTORAGE_HPP_
19
20 #include <cstdint>
21 #include <functional>
22 #include <map>
23 #include <memory>
24 #include <set>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 #include <sdl/exception.hpp>
29 #include <sdl/publisherid.hpp>
30
31 namespace shareddatalayer
32 {
33     /**
34      * @brief Class providing synchronous access to shared data layer storage.
35      *
36      * SyncStorage class provides synchronous access to all namespaces in
37      * shared data layer storage. Data can be saved, read and removed based on keys known
38      * to clients. Keys are unique within a namespace, namespace identifier is passed as
39      * a parameter to all operations.
40      *
41      * SyncStorage is primarily intended for command-line interface-typed applications, or
42      * non-event-loop based, such as multi-threaded applications, where shareddatalayer
43      * operations are carried out in a separate thread.
44      *
45      * @note The same instance of SyncStorage must not be shared between multiple threads
46      *       without explicit application level locking.
47      *
48      * @see AsyncStorage for asynchronous interface.
49      * @see AsyncStorage::SEPARATOR for namespace format restrictions.
50      */
51     class SyncStorage
52     {
53     public:
54         SyncStorage(const SyncStorage&) = delete;
55
56         SyncStorage& operator = (const SyncStorage&) = delete;
57
58         SyncStorage(SyncStorage&&) = delete;
59
60         SyncStorage& operator = (SyncStorage&&) = delete;
61
62         virtual ~SyncStorage() = default;
63
64         using Namespace = std::string;
65
66         using Key = std::string;
67
68         using Data = std::vector<uint8_t>;
69
70         using DataMap = std::map<Key, Data>;
71
72         /**
73          * Write data to shared data layer storage. Writing is done atomically, i.e. either
74          * all succeeds or all fails.
75          *
76          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
77          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
78          * for different shareddatalayer error situations is not needed.
79          *
80          * @param ns Namespace under which this operation is targeted.
81          * @param dataMap Data to be written.
82          *
83          * @throw BackendError if the backend data storage fails to process the request.
84          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
85          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
86          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
87          */
88         virtual void set(const Namespace& ns,
89                          const DataMap& dataMap) = 0;
90
91         /**
92          * Conditionally modify the value of a key if the current value in data storage
93          * matches the user's last known value.
94          *
95          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
96          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
97          * for different shareddatalayer error situations is not needed.
98          *
99          * @param ns Namespace under which this operation is targeted.
100          * @param key Key for which data modification will be executed.
101          * @param oldData Last known data.
102          * @param newData Data to be written.
103          *
104          * @return True for successful modification, false if the user's last known data did
105          *         not match the current value in data storage.
106          *
107          * @throw BackendError if the backend data storage fails to process the request.
108          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
109          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
110          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
111          */
112         virtual bool setIf(const Namespace& ns,
113                            const Key& key,
114                            const Data& oldData,
115                            const Data& newData) = 0;
116
117         /**
118          * Conditionally set the value of a key. If key already exists, then it's value
119          * is not modified. Checking the key existence and potential set operation is done
120          * as a one atomic operation.
121          *
122          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
123          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
124          * for different shareddatalayer error situations is not needed.
125          *
126          * @param ns Namespace under which this operation is targeted.
127          * @param key Key.
128          * @param data Data to be written.
129          *
130          * @return True if key didn't exist yet and set operation was executed, false if
131          *         key already existed and thus its value was left untouched.
132          *
133          * @throw BackendError if the backend data storage fails to process the request.
134          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
135          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
136          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
137          */
138         virtual bool setIfNotExists(const Namespace& ns,
139                                     const Key& key,
140                                     const Data& data) = 0;
141
142         using Keys = std::set<Key>;
143
144         /**
145          * Read data from shared data layer storage. Only those entries that are found will
146          * be returned.
147          *
148          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
149          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
150          * for different shareddatalayer error situations is not needed.
151          *
152          * @param ns Namespace under which this operation is targeted.
153          * @param keys Data to be read.
154          *
155          * @return Data from the storage.
156          *
157          * @throw BackendError if the backend data storage fails to process the request.
158          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
159          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
160          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
161          */
162         virtual DataMap get(const Namespace& ns,
163                             const Keys& keys) = 0;
164
165         /**
166          * Remove data from shared data layer storage. Existing keys are removed. Removing
167          * is done atomically, i.e. either all succeeds or all fails.
168          *
169          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
170          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
171          * for different shareddatalayer error situations is not needed.
172          *
173          * @param ns Namespace under which this operation is targeted.
174          * @param keys Data to be removed.
175          *
176          * @throw BackendError if the backend data storage fails to process the request.
177          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
178          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
179          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
180          */
181         virtual void remove(const Namespace& ns,
182                             const Keys& keys) = 0;
183
184         /**
185          * Conditionally remove data from shared data layer storage if the current data value
186          * matches the user's last known value.
187          *
188          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
189          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
190          * for different shareddatalayer error situations is not needed.
191          *
192          * @param ns Namespace under which this operation is targeted.
193          * @param key Data to be removed.
194          * @param data Last known value of data
195          *
196          * @return True if successful removal, false if the user's last known data did
197          *         not match the current value in data storage.
198          *
199          * @throw BackendError if the backend data storage fails to process the request.
200          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
201          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
202          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
203          */
204         virtual bool removeIf(const Namespace& ns,
205                               const Key& key,
206                               const Data& data) = 0;
207
208         /**
209          * Find all keys matching search pattern under the namespace. No prior knowledge about the keys in the given
210          * namespace exists, thus operation is not guaranteed to be atomic or isolated.
211          *
212          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
213          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
214          * for different shareddatalayer error situations is not needed.
215          *
216          * @param ns Namespace under which this operation is targeted.
217          * @param keyPrefix Only keys starting with given keyPrefix are returned. Passing empty string as
218          *                  keyPrefix will return all keys.
219          *
220          * @return Found keys.
221          *
222          * @throw BackendError if the backend data storage fails to process the request.
223          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
224          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
225          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
226          */
227         virtual Keys findKeys(const Namespace& ns,
228                               const std::string& keyPrefix) = 0;
229
230         /**
231          * Remove all keys under the namespace. Found keys are removed atomically, i.e.
232          * either all succeeds or all fails.
233          *
234          * Exceptions thrown (excluding standard exceptions such as std::bad_alloc) are all derived from
235          * shareddatalayer::Exception base class. Client can catch only that exception if separate handling
236          * for different shareddatalayer error situations is not needed.
237          *
238          * @param ns Namespace under which this operation is targeted.
239          *
240          * @throw BackendError if the backend data storage fails to process the request.
241          * @throw NotConnected if shareddatalayer is not connected to the backend data storage.
242          * @throw OperationInterrupted if shareddatalayer does not receive a reply from the backend data storage.
243          * @throw InvalidNamespace if given namespace does not meet the namespace format restrictions.
244          */
245         virtual void removeAll(const Namespace& ns) = 0;
246
247         /**
248          * Create a new instance of SyncStorage.
249          *
250          * @return New instance of SyncStorage.
251          *
252          * @throw EmptyNamespace if namespace string is an empty string.
253          * @throw InvalidNamespace if namespace contains illegal characters.
254          *
255          */
256         static std::unique_ptr<SyncStorage> create();
257
258     protected:
259         SyncStorage() = default;
260     };
261 }
262
263 #endif