Add first version
[ric-plt/sdl.git] / src / syncstorageimpl.cpp
diff --git a/src/syncstorageimpl.cpp b/src/syncstorageimpl.cpp
new file mode 100644 (file)
index 0000000..b73029c
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+   Copyright (c) 2018-2019 Nokia.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+#include <sstream>
+#include <sys/poll.h>
+#include <sdl/asyncstorage.hpp>
+#include <sdl/backenderror.hpp>
+#include <sdl/errorqueries.hpp>
+#include <sdl/invalidnamespace.hpp>
+#include <sdl/notconnected.hpp>
+#include <sdl/operationinterrupted.hpp>
+#include <sdl/rejectedbybackend.hpp>
+#include <sdl/rejectedbysdl.hpp>
+#include "private/redis/asyncredisstorage.hpp"
+#include "private/syncstorageimpl.hpp"
+#include "private/system.hpp"
+
+using namespace shareddatalayer;
+
+namespace
+{
+    void throwExceptionForErrorCode[[ noreturn ]](const std::error_code& ec)
+    {
+        if (ec == shareddatalayer::Error::BACKEND_FAILURE)
+            throw BackendError(ec.message());
+        else if (ec == shareddatalayer::Error::NOT_CONNECTED)
+            throw NotConnected(ec.message());
+        else if (ec == shareddatalayer::Error::OPERATION_INTERRUPTED)
+            throw OperationInterrupted(ec.message());
+        else if (ec == shareddatalayer::Error::REJECTED_BY_BACKEND)
+            throw RejectedByBackend(ec.message());
+        else if (ec == AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE)
+            throw InvalidNamespace(ec.message());
+        else if (ec == shareddatalayer::Error::REJECTED_BY_SDL)
+            throw RejectedBySdl(ec.message());
+
+        std::ostringstream os;
+        os << "No corresponding SDL exception found for error code: " << ec.category().name() << " " << ec.value();
+        throw std::range_error(os.str());
+    }
+}
+
+SyncStorageImpl::SyncStorageImpl(std::unique_ptr<AsyncStorage> asyncStorage):
+    SyncStorageImpl(std::move(asyncStorage), System::getSystem())
+{
+}
+
+SyncStorageImpl::SyncStorageImpl(std::unique_ptr<AsyncStorage> pAsyncStorage,
+                                 System& system):
+    asyncStorage(std::move(pAsyncStorage)),
+    system(system),
+    pFd(asyncStorage->fd()),
+    localStatus(false),
+    synced(false)
+{
+}
+
+void SyncStorageImpl::modifyAck(const std::error_code& error)
+{
+    synced = true;
+    localError = error;
+}
+
+void SyncStorageImpl::modifyIfAck(const std::error_code& error, bool status)
+{
+    synced = true;
+    localError = error;
+    localStatus = status;
+}
+
+void SyncStorageImpl::getAck(const std::error_code& error, const DataMap& dataMap)
+{
+    synced = true;
+    localError = error;
+    localMap = dataMap;
+}
+
+void SyncStorageImpl::findKeysAck(const std::error_code& error, const Keys& keys)
+{
+    synced = true;
+    localError = error;
+    localKeys = keys;
+}
+
+void SyncStorageImpl::verifyBackendResponse()
+{
+    if(localError)
+        throwExceptionForErrorCode(localError);
+}
+
+void SyncStorageImpl::waitForCallback()
+{
+    struct pollfd events { pFd, POLLIN, 0 };
+    while(!synced)
+        if (system.poll(&events, 1, -1) > 0 && (events.revents & POLLIN))
+            asyncStorage->handleEvents();
+}
+
+void SyncStorageImpl::waitSdlToBeReady(const Namespace& ns)
+{
+    synced = false;
+    asyncStorage->waitReadyAsync(ns,
+                                 std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
+                                           this,
+                                           std::error_code()));
+    waitForCallback();
+    verifyBackendResponse();
+}
+
+void SyncStorageImpl::set(const Namespace& ns, const DataMap& dataMap)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->setAsync(ns,
+                           dataMap,
+                           std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
+                                     this,
+                                     std::placeholders::_1));
+    waitForCallback();
+    verifyBackendResponse();
+}
+
+bool SyncStorageImpl::setIf(const Namespace& ns, const Key& key, const Data& oldData, const Data& newData)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->setIfAsync(ns,
+                             key,
+                             oldData,
+                             newData,
+                             std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
+                                       this,
+                                       std::placeholders::_1,
+                                       std::placeholders::_2));
+    waitForCallback();
+    verifyBackendResponse();
+    return localStatus;
+}
+
+bool SyncStorageImpl::setIfNotExists(const Namespace& ns, const Key& key, const Data& data)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->setIfNotExistsAsync(ns,
+                                      key,
+                                      data,
+                                      std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
+                                                this,
+                                                std::placeholders::_1,
+                                                std::placeholders::_2));
+    waitForCallback();
+    verifyBackendResponse();
+    return localStatus;
+}
+
+SyncStorageImpl::DataMap SyncStorageImpl::get(const Namespace& ns, const Keys& keys)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->getAsync(ns,
+                           keys,
+                           std::bind(&shareddatalayer::SyncStorageImpl::getAck,
+                                     this,
+                                     std::placeholders::_1,
+                                     std::placeholders::_2));
+    waitForCallback();
+    verifyBackendResponse();
+    return localMap;
+}
+
+void SyncStorageImpl::remove(const Namespace& ns, const Keys& keys)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->removeAsync(ns,
+                              keys,
+                              std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
+                                        this,
+                                        std::placeholders::_1));
+    waitForCallback();
+    verifyBackendResponse();
+}
+
+bool SyncStorageImpl::removeIf(const Namespace& ns, const Key& key, const Data& data)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->removeIfAsync(ns,
+                                key,
+                                data,
+                                std::bind(&shareddatalayer::SyncStorageImpl::modifyIfAck,
+                                          this,
+                                          std::placeholders::_1,
+                                          std::placeholders::_2));
+    waitForCallback();
+    verifyBackendResponse();
+    return localStatus;
+}
+
+SyncStorageImpl::Keys SyncStorageImpl::findKeys(const Namespace& ns, const std::string& keyPrefix)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->findKeysAsync(ns,
+                                keyPrefix,
+                                std::bind(&shareddatalayer::SyncStorageImpl::findKeysAck,
+                                          this,
+                                          std::placeholders::_1,
+                                          std::placeholders::_2));
+    waitForCallback();
+    verifyBackendResponse();
+    return localKeys;
+}
+
+void SyncStorageImpl::removeAll(const Namespace& ns)
+{
+    waitSdlToBeReady(ns);
+    synced = false;
+    asyncStorage->removeAllAsync(ns,
+                                 std::bind(&shareddatalayer::SyncStorageImpl::modifyAck,
+                                           this,
+                                           std::placeholders::_1));
+    waitForCallback();
+    verifyBackendResponse();
+}