New namespace (--ns) option in sdltool test-get-set -command
[ric-plt/sdl.git] / src / syncstorageimpl.cpp
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 #include <sstream>
23 #include <sys/poll.h>
24 #include <sdl/asyncstorage.hpp>
25 #include <sdl/backenderror.hpp>
26 #include <sdl/errorqueries.hpp>
27 #include <sdl/invalidnamespace.hpp>
28 #include <sdl/notconnected.hpp>
29 #include <sdl/operationinterrupted.hpp>
30 #include <sdl/rejectedbybackend.hpp>
31 #include <sdl/rejectedbysdl.hpp>
32 #include "private/redis/asyncredisstorage.hpp"
33 #include "private/syncstorageimpl.hpp"
34 #include "private/system.hpp"
35
36 using namespace shareddatalayer;
37
38 namespace
39 {
40     void throwExceptionForErrorCode[[ noreturn ]](const std::error_code& ec)
41     {
42         if (ec == shareddatalayer::Error::BACKEND_FAILURE)
43             throw BackendError(ec.message());
44         else if (ec == shareddatalayer::Error::NOT_CONNECTED)
45             throw NotConnected(ec.message());
46         else if (ec == shareddatalayer::Error::OPERATION_INTERRUPTED)
47             throw OperationInterrupted(ec.message());
48         else if (ec == shareddatalayer::Error::REJECTED_BY_BACKEND)
49             throw RejectedByBackend(ec.message());
50         else if (ec == AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE)
51             throw InvalidNamespace(ec.message());
52         else if (ec == shareddatalayer::Error::REJECTED_BY_SDL)
53             throw RejectedBySdl(ec.message());
54
55         std::ostringstream os;
56         os << "No corresponding SDL exception found for error code: " << ec.category().name() << " " << ec.value();
57         throw std::range_error(os.str());
58     }
59 }
60
61 SyncStorageImpl::SyncStorageImpl(std::unique_ptr<AsyncStorage> asyncStorage):
62     SyncStorageImpl(std::move(asyncStorage), System::getSystem())
63 {
64 }
65
66 SyncStorageImpl::SyncStorageImpl(std::unique_ptr<AsyncStorage> pAsyncStorage,
67                                  System& system):
68     asyncStorage(std::move(pAsyncStorage)),
69     system(system),
70     pFd(asyncStorage->fd()),
71     localStatus(false),
72     synced(false)
73 {
74 }
75
76 void SyncStorageImpl::modifyAck(const std::error_code& error)
77 {
78     synced = true;
79     localError = error;
80 }
81
82 void SyncStorageImpl::modifyIfAck(const std::error_code& error, bool status)
83 {
84     synced = true;
85     localError = error;
86     localStatus = status;
87 }
88
89 void SyncStorageImpl::getAck(const std::error_code& error, const DataMap& dataMap)
90 {
91     synced = true;
92     localError = error;
93     localMap = dataMap;
94 }
95
96 void SyncStorageImpl::findKeysAck(const std::error_code& error, const Keys& keys)
97 {
98     synced = true;
99     localError = error;
100     localKeys = keys;
101 }
102
103 void SyncStorageImpl::verifyBackendResponse()
104 {
105     if(localError)
106         throwExceptionForErrorCode(localError);
107 }
108
109 void SyncStorageImpl::waitForCallback()
110 {
111     struct pollfd events { pFd, POLLIN, 0 };
112     while(!synced)
113         if (system.poll(&events, 1, -1) > 0 && (events.revents & POLLIN))
114             asyncStorage->handleEvents();
115 }
116
117 void SyncStorageImpl::waitSdlToBeReady(const Namespace& ns)
118 {
119     synced = false;
120     asyncStorage->waitReadyAsync(ns,
121                                  std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
122                                            this,
123                                            std::error_code()));
124     waitForCallback();
125     verifyBackendResponse();
126 }
127
128 void SyncStorageImpl::set(const Namespace& ns, const DataMap& dataMap)
129 {
130     waitSdlToBeReady(ns);
131     synced = false;
132     asyncStorage->setAsync(ns,
133                            dataMap,
134                            std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
135                                      this,
136                                      std::placeholders::_1));
137     waitForCallback();
138     verifyBackendResponse();
139 }
140
141 bool SyncStorageImpl::setIf(const Namespace& ns, const Key& key, const Data& oldData, const Data& newData)
142 {
143     waitSdlToBeReady(ns);
144     synced = false;
145     asyncStorage->setIfAsync(ns,
146                              key,
147                              oldData,
148                              newData,
149                              std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
150                                        this,
151                                        std::placeholders::_1,
152                                        std::placeholders::_2));
153     waitForCallback();
154     verifyBackendResponse();
155     return localStatus;
156 }
157
158 bool SyncStorageImpl::setIfNotExists(const Namespace& ns, const Key& key, const Data& data)
159 {
160     waitSdlToBeReady(ns);
161     synced = false;
162     asyncStorage->setIfNotExistsAsync(ns,
163                                       key,
164                                       data,
165                                       std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
166                                                 this,
167                                                 std::placeholders::_1,
168                                                 std::placeholders::_2));
169     waitForCallback();
170     verifyBackendResponse();
171     return localStatus;
172 }
173
174 SyncStorageImpl::DataMap SyncStorageImpl::get(const Namespace& ns, const Keys& keys)
175 {
176     waitSdlToBeReady(ns);
177     synced = false;
178     asyncStorage->getAsync(ns,
179                            keys,
180                            std::bind(&shareddatalayer::SyncStorageImpl::getAck,
181                                      this,
182                                      std::placeholders::_1,
183                                      std::placeholders::_2));
184     waitForCallback();
185     verifyBackendResponse();
186     return localMap;
187 }
188
189 void SyncStorageImpl::remove(const Namespace& ns, const Keys& keys)
190 {
191     waitSdlToBeReady(ns);
192     synced = false;
193     asyncStorage->removeAsync(ns,
194                               keys,
195                               std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
196                                         this,
197                                         std::placeholders::_1));
198     waitForCallback();
199     verifyBackendResponse();
200 }
201
202 bool SyncStorageImpl::removeIf(const Namespace& ns, const Key& key, const Data& data)
203 {
204     waitSdlToBeReady(ns);
205     synced = false;
206     asyncStorage->removeIfAsync(ns,
207                                 key,
208                                 data,
209                                 std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
210                                           this,
211                                           std::placeholders::_1,
212                                           std::placeholders::_2));
213     waitForCallback();
214     verifyBackendResponse();
215     return localStatus;
216 }
217
218 SyncStorageImpl::Keys SyncStorageImpl::findKeys(const Namespace& ns, const std::string& keyPrefix)
219 {
220     waitSdlToBeReady(ns);
221     synced = false;
222     asyncStorage->findKeysAsync(ns,
223                                 keyPrefix,
224                                 std::bind(&shareddatalayer::SyncStorageImpl::findKeysAck,
225                                           this,
226                                           std::placeholders::_1,
227                                           std::placeholders::_2));
228     waitForCallback();
229     verifyBackendResponse();
230     return localKeys;
231 }
232
233 void SyncStorageImpl::removeAll(const Namespace& ns)
234 {
235     waitSdlToBeReady(ns);
236     synced = false;
237     asyncStorage->removeAllAsync(ns,
238                                  std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
239                                            this,
240                                            std::placeholders::_1));
241     waitForCallback();
242     verifyBackendResponse();
243 }