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