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