Add loading database in Cynara::init 37/24637/5
authorAleksander Zdyb <a.zdyb@partner.samsung.com>
Thu, 17 Jul 2014 12:29:53 +0000 (14:29 +0200)
committerLukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Mon, 21 Jul 2014 09:10:07 +0000 (11:10 +0200)
Change-Id: Ie0d0774e4bc539ee4a33d87fb57afe33a5045952

packaging/cynara.spec
src/common/exceptions/FileNotFoundException.h [new file with mode: 0644]
src/service/CMakeLists.txt
src/service/main/Cynara.cpp
src/service/main/Cynara.h
src/service/main/main.cpp
src/service/storage/InMemoryStorageBackend.cpp
src/service/storage/InMemoryStorageBackend.h
src/service/storage/Storage.cpp
src/service/storage/Storage.h
src/service/storage/StorageBackend.h

index 4b68a35..aeca477 100644 (file)
@@ -17,6 +17,8 @@ BuildRequires: pkgconfig(libsystemd-journal)
 %global user_name %{name}
 %global group_name %{name}
 
+%global db_path %{_localstatedir}/%{name}/db/
+
 %global build_type %{?build_type:%build_type}%{!?build_type:RELEASE}
 
 %if %{?build_type} == "DEBUG"
@@ -84,6 +86,7 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
 export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
 %endif
 
+export CXXFLAGS="$CXXFLAGS -DCYNARA_DB_PATH=\\\"%{db_path}\\\""
 export LDFLAGS+="-Wl,--rpath=%{_libdir}"
 
 %cmake . -DVERSION=%{version} \
diff --git a/src/common/exceptions/FileNotFoundException.h b/src/common/exceptions/FileNotFoundException.h
new file mode 100644 (file)
index 0000000..e353c19
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/*
+ * @file        FileNotFoundException.h
+ * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file defines exception thrown when database file is not found
+ */
+
+#ifndef SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_
+#define SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_
+
+#include <string>
+
+#include <exceptions/DatabaseException.h>
+
+namespace Cynara {
+
+class FileNotFoundException : public DatabaseException {
+public:
+    FileNotFoundException(const std::string &filename) : m_filename(filename) {};
+    virtual ~FileNotFoundException() = default;
+
+    const std::string message(void) const {
+        if (m_message.empty()) {
+            m_message = "File " + filename() + " not found or corrupted badly";
+        }
+        return m_message;
+    }
+
+    const std::string &filename(void) const {
+        return m_filename;
+    }
+
+private:
+    mutable std::string m_message;
+    std::string m_filename;
+};
+
+} /* namespace Cynara */
+
+#endif /* SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_ */
index 915cc00..9f11ab8 100644 (file)
@@ -24,8 +24,11 @@ SET(CYNARA_SOURCES
     ${CYNARA_SERVICE_PATH}/main/main.cpp
     ${CYNARA_SERVICE_PATH}/sockets/Descriptor.cpp
     ${CYNARA_SERVICE_PATH}/sockets/SocketManager.cpp
+    ${CYNARA_SERVICE_PATH}/storage/BucketDeserializer.cpp
     ${CYNARA_SERVICE_PATH}/storage/InMemoryStorageBackend.cpp
     ${CYNARA_SERVICE_PATH}/storage/Storage.cpp
+    ${CYNARA_SERVICE_PATH}/storage/StorageDeserializer.cpp
+    ${CYNARA_SERVICE_PATH}/storage/StorageSerializer.cpp
     )
 
 SET_SOURCE_FILES_PROPERTIES(
index c99bbe4..20bb0ab 100644 (file)
@@ -23,6 +23,7 @@
 #include <memory>
 #include <stddef.h>
 
+#include <log/log.h>
 #include <exceptions/InitException.h>
 
 #include <logic/Logic.h>
@@ -43,16 +44,31 @@ Cynara::~Cynara() {
     finalize();
 }
 
+const std::string Cynara::storageDir(void) const {
+    std::string dir("/var/lib/cynara/db/");
+
+#ifdef CYNARA_DB_PATH
+    dir = CYNARA_DB_PATH;
+#else
+    LOGW("Cynara compiled without CYNARA_DB_PATH flag. Using default database directory.");
+#endif
+
+    LOGI("Cynara database path = <%s>", dir.c_str());
+    return dir;
+}
+
 void Cynara::init(void) {
     m_logic = std::make_shared<Logic>();
     m_socketManager = std::make_shared<SocketManager>();
-    m_storageBackend = std::make_shared<InMemoryStorageBackend>();
+    m_storageBackend = std::make_shared<InMemoryStorageBackend>(storageDir());
     m_storage = std::make_shared<Storage>(*m_storageBackend);
 
     m_logic->bindStorage(m_storage);
     m_logic->bindSocketManager(m_socketManager);
 
     m_socketManager->bindLogic(m_logic);
+
+    m_storage->load();
 }
 
 void Cynara::run(void) {
index 207e1b0..2e962c5 100644 (file)
@@ -34,6 +34,8 @@ private:
     StoragePtr m_storage;
     StorageBackendPtr m_storageBackend;
 
+    const std::string storageDir(void) const;
+
 public:
     Cynara();
     ~Cynara();
index 766a422..ce7b07b 100644 (file)
  * @brief       Main Cynara daemon file
  */
 
-//#include <errno.h>
 #include <exception>
-//#include <fcntl.h>
-//#include <signal.h>
-//#include <stdio.h>
 #include <stdlib.h>
-//#include <string.h>
-//#include <sys/prctl.h>
-//#include <sys/stat.h>
-//#include <sys/types.h>
-//#include <unistd.h>
 
 #include <systemd/sd-journal.h>
 #include <systemd/sd-daemon.h>
index b213111..1b7ae44 100644 (file)
  * @brief       Implementation of InMemoryStorageBackend
  */
 
+#include <fstream>
+#include <functional>
+
+#include <log/log.h>
+#include <exceptions/FileNotFoundException.h>
+#include <storage/BucketDeserializer.h>
+#include <storage/StorageDeserializer.h>
+#include <types/PolicyBucketId.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 + "buckets";
+
+    try {
+        std::ifstream indexStream;
+        openFileStream(indexStream, indexFilename);
 
-InMemoryStorageBackend::~InMemoryStorageBackend() {}
+        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() });
+    }
+}
 
 PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
     return searchBucket(defaultPolicyBucketId, key);
@@ -118,4 +142,25 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
     }
 }
 
+void InMemoryStorageBackend::openFileStream(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);
+}
+
+std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
+        const PolicyBucketId &bucketId) {
+    std::string bucketFilename = m_dbPath + "_" + bucketId;
+    std::ifstream bucketStream;
+    try {
+        openFileStream(bucketStream, bucketFilename);
+        return std::make_shared<BucketDeserializer>(bucketStream);
+    } catch (const FileNotFoundException &) {
+        return nullptr;
+    }
+}
+
 } /* namespace Cynara */
index 409a84c..1791b00 100644 (file)
 #ifndef INMEMORYSTORAGEBACKEND_H_
 #define INMEMORYSTORAGEBACKEND_H_
 
-#include "StorageBackend.h"
-#include <exceptions/NotImplementedException.h>
-#include <exceptions/BucketNotExistsException.h>
-#include <types/Policy.h>
-
-#include <unordered_map>
 #include <algorithm>
+#include <fstream>
 #include <functional>
 #include <iostream>
+#include <unordered_map>
+
+#include <exceptions/BucketNotExistsException.h>
+#include <exceptions/NotImplementedException.h>
+#include <storage/BucketDeserializer.h>
+#include <types/Policy.h>
+
+#include "StorageBackend.h"
 
 namespace Cynara {
 
-class InMemoryStorageBackend: public StorageBackend {
+class InMemoryStorageBackend : public StorageBackend {
 public:
     typedef std::unordered_map<PolicyBucketId, PolicyBucket> Buckets;
 
-    InMemoryStorageBackend();
-    virtual ~InMemoryStorageBackend();
+    InMemoryStorageBackend(const std::string &path) : m_dbPath(path) {
+    }
+
+    virtual ~InMemoryStorageBackend() = default;
+
+    virtual void load(void);
 
     virtual PolicyBucket searchDefaultBucket(const PolicyKey &key);
     virtual PolicyBucket searchBucket(const PolicyBucketId &bucketId, const PolicyKey &key);
@@ -52,7 +59,12 @@ public:
     virtual void deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key);
     virtual void deleteLinking(const PolicyBucketId &bucketId);
 
+protected:
+    void openFileStream(std::ifstream &stream, const std::string &filename);
+    std::shared_ptr<BucketDeserializer> bucketStreamOpener(const PolicyBucketId &bucketId);
+
 private:
+    std::string m_dbPath;
     Buckets m_buckets;
 
 protected:
index 60de8ff..319dbda 100644 (file)
@@ -121,4 +121,8 @@ void Storage::deletePolicies(const std::map<PolicyBucketId, std::vector<PolicyKe
     }
 }
 
+void Storage::load(void) {
+    m_backend.load();
+}
+
 } // namespace Cynara
index a52d1cc..b1c7cb3 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <map>
 #include <memory>
+#include <string>
 #include <tuple>
 #include <vector>
 
@@ -52,6 +53,8 @@ public:
     void addOrUpdateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultBucketPolicy);
     void deleteBucket(const PolicyBucketId &bucketId);
 
+    void load(void);
+
 protected:
     PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key);
 
index 6689bae..97e0fd7 100644 (file)
@@ -50,6 +50,8 @@ public:
 
     virtual void deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key) = 0;
     virtual void deleteLinking(const PolicyBucketId &bucket) = 0;
+
+    virtual void load(void) = 0;
 };
 
 } /* namespace Cynara */