Remove unneeded return statement
[platform/core/security/cynara.git] / src / service / storage / InMemoryStorageBackend.cpp
index ab80521..bf1c1c9 100644 (file)
  * @brief       Implementation of InMemoryStorageBackend
  */
 
+#include <errno.h>
+#include <fstream>
+#include <functional>
+#include <memory>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unordered_map>
+#include <vector>
+
+#include <log/log.h>
+#include <exceptions/BucketNotExistsException.h>
+#include <exceptions/CannotCreateFileException.h>
+#include <exceptions/FileNotFoundException.h>
+#include <exceptions/UnexpectedErrorException.h>
+#include <types/PolicyBucket.h>
+#include <types/PolicyResult.h>
+#include <types/PolicyType.h>
+
+#include <storage/BucketDeserializer.h>
+#include <storage/StorageDeserializer.h>
+#include <storage/StorageSerializer.h>
+
 #include "InMemoryStorageBackend.h"
 
 namespace Cynara {
 
-InMemoryStorageBackend::InMemoryStorageBackend() {
-    // Make sure, there's always default bucket
-    this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
+void InMemoryStorageBackend::load(void) {
+    std::string indexFilename = m_dbPath + m_indexFileName;
+
+    try {
+        std::shared_ptr<std::ifstream> indexStream = std::make_shared<std::ifstream>();
+        openFileStream(indexStream, indexFilename);
+
+        StorageDeserializer storageDeserializer(indexStream,
+            std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
+
+        storageDeserializer.initBuckets(buckets());
+        storageDeserializer.loadBuckets(buckets());
+    } catch (const FileNotFoundException &) {
+        LOGE("Reading cynara database failed.");
+    }
+
+    if (!hasBucket(defaultPolicyBucketId)) {
+            LOGN("Creating defaultBucket.");
+            this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
+    }
 }
 
-InMemoryStorageBackend::~InMemoryStorageBackend() {}
+void InMemoryStorageBackend::save(void) {
+
+    //create directory
+    int ret = mkdir(m_dbPath.c_str(), S_IRWXU);
+    if (ret < 0) {
+        int err = errno;
+        if (err != EEXIST) {
+            LOGE("Cannot create directory <%s>. Error [%d] : <%s>.",
+                 m_dbPath.c_str(), err, strerror(err));
+            throw UnexpectedErrorException(err, strerror(err));
+        }
+    }
+
+    std::shared_ptr<std::ofstream> indexStream = std::make_shared<std::ofstream>();
+    openDumpFileStream(indexStream, m_dbPath + m_indexFileName);
+
+    StorageSerializer storageSerializer(indexStream);
+    storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener,
+                           this, std::placeholders::_1));
+}
 
 PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
     return searchBucket(defaultPolicyBucketId, key);
@@ -37,8 +96,12 @@ PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
 
 PolicyBucket InMemoryStorageBackend::searchBucket(const PolicyBucketId &bucketId,
                                                   const PolicyKey &key) {
-    const auto &bucket = this->buckets().at(bucketId);
-    return bucket.filtered(key);
+    try {
+        const auto &bucket = this->buckets().at(bucketId);
+        return bucket.filtered(key);
+    } catch (const std::out_of_range &) {
+        throw BucketNotExistsException(bucketId);
+    }
 }
 
 void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
@@ -88,7 +151,7 @@ void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const
                 [key](PolicyPtr policy) -> bool {
                     return policy->key() == key;
             }), policies.end());
-    } catch(const std::out_of_range &) {
+    } catch (const std::out_of_range &) {
         throw BucketNotExistsException(bucketId);
     }
 }
@@ -105,7 +168,7 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
         return false;
     };
 
-    for(auto &bucketIter : buckets()) {
+    for (auto &bucketIter : buckets()) {
         // TODO: Move the erase code to PolicyCollection maybe?
         auto &bucket = bucketIter.second;
         auto &policies = bucket.policyCollection();
@@ -114,4 +177,44 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
     }
 }
 
+void InMemoryStorageBackend::openFileStream(std::shared_ptr<std::ifstream> stream,
+                                            const std::string &filename) {
+    // TODO: Consider adding exceptions to streams and handling them:
+    // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+    stream->open(filename);
+
+    if (!stream->is_open())
+        throw FileNotFoundException(filename);
+}
+
+void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr<std::ofstream> stream,
+                                                const std::string &filename) {
+    stream->open(filename, std::ofstream::out | std::ofstream::trunc);
+
+    if (!stream->is_open()) {
+        throw CannotCreateFileException(filename);
+    }
+}
+
+std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
+        const PolicyBucketId &bucketId) {
+    std::string bucketFilename = m_dbPath + "_" + bucketId;
+    std::shared_ptr<std::ifstream> bucketStream = std::make_shared<std::ifstream>();
+    try {
+        openFileStream(bucketStream, bucketFilename);
+        return std::make_shared<BucketDeserializer>(bucketStream);
+    } catch (const FileNotFoundException &) {
+        return nullptr;
+    }
+}
+
+std::shared_ptr<StorageSerializer> InMemoryStorageBackend::bucketDumpStreamOpener(
+        const PolicyBucketId &bucketId) {
+    std::string bucketFilename = m_dbPath + "_" + bucketId;
+    std::shared_ptr<std::ofstream> bucketStream = std::make_shared<std::ofstream>();
+
+    openDumpFileStream(bucketStream, bucketFilename);
+    return std::make_shared<StorageSerializer>(bucketStream);
+}
+
 } /* namespace Cynara */