Reorganize directory structure
authorSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 8 Nov 2019 06:20:40 +0000 (15:20 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 8 Nov 2019 06:20:40 +0000 (15:20 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
35 files changed:
plugins/bluetooth/bluetooth.cpp
plugins/wifi/wifi.cpp
src/vist/CMakeLists.txt
src/vist/policy/CMakeLists.txt
src/vist/policy/api.cpp [new file with mode: 0644]
src/vist/policy/api.hpp
src/vist/policy/core/api.cpp [deleted file]
src/vist/policy/core/db-schema.hpp [deleted file]
src/vist/policy/core/policy-loader.cpp [deleted file]
src/vist/policy/core/policy-loader.hpp [deleted file]
src/vist/policy/core/policy-manager.cpp [deleted file]
src/vist/policy/core/policy-manager.hpp [deleted file]
src/vist/policy/core/policy-storage.cpp [deleted file]
src/vist/policy/core/policy-storage.hpp [deleted file]
src/vist/policy/core/tests/core.cpp [deleted file]
src/vist/policy/core/tests/storage.cpp [deleted file]
src/vist/policy/db-schema.hpp [new file with mode: 0644]
src/vist/policy/policy-loader.cpp [new file with mode: 0644]
src/vist/policy/policy-loader.hpp [new file with mode: 0644]
src/vist/policy/policy-manager.cpp [new file with mode: 0644]
src/vist/policy/policy-manager.hpp [new file with mode: 0644]
src/vist/policy/policy-storage.cpp [new file with mode: 0644]
src/vist/policy/policy-storage.hpp [new file with mode: 0644]
src/vist/policy/sdk/policy-model.hpp [deleted file]
src/vist/policy/sdk/policy-provider.hpp [deleted file]
src/vist/policy/sdk/policy-value.hpp [deleted file]
src/vist/policy/sdk/tests/sdk.cpp [deleted file]
src/vist/policy/tests/core.cpp [new file with mode: 0644]
src/vist/policy/tests/storage.cpp [new file with mode: 0644]
src/vist/sdk/CMakeLists.txt [new file with mode: 0644]
src/vist/sdk/policy-model.hpp [new file with mode: 0644]
src/vist/sdk/policy-provider.hpp [new file with mode: 0644]
src/vist/sdk/policy-value.hpp [new file with mode: 0644]
src/vist/sdk/tests/sdk.cpp [new file with mode: 0644]
src/vist/service/tests/core.cpp

index 0caa39eb4dd31733d9264e8c795b8769bc156d1c..32da9bb5d708ae0fce41819dda4b35c38a3766f3 100644 (file)
@@ -18,8 +18,8 @@
 #include <bluetooth-api.h>
 #include <bluetooth_internal.h>
 
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
 
 #include <memory>
 
index 95ca32e9b61092e4678088301ba9621258481ab3..5dff58fb848a8dbe657c23ec8e1199dc470c8d4d 100644 (file)
@@ -17,8 +17,8 @@
 #include <arpa/inet.h>
 #include <wifi-manager.h>
 
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
 
 #include <klay/dbus/connection.h>
 
index fb12f6f1a4ecdffb56f2b1dce36241ab136eb81e..26157a94034b532b572846c3671ddaee83937bb5 100644 (file)
@@ -31,6 +31,7 @@ ADD_DEFINITIONS(-DDB_PATH="${DB_INSTALL_DIR}/.vist.db"
 ADD_SUBDIRECTORY(client)
 ADD_SUBDIRECTORY(notification)
 ADD_SUBDIRECTORY(policy)
+ADD_SUBDIRECTORY(sdk)
 ADD_SUBDIRECTORY(service)
 
 ADD_LIBRARY(${TARGET_VIST_LIB} STATIC ${${TARGET_VIST_LIB}_SRCS})
index fc297901db2e1258fccdbd79017e59c4f1c09429..5387a8eafe715665b3583ff95500216f25afbc98 100644 (file)
@@ -17,19 +17,16 @@ SET(${TARGET_VIST_POLICY_LIB}_SRCS "")
 
 PKG_CHECK_MODULES(VIST_POLICY_DEPS REQUIRED klay dlog)
 
-INCLUDE_DIRECTORIES(SYSTEM . common ${VIST_POLICY_DEPS_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM . ${VIST_POLICY_DEPS_INCLUDE_DIRS})
 
-ADD_VIST_POLICY_LIBRARY(vist_policy_core core/api.cpp
-                                                                                core/policy-manager.cpp
-                                                                                core/policy-loader.cpp
-                                                                                core/policy-storage.cpp)
+ADD_VIST_POLICY_LIBRARY(vist_policy_core api.cpp
+                                                                                policy-manager.cpp
+                                                                                policy-loader.cpp
+                                                                                policy-storage.cpp)
 
-FILE(GLOB POLICY_CORE_TESTS "core/tests/*.cpp")
+FILE(GLOB POLICY_CORE_TESTS "tests/*.cpp")
 ADD_VIST_TEST(${POLICY_CORE_TESTS})
 
-FILE(GLOB POLICY_SDK_TESTS "sdk/tests/*.cpp")
-ADD_VIST_TEST(${POLICY_SDK_TESTS})
-
 ADD_LIBRARY(${TARGET_VIST_POLICY_LIB} STATIC ${${TARGET_VIST_POLICY_LIB}_SRCS})
 TARGET_LINK_LIBRARIES(${TARGET_VIST_POLICY_LIB} ${VIST_POLICY_DEPS_LIBRARIES}
                                                                                                pthread
diff --git a/src/vist/policy/api.cpp b/src/vist/policy/api.cpp
new file mode 100644 (file)
index 0000000..0a38eb5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include <vist/policy/api.hpp>
+
+#include "policy-manager.hpp"
+
+namespace vist {
+namespace policy {
+
+PolicyValue API::Get(const std::string& policy)
+{
+       return PolicyManager::Instance().get(policy);
+}
+
+std::unordered_map<std::string, PolicyValue> API::GetAll()
+{
+       return PolicyManager::Instance().getAll();
+}
+
+void API::Admin::Set(const std::string& policy, const PolicyValue& value)
+{
+       // TODO(Sangwan): Get admin name from peer PID
+       PolicyManager::Instance().set(policy, value, "admin");
+}
+
+void API::Admin::Enroll(const std::string& admin)
+{
+       PolicyManager::Instance().enroll(admin);
+}
+
+void API::Admin::Disenroll(const std::string& admin)
+{
+       PolicyManager::Instance().disenroll(admin);
+}
+
+std::vector<std::string> API::Admin::GetAll()
+{
+       return PolicyManager::Instance().getAdmins();
+}
+
+} // namespace policy
+} // namespace vist
index bd8aa913c91ae2aa6b1003fad50ba9789e700cec..6c15af82cf5e57eb1e3983fa1c2daf59ec926319 100644 (file)
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include <vist/policy/sdk/policy-value.hpp>
+#include <vist/sdk/policy-value.hpp>
 
 #include <string>
 #include <unordered_map>
diff --git a/src/vist/policy/core/api.cpp b/src/vist/policy/core/api.cpp
deleted file mode 100644 (file)
index 0a38eb5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include <vist/policy/api.hpp>
-
-#include "policy-manager.hpp"
-
-namespace vist {
-namespace policy {
-
-PolicyValue API::Get(const std::string& policy)
-{
-       return PolicyManager::Instance().get(policy);
-}
-
-std::unordered_map<std::string, PolicyValue> API::GetAll()
-{
-       return PolicyManager::Instance().getAll();
-}
-
-void API::Admin::Set(const std::string& policy, const PolicyValue& value)
-{
-       // TODO(Sangwan): Get admin name from peer PID
-       PolicyManager::Instance().set(policy, value, "admin");
-}
-
-void API::Admin::Enroll(const std::string& admin)
-{
-       PolicyManager::Instance().enroll(admin);
-}
-
-void API::Admin::Disenroll(const std::string& admin)
-{
-       PolicyManager::Instance().disenroll(admin);
-}
-
-std::vector<std::string> API::Admin::GetAll()
-{
-       return PolicyManager::Instance().getAdmins();
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/db-schema.hpp b/src/vist/policy/core/db-schema.hpp
deleted file mode 100644 (file)
index 2bdf75b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <string>
-
-namespace vist {
-namespace policy {
-namespace schema {
-
-struct Admin {
-       std::string name;
-};
-
-struct PolicyActivated {
-       std::string admin;
-       std::string policy;
-       int value = -1;
-};
-
-struct PolicyDefinition {
-       std::string name;
-       int ivalue = -1;
-};
-
-} // namespace schema
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-loader.cpp b/src/vist/policy/core/policy-loader.cpp
deleted file mode 100644 (file)
index 28c3b41..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include "policy-loader.hpp"
-
-namespace vist {
-namespace policy {
-
-PolicyProvider* PolicyLoader::load(const std::string& path)
-{
-       PluginLoader loader(path);
-       PolicyProvider::FactoryType factory = nullptr;
-       loader.load(PolicyProvider::getFactoryName(), factory);
-       if (factory == nullptr)
-               std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName());
-
-       auto provider = (*factory)();
-       if (provider == nullptr)
-               std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName());
-
-       return provider;
-}
-
-PluginLoader::PluginLoader(const std::string& path, int flag)
-       : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;})
-// Cleaning object after dlclose() makes SEGFAULT.
-// TODO: Sync dynamic loading's life-cycle with program.(PluginManager)
-//     : handle(::dlopen(path.c_str(), flag), ::dlclose)
-{
-       if (handle == nullptr)
-               throw std::invalid_argument("Failed to open: " + path);
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-loader.hpp b/src/vist/policy/core/policy-loader.hpp
deleted file mode 100644 (file)
index b463fd6..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-provider.hpp>
-
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-#include <dlfcn.h>
-
-namespace vist {
-namespace policy {
-
-struct PolicyLoader final {
-       static PolicyProvider* load(const std::string& path);
-};
-
-class PluginLoader final {
-public:
-       explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY);
-
-       template<typename T>
-       void load(const std::string& name, T& symbol);
-
-private:
-       using Handle = std::unique_ptr<void, int(*)(void*)>;
-       Handle handle;
-};
-
-template<typename T>
-void PluginLoader::load(const std::string& name, T& symbol)
-{
-       symbol = reinterpret_cast<T>(::dlsym(handle.get(), name.c_str()));
-       if (symbol == nullptr)
-               throw std::runtime_error("Failed to load: " + name);
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-manager.cpp b/src/vist/policy/core/policy-manager.cpp
deleted file mode 100644 (file)
index f1bd3e5..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include "policy-manager.hpp"
-#include "policy-loader.hpp"
-
-#include <vist/logger.hpp>
-
-#include <klay/filesystem.h>
-
-namespace vist {
-namespace policy {
-
-PolicyManager::PolicyManager() : storage(DB_PATH)
-{
-       loadProviders(PLUGIN_INSTALL_DIR);
-       int cnt = loadPolicies();
-       INFO(VIST) << std::to_string(cnt) << "-policies loaded";
-}
-
-std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
-{
-       INFO(VIST) << "Load policies from :" << path;
-       klay::File dir(path);
-       if (!dir.exists() || !dir.isDirectory())
-               throw std::invalid_argument("Plugin directory is wrong.: " + path);
-
-       int passed = 0, failed = 0;
-       klay::DirectoryIterator end;
-       for (klay::DirectoryIterator iter(path); iter != end; ++iter) {
-               if (!iter->isFile())
-                       continue;
-
-               try {
-                       auto provider = PolicyLoader::load(iter->getPath());
-                       DEBUG(VIST) << "Loaded provider: " << provider->getName();
-
-                       bool exist = false;
-                       for (const auto& p : this->providers) {
-                               if (p->getName() == provider->getName()) {
-                                       exist = true;
-                                       break;
-                               }
-                       }
-
-                       if (!exist)
-                               this->providers.emplace_back(std::move(provider));
-               } catch (const std::exception& e) {
-                       ++failed;
-                       ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what();
-                       continue;
-               }
-
-               ++passed;
-       }
-
-       INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed;
-       return std::make_pair(passed, failed);
-}
-
-int PolicyManager::loadPolicies()
-{
-       bool changed = false;
-
-       /// Make policy-provider map for performance
-       for (const auto& provider : providers) {
-               for (const auto& pair : provider->policies) {
-                       policies[pair.first] = provider->getName();
-
-                       /// Check the policy is defined on policy-storage
-                       if (!storage.exists(pair.first)) {
-                               INFO(VIST) << "Define policy: " << pair.first;
-                               storage.define(pair.first, pair.second->getInitial().value);
-                               changed = true;
-                       }
-               }
-       }
-
-       if (changed)
-               storage.syncPolicyDefinition();
-
-       return policies.size();
-}
-
-void PolicyManager::enroll(const std::string& admin)
-{
-       this->storage.enroll(admin);
-}
-
-void PolicyManager::disenroll(const std::string& admin)
-{
-       this->storage.disenroll(admin);
-}
-
-void PolicyManager::set(const std::string& policy,
-                                               const PolicyValue& value,
-                                               const std::string& admin)
-{
-       if (this->policies.find(policy) == this->policies.end())
-               std::runtime_error("Not exist policy: " + policy);
-
-       storage.update(admin, policy, value);
-
-       for (auto& p : providers) {
-               if (p->getName() != this->policies[policy])
-                       continue;
-
-               if (p->policies.find(policy) != p->policies.end()) {
-                       p->policies[policy]->set(value);
-                       return;
-               }
-       }
-}
-
-PolicyValue PolicyManager::get(const std::string& policy)
-{
-       return storage.strictest(policy);
-}
-
-std::unordered_map<std::string, PolicyValue> PolicyManager::getAll()
-{
-       return storage.strictest();
-}
-
-std::vector<std::string> PolicyManager::getAdmins()
-{
-       return storage.getAdmins();
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-manager.hpp b/src/vist/policy/core/policy-manager.hpp
deleted file mode 100644 (file)
index bdc364b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-provider.hpp>
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include "policy-storage.hpp"
-
-#include <exception>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <gtest/gtest_prod.h>
-
-namespace vist {
-namespace policy {
-
-class PolicyManager final {
-public:
-       PolicyManager(const PolicyManager&) = delete;
-       PolicyManager& operator=(const PolicyManager&) = delete;
-
-       PolicyManager(PolicyManager&&) = delete;
-       PolicyManager& operator=(PolicyManager&&) = delete;
-
-       static PolicyManager& Instance()
-       {
-               static PolicyManager manager;
-               return manager;
-       }
-
-       void enroll(const std::string& admin);
-       void disenroll(const std::string& admin);
-
-       void set(const std::string& policy,
-                        const PolicyValue& value,
-                        const std::string& admin);
-       PolicyValue get(const std::string& policy);
-       std::unordered_map<std::string, PolicyValue> getAll();
-
-       std::vector<std::string> getAdmins();
-
-private:
-       explicit PolicyManager();
-       ~PolicyManager() = default;
-
-       std::pair<int, int> loadProviders(const std::string& path);
-       int loadPolicies();
-
-       PolicyStorage storage;
-       std::vector<std::unique_ptr<PolicyProvider>> providers;
-
-       /// Policy-Provider
-       std::unordered_map<std::string, std::string> policies;
-
-       FRIEND_TEST(PolicyCoreTests, policy_loader);
-};
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-storage.cpp b/src/vist/policy/core/policy-storage.cpp
deleted file mode 100644 (file)
index 6cc3798..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include "policy-storage.hpp"
-
-#include <vist/logger.hpp>
-#include <vist/query-builder.hpp>
-
-#include <klay/db/column.h>
-#include <klay/db/statement.h>
-#include <klay/exception.h>
-
-#include <algorithm>
-#include <fstream>
-
-using namespace vist::tsqb;
-using namespace vist::policy::schema;
-
-namespace {
-
-auto adminTable = make_table("ADMIN", make_column("name", &Admin::name));
-
-auto polActivatedTable = make_table("POLICY_ACTIVATED",
-                                                                       make_column("admin", &PolicyActivated::admin),
-                                                                       make_column("policy", &PolicyActivated::policy),
-                                                                       make_column("value", &PolicyActivated::value));
-
-auto polDefinitionTable = make_table("POLICY_DEFINITION",
-                                                                        make_column("name", &PolicyDefinition::name),
-                                                                        make_column("ivalue", &PolicyDefinition::ivalue));
-
-const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR;
-const std::string SCRIPT_CREATE_SCHEMA  = "create-schema";
-
-} // anonymous namespace
-
-namespace vist {
-namespace policy {
-
-PolicyStorage::PolicyStorage(const std::string& path) :
-       database(std::make_shared<database::Connection>(path,
-                                                                                                       database::Connection::ReadWrite |
-                                                                                                       database::Connection::Create))
-{
-       database->exec("PRAGMA foreign_keys = ON;");
-       database->exec(getScript(SCRIPT_CREATE_SCHEMA));
-
-       sync();
-}
-
-void PolicyStorage::sync()
-{
-       DEBUG(VIST) << "Sync policy storage to cache object.";
-       syncAdmin();
-       syncPolicyActivated();
-       syncPolicyDefinition();
-}
-
-void PolicyStorage::syncPolicyDefinition()
-{
-       this->definitions.clear();
-       std::string query = polDefinitionTable.selectAll();
-       database::Statement stmt(*database, query);
-
-       while (stmt.step()) {
-               PolicyDefinition pd;
-               pd.name = std::string(stmt.getColumn(0));
-               pd.ivalue = stmt.getColumn(1);
-               DEBUG(VIST) << "Defined policy:" << pd.name;
-               this->definitions.emplace(pd.name, std::move(pd));
-       }
-
-       DEBUG(VIST) << definitions.size() << "- policies synced.";
-}
-
-void PolicyStorage::syncAdmin()
-{
-       this->admins.clear();
-       std::string query = adminTable.selectAll();
-       database::Statement stmt(*database, query);
-
-       while (stmt.step())
-               this->admins.emplace_back(std::string(stmt.getColumn(0)));
-
-       DEBUG(VIST) << admins.size() << "-admins synced.";
-}
-
-void PolicyStorage::syncPolicyActivated()
-{
-       this->activatedPolicies.clear();
-       std::string query = polActivatedTable.selectAll();
-       database::Statement stmt(*database, query);
-
-       while (stmt.step()) {
-               PolicyActivated pa;
-               pa.admin = std::string(stmt.getColumn(0));
-               pa.policy = std::string(stmt.getColumn(1));
-               pa.value = stmt.getColumn(2);
-               this->activatedPolicies.emplace(pa.policy, std::move(pa));
-       }
-
-       DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced.";
-}
-
-std::string PolicyStorage::getScript(const std::string& name)
-{
-       std::string path = SCRIPT_BASE + "/" + name + ".sql";
-       std::ifstream is(path);
-       if (is.fail())
-               throw std::invalid_argument("Failed to open script: " + path); 
-
-       std::istreambuf_iterator<char> begin(is), end;
-       auto content = std::string(begin, end);
-       if (content.empty())
-               throw std::runtime_error("Failed to read script: " + path); 
-
-       return content;
-}
-
-void PolicyStorage::define(const std::string& policy, int ivalue)
-{
-       if (definitions.find(policy) != definitions.end()) {
-               INFO(VIST) << "Policy is already defined: " << policy;
-               return;
-       }
-
-       PolicyDefinition pd;
-       pd.name = policy;
-       pd.ivalue = ivalue;
-
-       std::string query = polDefinitionTable.insert(&PolicyDefinition::name,
-                                                                                                 &PolicyDefinition::ivalue);
-       database::Statement stmt(*database, query);
-       stmt.bind(1, pd.name);
-       stmt.bind(2, pd.ivalue);
-       if (!stmt.exec())
-               throw std::runtime_error("Failed to define policy: " + pd.name);
-}
-
-void PolicyStorage::enroll(const std::string& name)
-{
-       INFO(VIST) << "Enroll admin: " << name;
-       if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
-               ERROR(VIST) << "Admin is aleady enrolled.: " << name;
-               return;
-       }
-
-       std::string query = adminTable.insert(&Admin::name);
-       DEBUG(VIST) << "Enroll admin query statement: " << query;
-       database::Statement stmt(*database, query);
-       stmt.bind(1, name);
-       if (!stmt.exec())
-               throw std::runtime_error("Failed to enroll admin: " + name);
-
-       admins.push_back(name);
-       /// PolicyActivated is triggered by enrolling admin.
-       syncPolicyActivated();
-
-       int count = activatedPolicies.size() / admins.size();
-       INFO(VIST) << "Admin[" << name << "] manages "
-                          << std::to_string(count) << "-policies.";
-}
-
-void PolicyStorage::disenroll(const std::string& name)
-{
-       INFO(VIST) << "Disenroll admin: " << name;
-       auto iter = std::find(admins.begin(), admins.end(), name);
-       if (iter == admins.end()) {
-               ERROR(VIST) << "Not exist admin: " << name;
-               return;
-       } else {
-               admins.erase(iter);
-       }
-
-       std::string query = adminTable.remove().where(expr(&Admin::name) == name);
-       database::Statement stmt(*database, query);
-       stmt.bind(1, name);
-       if (!stmt.exec())
-               throw std::runtime_error("Failed to disenroll admin: " + name);
-}
-
-void PolicyStorage::update(const std::string& admin,
-                                                  const std::string& policy,
-                                                  const PolicyValue& value)
-{
-       DEBUG(VIST) << "Policy-update is called by admin: " << admin
-                               << ", about: " << policy << ", value: " << std::to_string(value);
-
-       if (std::find(admins.begin(), admins.end(), admin) == admins.end())
-               throw std::runtime_error("Not exist admin: " + admin);
-
-       if (definitions.find(policy) == definitions.end())
-               throw std::runtime_error("Not exist policy: " + policy);
-
-       int policyValue = value;
-       std::string query = polActivatedTable.update(&PolicyActivated::value)
-                                                                          .where(expr(&PolicyActivated::admin) == admin &&
-                                                                                         expr(&PolicyActivated::policy) == policy);
-       database::Statement stmt(*database, query);
-       stmt.bind(1, policyValue);
-       stmt.bind(2, admin);
-       stmt.bind(3, policy);
-       if (!stmt.exec())
-               throw runtime::Exception("Failed to update policy:" + policy);
-
-       syncPolicyActivated();
-}
-
-PolicyValue PolicyStorage::strictest(const std::string& policy)
-{
-       if (definitions.find(policy) == definitions.end())
-               throw std::runtime_error("Not exist policy: " + policy);
-
-       // There is no enrolled admins.
-       if (activatedPolicies.size() == 0)
-               return PolicyValue(definitions[policy].ivalue);
-
-       std::shared_ptr<PolicyValue> strictestPtr = nullptr;
-       auto range = activatedPolicies.equal_range(policy);
-       for (auto iter = range.first; iter != range.second; iter++) {
-               int value = iter->second.value;
-               if (strictestPtr == nullptr)
-                       strictestPtr = std::make_shared<PolicyValue>(value);
-               else
-                       strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value;
-
-               DEBUG(VIST) << "The strictest of policy[" << policy
-                                       << "] : " + std::to_string(strictestPtr->value);
-       }
-
-       if (strictestPtr == nullptr)
-               throw std::runtime_error("Not exist managed policy: " + policy);
-
-       return std::move(*strictestPtr);
-}
-
-std::unordered_map<std::string, PolicyValue> PolicyStorage::strictest()
-{
-       std::unordered_map<std::string, PolicyValue> policies;
-       for (const auto& pair : definitions) {
-               std::string name = pair.first;
-               auto value = this->strictest(name);
-
-               policies.emplace(std::move(name), std::move(value));
-       }
-
-       return policies;
-}
-
-const std::vector<std::string>& PolicyStorage::getAdmins() const noexcept
-{
-       return admins;
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/policy-storage.hpp b/src/vist/policy/core/policy-storage.hpp
deleted file mode 100644 (file)
index cec538d..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- *
- *      ttp://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
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include "db-schema.hpp"
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include <klay/db/connection.h>
-
-namespace vist {
-namespace policy {
-
-using namespace schema;
-
-class PolicyStorage final {
-public:
-       explicit PolicyStorage(const std::string& path);
-
-       /// TODO(Sangwan): Consider to support lazy sync
-       void sync();
-
-       void syncAdmin();
-       void syncPolicyActivated();
-       void syncPolicyDefinition();
-
-       inline bool exists(const std::string& policy) const noexcept
-       {
-               return definitions.find(policy) != definitions.end();
-       }
-
-       inline bool isActivated() const noexcept
-       {
-               return admins.size() > 0 && activatedPolicies.size() > 0;
-       }
-
-       void enroll(const std::string& admin);
-       void disenroll(const std::string& admin);
-
-       void define(const std::string& policy, int ivalue);
-       void update(const std::string& admin,
-                               const std::string& policy,
-                               const PolicyValue& value);
-
-       PolicyValue strictest(const std::string& policy);
-       /// Return all strictest policy values
-       std::unordered_map<std::string, PolicyValue> strictest();
-
-       const std::vector<std::string>& getAdmins() const noexcept;
-
-private:
-       std::string getScript(const std::string& name);
-
-       std::shared_ptr<klay::database::Connection> database;
-
-       /// DB Cache objects
-       /// TODO(Sangwan): add locking mechanism
-       std::vector<std::string> admins;
-       std::unordered_map<std::string, PolicyActivated> activatedPolicies;
-       std::unordered_map<std::string, PolicyDefinition> definitions;
-};
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/tests/core.cpp b/src/vist/policy/core/tests/core.cpp
deleted file mode 100644 (file)
index 2cf5bb8..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include <gtest/gtest.h>
-
-#include <vist/policy/core/policy-manager.hpp>
-
-namespace vist {
-namespace policy {
-
-class PolicyCoreTests : public testing::Test {};
-
-TEST_F(PolicyCoreTests, policy_loader) {
-       auto& manager = PolicyManager::Instance();
-
-       EXPECT_TRUE(manager.providers.size() > 0);
-       EXPECT_TRUE(manager.policies.size() > 0);
-}
-
-TEST_F(PolicyCoreTests, policy_set_get) {
-       auto& manager = PolicyManager::Instance();
-       manager.enroll("testAdmin");
-       manager.set("bluetooth", PolicyValue(5), "testAdmin");
-
-       auto policy = manager.get("bluetooth");
-       EXPECT_EQ(policy.value, 5);
-
-       manager.enroll("testAdmin1");
-       manager.set("bluetooth", PolicyValue(10), "testAdmin1");
-
-       /// Manager should return the strongest policy.
-       policy = manager.get("bluetooth");
-       EXPECT_EQ(policy.value, 5);
-
-       manager.disenroll("testAdmin");
-       manager.disenroll("testAdmin1");
-}
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/core/tests/storage.cpp b/src/vist/policy/core/tests/storage.cpp
deleted file mode 100644 (file)
index 369fb00..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include <gtest/gtest.h>
-
-#include <memory>
-
-#include <vist/policy/core/policy-storage.hpp>
-
-using namespace vist::policy;
-
-class PolicyStorageTests : public testing::Test {
-public:
-       void SetUp() override
-       {
-               this->storage = std::make_shared<PolicyStorage>(DB_PATH);
-       }
-
-       std::shared_ptr<PolicyStorage> getStorage()
-       {
-               return this->storage;
-       }
-
-private:
-       std::shared_ptr<PolicyStorage> storage = nullptr;
-};
-
-TEST_F(PolicyStorageTests, initialize)
-{
-       bool isRaised = false;
-
-       try {
-               // DB is maden at run-time
-               PolicyStorage storage("/tmp/dummy");
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-
-       EXPECT_FALSE(isRaised);
-}
-
-TEST_F(PolicyStorageTests, enrollment)
-{
-       auto storage = getStorage();
-       EXPECT_FALSE(storage->isActivated());
-
-       storage->enroll("testAdmin0");
-       storage->enroll("testAdmin1");
-       EXPECT_TRUE(storage->isActivated());
-
-       storage->disenroll("testAdmin0");
-       EXPECT_TRUE(storage->isActivated());
-
-       storage->disenroll("testAdmin1");
-       EXPECT_FALSE(storage->isActivated());
-}
-
-TEST_F(PolicyStorageTests, update)
-{
-       auto storage = getStorage();
-       storage->enroll("testAdmin");
-
-       bool isRaised = false;
-       try {
-               storage->update("fakeAdmin", "bluetooth", PolicyValue(0));
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-
-       isRaised = false;
-       try {
-               storage->update("testAdmin", "bluetooth", PolicyValue(0));
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-       EXPECT_FALSE(isRaised);
-
-       isRaised = false;
-       try {
-               storage->update("testAdmin", "FakePolicy", PolicyValue(0));
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-       EXPECT_TRUE(isRaised);
-
-       storage->disenroll("testAdmin");
-}
-
-TEST_F(PolicyStorageTests, strictest)
-{
-       auto storage = getStorage();
-       storage->enroll("testAdmin0");
-       storage->enroll("testAdmin1");
-
-       storage->update("testAdmin0", "bluetooth", PolicyValue(3));
-       storage->update("testAdmin1", "bluetooth", PolicyValue(6));
-
-       bool isRaised = false;
-       try {
-               auto value = storage->strictest("FakePolicy");
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-       EXPECT_TRUE(isRaised);
-
-       auto policy = storage->strictest("bluetooth");
-       EXPECT_EQ(policy.value, 3);
-
-       storage->disenroll("testAdmin0");
-       storage->disenroll("testAdmin1");
-}
-
-TEST_F(PolicyStorageTests, strictest_all)
-{
-       auto storage = getStorage();
-       storage->enroll("testAdmin");
-
-       auto policies = storage->strictest();
-       EXPECT_TRUE(policies.size() > 0);
-
-       storage->disenroll("testAdmin");
-}
-
-TEST_F(PolicyStorageTests, admin_list)
-{
-       auto storage = getStorage();
-
-       auto admins = storage->getAdmins();
-       EXPECT_EQ(admins.size(), 0);
-
-       storage->enroll("testAdmin1");
-       admins = storage->getAdmins();
-       EXPECT_EQ(admins.size(), 1);
-
-       storage->enroll("testAdmin2");
-       admins = storage->getAdmins();
-       EXPECT_EQ(admins.size(), 2);
-
-       storage->disenroll("testAdmin2");
-       admins = storage->getAdmins();
-       EXPECT_EQ(admins.size(), 1);
-
-       storage->disenroll("testAdmin1");
-       admins = storage->getAdmins();
-       EXPECT_EQ(admins.size(), 0);
-}
diff --git a/src/vist/policy/db-schema.hpp b/src/vist/policy/db-schema.hpp
new file mode 100644 (file)
index 0000000..2bdf75b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <string>
+
+namespace vist {
+namespace policy {
+namespace schema {
+
+struct Admin {
+       std::string name;
+};
+
+struct PolicyActivated {
+       std::string admin;
+       std::string policy;
+       int value = -1;
+};
+
+struct PolicyDefinition {
+       std::string name;
+       int ivalue = -1;
+};
+
+} // namespace schema
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-loader.cpp b/src/vist/policy/policy-loader.cpp
new file mode 100644 (file)
index 0000000..28c3b41
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include "policy-loader.hpp"
+
+namespace vist {
+namespace policy {
+
+PolicyProvider* PolicyLoader::load(const std::string& path)
+{
+       PluginLoader loader(path);
+       PolicyProvider::FactoryType factory = nullptr;
+       loader.load(PolicyProvider::getFactoryName(), factory);
+       if (factory == nullptr)
+               std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName());
+
+       auto provider = (*factory)();
+       if (provider == nullptr)
+               std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName());
+
+       return provider;
+}
+
+PluginLoader::PluginLoader(const std::string& path, int flag)
+       : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;})
+// Cleaning object after dlclose() makes SEGFAULT.
+// TODO: Sync dynamic loading's life-cycle with program.(PluginManager)
+//     : handle(::dlopen(path.c_str(), flag), ::dlclose)
+{
+       if (handle == nullptr)
+               throw std::invalid_argument("Failed to open: " + path);
+}
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-loader.hpp b/src/vist/policy/policy-loader.hpp
new file mode 100644 (file)
index 0000000..7221223
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-provider.hpp>
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <dlfcn.h>
+
+namespace vist {
+namespace policy {
+
+struct PolicyLoader final {
+       static PolicyProvider* load(const std::string& path);
+};
+
+class PluginLoader final {
+public:
+       explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY);
+
+       template<typename T>
+       void load(const std::string& name, T& symbol);
+
+private:
+       using Handle = std::unique_ptr<void, int(*)(void*)>;
+       Handle handle;
+};
+
+template<typename T>
+void PluginLoader::load(const std::string& name, T& symbol)
+{
+       symbol = reinterpret_cast<T>(::dlsym(handle.get(), name.c_str()));
+       if (symbol == nullptr)
+               throw std::runtime_error("Failed to load: " + name);
+}
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-manager.cpp b/src/vist/policy/policy-manager.cpp
new file mode 100644 (file)
index 0000000..f1bd3e5
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include "policy-manager.hpp"
+#include "policy-loader.hpp"
+
+#include <vist/logger.hpp>
+
+#include <klay/filesystem.h>
+
+namespace vist {
+namespace policy {
+
+PolicyManager::PolicyManager() : storage(DB_PATH)
+{
+       loadProviders(PLUGIN_INSTALL_DIR);
+       int cnt = loadPolicies();
+       INFO(VIST) << std::to_string(cnt) << "-policies loaded";
+}
+
+std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
+{
+       INFO(VIST) << "Load policies from :" << path;
+       klay::File dir(path);
+       if (!dir.exists() || !dir.isDirectory())
+               throw std::invalid_argument("Plugin directory is wrong.: " + path);
+
+       int passed = 0, failed = 0;
+       klay::DirectoryIterator end;
+       for (klay::DirectoryIterator iter(path); iter != end; ++iter) {
+               if (!iter->isFile())
+                       continue;
+
+               try {
+                       auto provider = PolicyLoader::load(iter->getPath());
+                       DEBUG(VIST) << "Loaded provider: " << provider->getName();
+
+                       bool exist = false;
+                       for (const auto& p : this->providers) {
+                               if (p->getName() == provider->getName()) {
+                                       exist = true;
+                                       break;
+                               }
+                       }
+
+                       if (!exist)
+                               this->providers.emplace_back(std::move(provider));
+               } catch (const std::exception& e) {
+                       ++failed;
+                       ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what();
+                       continue;
+               }
+
+               ++passed;
+       }
+
+       INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed;
+       return std::make_pair(passed, failed);
+}
+
+int PolicyManager::loadPolicies()
+{
+       bool changed = false;
+
+       /// Make policy-provider map for performance
+       for (const auto& provider : providers) {
+               for (const auto& pair : provider->policies) {
+                       policies[pair.first] = provider->getName();
+
+                       /// Check the policy is defined on policy-storage
+                       if (!storage.exists(pair.first)) {
+                               INFO(VIST) << "Define policy: " << pair.first;
+                               storage.define(pair.first, pair.second->getInitial().value);
+                               changed = true;
+                       }
+               }
+       }
+
+       if (changed)
+               storage.syncPolicyDefinition();
+
+       return policies.size();
+}
+
+void PolicyManager::enroll(const std::string& admin)
+{
+       this->storage.enroll(admin);
+}
+
+void PolicyManager::disenroll(const std::string& admin)
+{
+       this->storage.disenroll(admin);
+}
+
+void PolicyManager::set(const std::string& policy,
+                                               const PolicyValue& value,
+                                               const std::string& admin)
+{
+       if (this->policies.find(policy) == this->policies.end())
+               std::runtime_error("Not exist policy: " + policy);
+
+       storage.update(admin, policy, value);
+
+       for (auto& p : providers) {
+               if (p->getName() != this->policies[policy])
+                       continue;
+
+               if (p->policies.find(policy) != p->policies.end()) {
+                       p->policies[policy]->set(value);
+                       return;
+               }
+       }
+}
+
+PolicyValue PolicyManager::get(const std::string& policy)
+{
+       return storage.strictest(policy);
+}
+
+std::unordered_map<std::string, PolicyValue> PolicyManager::getAll()
+{
+       return storage.strictest();
+}
+
+std::vector<std::string> PolicyManager::getAdmins()
+{
+       return storage.getAdmins();
+}
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-manager.hpp b/src/vist/policy/policy-manager.hpp
new file mode 100644 (file)
index 0000000..7523976
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-value.hpp>
+
+#include "policy-storage.hpp"
+
+#include <exception>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <gtest/gtest_prod.h>
+
+namespace vist {
+namespace policy {
+
+class PolicyManager final {
+public:
+       PolicyManager(const PolicyManager&) = delete;
+       PolicyManager& operator=(const PolicyManager&) = delete;
+
+       PolicyManager(PolicyManager&&) = delete;
+       PolicyManager& operator=(PolicyManager&&) = delete;
+
+       static PolicyManager& Instance()
+       {
+               static PolicyManager manager;
+               return manager;
+       }
+
+       void enroll(const std::string& admin);
+       void disenroll(const std::string& admin);
+
+       void set(const std::string& policy,
+                        const PolicyValue& value,
+                        const std::string& admin);
+       PolicyValue get(const std::string& policy);
+       std::unordered_map<std::string, PolicyValue> getAll();
+
+       std::vector<std::string> getAdmins();
+
+private:
+       explicit PolicyManager();
+       ~PolicyManager() = default;
+
+       std::pair<int, int> loadProviders(const std::string& path);
+       int loadPolicies();
+
+       PolicyStorage storage;
+       std::vector<std::unique_ptr<PolicyProvider>> providers;
+
+       /// Policy-Provider
+       std::unordered_map<std::string, std::string> policies;
+
+       FRIEND_TEST(PolicyCoreTests, policy_loader);
+};
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-storage.cpp b/src/vist/policy/policy-storage.cpp
new file mode 100644 (file)
index 0000000..6cc3798
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include "policy-storage.hpp"
+
+#include <vist/logger.hpp>
+#include <vist/query-builder.hpp>
+
+#include <klay/db/column.h>
+#include <klay/db/statement.h>
+#include <klay/exception.h>
+
+#include <algorithm>
+#include <fstream>
+
+using namespace vist::tsqb;
+using namespace vist::policy::schema;
+
+namespace {
+
+auto adminTable = make_table("ADMIN", make_column("name", &Admin::name));
+
+auto polActivatedTable = make_table("POLICY_ACTIVATED",
+                                                                       make_column("admin", &PolicyActivated::admin),
+                                                                       make_column("policy", &PolicyActivated::policy),
+                                                                       make_column("value", &PolicyActivated::value));
+
+auto polDefinitionTable = make_table("POLICY_DEFINITION",
+                                                                        make_column("name", &PolicyDefinition::name),
+                                                                        make_column("ivalue", &PolicyDefinition::ivalue));
+
+const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR;
+const std::string SCRIPT_CREATE_SCHEMA  = "create-schema";
+
+} // anonymous namespace
+
+namespace vist {
+namespace policy {
+
+PolicyStorage::PolicyStorage(const std::string& path) :
+       database(std::make_shared<database::Connection>(path,
+                                                                                                       database::Connection::ReadWrite |
+                                                                                                       database::Connection::Create))
+{
+       database->exec("PRAGMA foreign_keys = ON;");
+       database->exec(getScript(SCRIPT_CREATE_SCHEMA));
+
+       sync();
+}
+
+void PolicyStorage::sync()
+{
+       DEBUG(VIST) << "Sync policy storage to cache object.";
+       syncAdmin();
+       syncPolicyActivated();
+       syncPolicyDefinition();
+}
+
+void PolicyStorage::syncPolicyDefinition()
+{
+       this->definitions.clear();
+       std::string query = polDefinitionTable.selectAll();
+       database::Statement stmt(*database, query);
+
+       while (stmt.step()) {
+               PolicyDefinition pd;
+               pd.name = std::string(stmt.getColumn(0));
+               pd.ivalue = stmt.getColumn(1);
+               DEBUG(VIST) << "Defined policy:" << pd.name;
+               this->definitions.emplace(pd.name, std::move(pd));
+       }
+
+       DEBUG(VIST) << definitions.size() << "- policies synced.";
+}
+
+void PolicyStorage::syncAdmin()
+{
+       this->admins.clear();
+       std::string query = adminTable.selectAll();
+       database::Statement stmt(*database, query);
+
+       while (stmt.step())
+               this->admins.emplace_back(std::string(stmt.getColumn(0)));
+
+       DEBUG(VIST) << admins.size() << "-admins synced.";
+}
+
+void PolicyStorage::syncPolicyActivated()
+{
+       this->activatedPolicies.clear();
+       std::string query = polActivatedTable.selectAll();
+       database::Statement stmt(*database, query);
+
+       while (stmt.step()) {
+               PolicyActivated pa;
+               pa.admin = std::string(stmt.getColumn(0));
+               pa.policy = std::string(stmt.getColumn(1));
+               pa.value = stmt.getColumn(2);
+               this->activatedPolicies.emplace(pa.policy, std::move(pa));
+       }
+
+       DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced.";
+}
+
+std::string PolicyStorage::getScript(const std::string& name)
+{
+       std::string path = SCRIPT_BASE + "/" + name + ".sql";
+       std::ifstream is(path);
+       if (is.fail())
+               throw std::invalid_argument("Failed to open script: " + path); 
+
+       std::istreambuf_iterator<char> begin(is), end;
+       auto content = std::string(begin, end);
+       if (content.empty())
+               throw std::runtime_error("Failed to read script: " + path); 
+
+       return content;
+}
+
+void PolicyStorage::define(const std::string& policy, int ivalue)
+{
+       if (definitions.find(policy) != definitions.end()) {
+               INFO(VIST) << "Policy is already defined: " << policy;
+               return;
+       }
+
+       PolicyDefinition pd;
+       pd.name = policy;
+       pd.ivalue = ivalue;
+
+       std::string query = polDefinitionTable.insert(&PolicyDefinition::name,
+                                                                                                 &PolicyDefinition::ivalue);
+       database::Statement stmt(*database, query);
+       stmt.bind(1, pd.name);
+       stmt.bind(2, pd.ivalue);
+       if (!stmt.exec())
+               throw std::runtime_error("Failed to define policy: " + pd.name);
+}
+
+void PolicyStorage::enroll(const std::string& name)
+{
+       INFO(VIST) << "Enroll admin: " << name;
+       if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
+               ERROR(VIST) << "Admin is aleady enrolled.: " << name;
+               return;
+       }
+
+       std::string query = adminTable.insert(&Admin::name);
+       DEBUG(VIST) << "Enroll admin query statement: " << query;
+       database::Statement stmt(*database, query);
+       stmt.bind(1, name);
+       if (!stmt.exec())
+               throw std::runtime_error("Failed to enroll admin: " + name);
+
+       admins.push_back(name);
+       /// PolicyActivated is triggered by enrolling admin.
+       syncPolicyActivated();
+
+       int count = activatedPolicies.size() / admins.size();
+       INFO(VIST) << "Admin[" << name << "] manages "
+                          << std::to_string(count) << "-policies.";
+}
+
+void PolicyStorage::disenroll(const std::string& name)
+{
+       INFO(VIST) << "Disenroll admin: " << name;
+       auto iter = std::find(admins.begin(), admins.end(), name);
+       if (iter == admins.end()) {
+               ERROR(VIST) << "Not exist admin: " << name;
+               return;
+       } else {
+               admins.erase(iter);
+       }
+
+       std::string query = adminTable.remove().where(expr(&Admin::name) == name);
+       database::Statement stmt(*database, query);
+       stmt.bind(1, name);
+       if (!stmt.exec())
+               throw std::runtime_error("Failed to disenroll admin: " + name);
+}
+
+void PolicyStorage::update(const std::string& admin,
+                                                  const std::string& policy,
+                                                  const PolicyValue& value)
+{
+       DEBUG(VIST) << "Policy-update is called by admin: " << admin
+                               << ", about: " << policy << ", value: " << std::to_string(value);
+
+       if (std::find(admins.begin(), admins.end(), admin) == admins.end())
+               throw std::runtime_error("Not exist admin: " + admin);
+
+       if (definitions.find(policy) == definitions.end())
+               throw std::runtime_error("Not exist policy: " + policy);
+
+       int policyValue = value;
+       std::string query = polActivatedTable.update(&PolicyActivated::value)
+                                                                          .where(expr(&PolicyActivated::admin) == admin &&
+                                                                                         expr(&PolicyActivated::policy) == policy);
+       database::Statement stmt(*database, query);
+       stmt.bind(1, policyValue);
+       stmt.bind(2, admin);
+       stmt.bind(3, policy);
+       if (!stmt.exec())
+               throw runtime::Exception("Failed to update policy:" + policy);
+
+       syncPolicyActivated();
+}
+
+PolicyValue PolicyStorage::strictest(const std::string& policy)
+{
+       if (definitions.find(policy) == definitions.end())
+               throw std::runtime_error("Not exist policy: " + policy);
+
+       // There is no enrolled admins.
+       if (activatedPolicies.size() == 0)
+               return PolicyValue(definitions[policy].ivalue);
+
+       std::shared_ptr<PolicyValue> strictestPtr = nullptr;
+       auto range = activatedPolicies.equal_range(policy);
+       for (auto iter = range.first; iter != range.second; iter++) {
+               int value = iter->second.value;
+               if (strictestPtr == nullptr)
+                       strictestPtr = std::make_shared<PolicyValue>(value);
+               else
+                       strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value;
+
+               DEBUG(VIST) << "The strictest of policy[" << policy
+                                       << "] : " + std::to_string(strictestPtr->value);
+       }
+
+       if (strictestPtr == nullptr)
+               throw std::runtime_error("Not exist managed policy: " + policy);
+
+       return std::move(*strictestPtr);
+}
+
+std::unordered_map<std::string, PolicyValue> PolicyStorage::strictest()
+{
+       std::unordered_map<std::string, PolicyValue> policies;
+       for (const auto& pair : definitions) {
+               std::string name = pair.first;
+               auto value = this->strictest(name);
+
+               policies.emplace(std::move(name), std::move(value));
+       }
+
+       return policies;
+}
+
+const std::vector<std::string>& PolicyStorage::getAdmins() const noexcept
+{
+       return admins;
+}
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/policy-storage.hpp b/src/vist/policy/policy-storage.hpp
new file mode 100644 (file)
index 0000000..4ef524d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  Copyright (c) 2019 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
+ *
+ *      ttp://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
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-value.hpp>
+
+#include "db-schema.hpp"
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include <klay/db/connection.h>
+
+namespace vist {
+namespace policy {
+
+using namespace schema;
+
+class PolicyStorage final {
+public:
+       explicit PolicyStorage(const std::string& path);
+
+       /// TODO(Sangwan): Consider to support lazy sync
+       void sync();
+
+       void syncAdmin();
+       void syncPolicyActivated();
+       void syncPolicyDefinition();
+
+       inline bool exists(const std::string& policy) const noexcept
+       {
+               return definitions.find(policy) != definitions.end();
+       }
+
+       inline bool isActivated() const noexcept
+       {
+               return admins.size() > 0 && activatedPolicies.size() > 0;
+       }
+
+       void enroll(const std::string& admin);
+       void disenroll(const std::string& admin);
+
+       void define(const std::string& policy, int ivalue);
+       void update(const std::string& admin,
+                               const std::string& policy,
+                               const PolicyValue& value);
+
+       PolicyValue strictest(const std::string& policy);
+       /// Return all strictest policy values
+       std::unordered_map<std::string, PolicyValue> strictest();
+
+       const std::vector<std::string>& getAdmins() const noexcept;
+
+private:
+       std::string getScript(const std::string& name);
+
+       std::shared_ptr<klay::database::Connection> database;
+
+       /// DB Cache objects
+       /// TODO(Sangwan): add locking mechanism
+       std::vector<std::string> admins;
+       std::unordered_map<std::string, PolicyActivated> activatedPolicies;
+       std::unordered_map<std::string, PolicyDefinition> definitions;
+};
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/sdk/policy-model.hpp b/src/vist/policy/sdk/policy-model.hpp
deleted file mode 100644 (file)
index 64580fc..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include <string>
-#include <stdexcept>
-
-namespace vist {
-namespace policy {
-
-class PolicyModel {
-public:
-       explicit PolicyModel(std::string name, PolicyValue initial) noexcept :
-               name(std::move(name)), initial(std::move(initial)) {}
-       virtual ~PolicyModel() = default;
-
-       PolicyModel(const PolicyModel&) = delete;
-       PolicyModel& operator=(const PolicyModel&) = delete;
-
-       PolicyModel(PolicyModel&&) = default;
-       PolicyModel& operator=(PolicyModel&&) = default;
-
-       inline void set(const PolicyValue& value)
-       {
-               auto rollback = current;
-               current = value;
-               ready = true;
-
-               try {
-                       this->onChanged(value);
-               } catch (const std::exception& e) {
-                       current = rollback;
-                       ready = false;
-                       std::rethrow_exception(std::current_exception());
-               }
-       }
-
-       inline const PolicyValue& get() const
-       {
-               if (!ready)
-                       throw std::runtime_error("Policy value should be set once before use.");
-
-               return current;
-       }
-
-       virtual void onChanged(const PolicyValue& value) = 0;
-
-       const std::string& getName() const noexcept { return name; }
-       const PolicyValue& getInitial() const noexcept { return initial; }
-
-protected:
-       std::string name;
-       PolicyValue initial;
-       PolicyValue current;
-       bool ready = false;
-};
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/sdk/policy-provider.hpp b/src/vist/policy/sdk/policy-provider.hpp
deleted file mode 100644 (file)
index c55ff26..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-model.hpp>
-
-#include <cstddef>
-#include <memory>
-#include <unordered_map>
-
-namespace vist {
-namespace policy {
-
-class PolicyProvider {
-public:
-       using FactoryType = PolicyProvider* (*)();
-
-       explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {}
-       virtual ~PolicyProvider() = default;
-
-       inline void add(const std::shared_ptr<PolicyModel>& policy)
-       {
-               policies[policy->getName()] = policy;
-       }
-
-       inline const std::string& getName() const noexcept { return name; }
-       static const std::string& getFactoryName() noexcept
-       {
-               static std::string name = "PolicyFactory";
-               return name;
-       }
-
-       inline std::size_t size() const noexcept { return policies.size(); }
-
-private:
-       std::string name;
-       std::unordered_map<std::string, std::shared_ptr<PolicyModel>> policies;
-
-       friend class PolicyManager;
-};
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/sdk/policy-value.hpp b/src/vist/policy/sdk/policy-value.hpp
deleted file mode 100644 (file)
index e1b2464..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#pragma once
-
-namespace vist {
-namespace policy {
-
-// TODO: Support various value type
-struct PolicyValue final {
-       explicit PolicyValue(int value) noexcept : value(value) {}
-       explicit PolicyValue() noexcept = default;
-       ~PolicyValue() = default;
-
-       PolicyValue(const PolicyValue&) noexcept = default;
-       PolicyValue& operator=(const PolicyValue&) noexcept = default;
-
-       PolicyValue(PolicyValue&&) noexcept = default;
-       PolicyValue& operator=(PolicyValue&&) noexcept = default;
-
-       PolicyValue& operator=(int val) {
-               value = val;
-               return *this;
-       }
-
-       operator int() const { return value; }
-       bool operator==(const PolicyValue& rhs) const { return value == rhs.value; }
-       bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; }
-       bool operator<(const PolicyValue& rhs) const { return value < rhs.value; }
-
-       int value = -1;
-};
-
-} // namespace policy
-} // namespace vist
diff --git a/src/vist/policy/sdk/tests/sdk.cpp b/src/vist/policy/sdk/tests/sdk.cpp
deleted file mode 100644 (file)
index 4be5d8d..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Copyright (c) 2019 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
- */
-
-#include <gtest/gtest.h>
-
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
-
-#include <exception>
-
-namespace {
-       int g_value = -1;
-} // anonymous namespace
-
-using namespace vist::policy;
-
-class PolicySDKTests : public testing::Test {};
-
-class TestPolicyModel : public PolicyModel {
-public:
-       TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {}
-
-       virtual void onChanged(const PolicyValue& value)
-       {
-               g_value = value;
-       }
-};
-
-class TestPolicyModelFailed : public PolicyModel {
-public:
-       TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {}
-
-       virtual void onChanged(const PolicyValue& value)
-       {
-               throw std::runtime_error("Intended exception for test.");
-       }
-};
-
-TEST_F(PolicySDKTests, policy_model)
-{
-       TestPolicyModel policy;
-
-       EXPECT_EQ(policy.getName(), "test_policy");
-       EXPECT_EQ(policy.getInitial(), 1);
-
-       // Policy value should be set once before use
-       bool isRaised = false;
-       try {
-               auto value = policy.get();
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-
-       EXPECT_TRUE(isRaised);
-
-       policy.set(PolicyValue(3));
-       EXPECT_EQ(3, g_value);
-       EXPECT_EQ(3, policy.get());
-}
-
-TEST_F(PolicySDKTests, policy_model_failed)
-{
-       TestPolicyModelFailed policy;
-
-       EXPECT_EQ(policy.getName(), "test_policy_failed");
-       EXPECT_EQ(policy.getInitial(), 1);
-
-       bool isRaised = true;
-       try {
-               policy.set(PolicyValue(3));
-       } catch (const std::exception&) {
-               isRaised = true;
-       }
-
-       EXPECT_TRUE(isRaised);
-}
-
-TEST_F(PolicySDKTests, policy_provider)
-{
-       PolicyProvider provider("testProvider");
-       provider.add(std::make_shared<TestPolicyModel>());
-       provider.add(std::make_shared<TestPolicyModelFailed>());
-
-       EXPECT_EQ(2, provider.size());
-}
diff --git a/src/vist/policy/tests/core.cpp b/src/vist/policy/tests/core.cpp
new file mode 100644 (file)
index 0000000..c5c53d9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/policy/policy-manager.hpp>
+
+namespace vist {
+namespace policy {
+
+class PolicyCoreTests : public testing::Test {};
+
+TEST_F(PolicyCoreTests, policy_loader) {
+       auto& manager = PolicyManager::Instance();
+
+       EXPECT_TRUE(manager.providers.size() > 0);
+       EXPECT_TRUE(manager.policies.size() > 0);
+}
+
+TEST_F(PolicyCoreTests, policy_set_get) {
+       auto& manager = PolicyManager::Instance();
+       manager.enroll("testAdmin");
+       manager.set("bluetooth", PolicyValue(5), "testAdmin");
+
+       auto policy = manager.get("bluetooth");
+       EXPECT_EQ(policy.value, 5);
+
+       manager.enroll("testAdmin1");
+       manager.set("bluetooth", PolicyValue(10), "testAdmin1");
+
+       /// Manager should return the strongest policy.
+       policy = manager.get("bluetooth");
+       EXPECT_EQ(policy.value, 5);
+
+       manager.disenroll("testAdmin");
+       manager.disenroll("testAdmin1");
+}
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/policy/tests/storage.cpp b/src/vist/policy/tests/storage.cpp
new file mode 100644 (file)
index 0000000..78fcc39
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include <vist/policy/policy-storage.hpp>
+
+using namespace vist::policy;
+
+class PolicyStorageTests : public testing::Test {
+public:
+       void SetUp() override
+       {
+               this->storage = std::make_shared<PolicyStorage>(DB_PATH);
+       }
+
+       std::shared_ptr<PolicyStorage> getStorage()
+       {
+               return this->storage;
+       }
+
+private:
+       std::shared_ptr<PolicyStorage> storage = nullptr;
+};
+
+TEST_F(PolicyStorageTests, initialize)
+{
+       bool isRaised = false;
+
+       try {
+               // DB is maden at run-time
+               PolicyStorage storage("/tmp/dummy");
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+
+       EXPECT_FALSE(isRaised);
+}
+
+TEST_F(PolicyStorageTests, enrollment)
+{
+       auto storage = getStorage();
+       EXPECT_FALSE(storage->isActivated());
+
+       storage->enroll("testAdmin0");
+       storage->enroll("testAdmin1");
+       EXPECT_TRUE(storage->isActivated());
+
+       storage->disenroll("testAdmin0");
+       EXPECT_TRUE(storage->isActivated());
+
+       storage->disenroll("testAdmin1");
+       EXPECT_FALSE(storage->isActivated());
+}
+
+TEST_F(PolicyStorageTests, update)
+{
+       auto storage = getStorage();
+       storage->enroll("testAdmin");
+
+       bool isRaised = false;
+       try {
+               storage->update("fakeAdmin", "bluetooth", PolicyValue(0));
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+
+       isRaised = false;
+       try {
+               storage->update("testAdmin", "bluetooth", PolicyValue(0));
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+       EXPECT_FALSE(isRaised);
+
+       isRaised = false;
+       try {
+               storage->update("testAdmin", "FakePolicy", PolicyValue(0));
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+       EXPECT_TRUE(isRaised);
+
+       storage->disenroll("testAdmin");
+}
+
+TEST_F(PolicyStorageTests, strictest)
+{
+       auto storage = getStorage();
+       storage->enroll("testAdmin0");
+       storage->enroll("testAdmin1");
+
+       storage->update("testAdmin0", "bluetooth", PolicyValue(3));
+       storage->update("testAdmin1", "bluetooth", PolicyValue(6));
+
+       bool isRaised = false;
+       try {
+               auto value = storage->strictest("FakePolicy");
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+       EXPECT_TRUE(isRaised);
+
+       auto policy = storage->strictest("bluetooth");
+       EXPECT_EQ(policy.value, 3);
+
+       storage->disenroll("testAdmin0");
+       storage->disenroll("testAdmin1");
+}
+
+TEST_F(PolicyStorageTests, strictest_all)
+{
+       auto storage = getStorage();
+       storage->enroll("testAdmin");
+
+       auto policies = storage->strictest();
+       EXPECT_TRUE(policies.size() > 0);
+
+       storage->disenroll("testAdmin");
+}
+
+TEST_F(PolicyStorageTests, admin_list)
+{
+       auto storage = getStorage();
+
+       auto admins = storage->getAdmins();
+       EXPECT_EQ(admins.size(), 0);
+
+       storage->enroll("testAdmin1");
+       admins = storage->getAdmins();
+       EXPECT_EQ(admins.size(), 1);
+
+       storage->enroll("testAdmin2");
+       admins = storage->getAdmins();
+       EXPECT_EQ(admins.size(), 2);
+
+       storage->disenroll("testAdmin2");
+       admins = storage->getAdmins();
+       EXPECT_EQ(admins.size(), 1);
+
+       storage->disenroll("testAdmin1");
+       admins = storage->getAdmins();
+       EXPECT_EQ(admins.size(), 0);
+}
diff --git a/src/vist/sdk/CMakeLists.txt b/src/vist/sdk/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5e233cf
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright (c) 2019 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(GLOB POLICY_SDK_TESTS "tests/*.cpp")
+ADD_VIST_TEST(${POLICY_SDK_TESTS})
diff --git a/src/vist/sdk/policy-model.hpp b/src/vist/sdk/policy-model.hpp
new file mode 100644 (file)
index 0000000..2194953
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-value.hpp>
+
+#include <string>
+#include <stdexcept>
+
+namespace vist {
+namespace policy {
+
+class PolicyModel {
+public:
+       explicit PolicyModel(std::string name, PolicyValue initial) noexcept :
+               name(std::move(name)), initial(std::move(initial)) {}
+       virtual ~PolicyModel() = default;
+
+       PolicyModel(const PolicyModel&) = delete;
+       PolicyModel& operator=(const PolicyModel&) = delete;
+
+       PolicyModel(PolicyModel&&) = default;
+       PolicyModel& operator=(PolicyModel&&) = default;
+
+       inline void set(const PolicyValue& value)
+       {
+               auto rollback = current;
+               current = value;
+               ready = true;
+
+               try {
+                       this->onChanged(value);
+               } catch (const std::exception& e) {
+                       current = rollback;
+                       ready = false;
+                       std::rethrow_exception(std::current_exception());
+               }
+       }
+
+       inline const PolicyValue& get() const
+       {
+               if (!ready)
+                       throw std::runtime_error("Policy value should be set once before use.");
+
+               return current;
+       }
+
+       virtual void onChanged(const PolicyValue& value) = 0;
+
+       const std::string& getName() const noexcept { return name; }
+       const PolicyValue& getInitial() const noexcept { return initial; }
+
+protected:
+       std::string name;
+       PolicyValue initial;
+       PolicyValue current;
+       bool ready = false;
+};
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/sdk/policy-provider.hpp b/src/vist/sdk/policy-provider.hpp
new file mode 100644 (file)
index 0000000..d228681
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-model.hpp>
+
+#include <cstddef>
+#include <memory>
+#include <unordered_map>
+
+namespace vist {
+namespace policy {
+
+class PolicyProvider {
+public:
+       using FactoryType = PolicyProvider* (*)();
+
+       explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {}
+       virtual ~PolicyProvider() = default;
+
+       inline void add(const std::shared_ptr<PolicyModel>& policy)
+       {
+               policies[policy->getName()] = policy;
+       }
+
+       inline const std::string& getName() const noexcept { return name; }
+       static const std::string& getFactoryName() noexcept
+       {
+               static std::string name = "PolicyFactory";
+               return name;
+       }
+
+       inline std::size_t size() const noexcept { return policies.size(); }
+
+private:
+       std::string name;
+       std::unordered_map<std::string, std::shared_ptr<PolicyModel>> policies;
+
+       friend class PolicyManager;
+};
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/sdk/policy-value.hpp b/src/vist/sdk/policy-value.hpp
new file mode 100644 (file)
index 0000000..e1b2464
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#pragma once
+
+namespace vist {
+namespace policy {
+
+// TODO: Support various value type
+struct PolicyValue final {
+       explicit PolicyValue(int value) noexcept : value(value) {}
+       explicit PolicyValue() noexcept = default;
+       ~PolicyValue() = default;
+
+       PolicyValue(const PolicyValue&) noexcept = default;
+       PolicyValue& operator=(const PolicyValue&) noexcept = default;
+
+       PolicyValue(PolicyValue&&) noexcept = default;
+       PolicyValue& operator=(PolicyValue&&) noexcept = default;
+
+       PolicyValue& operator=(int val) {
+               value = val;
+               return *this;
+       }
+
+       operator int() const { return value; }
+       bool operator==(const PolicyValue& rhs) const { return value == rhs.value; }
+       bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; }
+       bool operator<(const PolicyValue& rhs) const { return value < rhs.value; }
+
+       int value = -1;
+};
+
+} // namespace policy
+} // namespace vist
diff --git a/src/vist/sdk/tests/sdk.cpp b/src/vist/sdk/tests/sdk.cpp
new file mode 100644 (file)
index 0000000..d6773b3
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2019 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
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
+
+#include <exception>
+
+namespace {
+       int g_value = -1;
+} // anonymous namespace
+
+using namespace vist::policy;
+
+class PolicySDKTests : public testing::Test {};
+
+class TestPolicyModel : public PolicyModel {
+public:
+       TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {}
+
+       virtual void onChanged(const PolicyValue& value)
+       {
+               g_value = value;
+       }
+};
+
+class TestPolicyModelFailed : public PolicyModel {
+public:
+       TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {}
+
+       virtual void onChanged(const PolicyValue& value)
+       {
+               throw std::runtime_error("Intended exception for test.");
+       }
+};
+
+TEST_F(PolicySDKTests, policy_model)
+{
+       TestPolicyModel policy;
+
+       EXPECT_EQ(policy.getName(), "test_policy");
+       EXPECT_EQ(policy.getInitial(), 1);
+
+       // Policy value should be set once before use
+       bool isRaised = false;
+       try {
+               auto value = policy.get();
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+
+       EXPECT_TRUE(isRaised);
+
+       policy.set(PolicyValue(3));
+       EXPECT_EQ(3, g_value);
+       EXPECT_EQ(3, policy.get());
+}
+
+TEST_F(PolicySDKTests, policy_model_failed)
+{
+       TestPolicyModelFailed policy;
+
+       EXPECT_EQ(policy.getName(), "test_policy_failed");
+       EXPECT_EQ(policy.getInitial(), 1);
+
+       bool isRaised = true;
+       try {
+               policy.set(PolicyValue(3));
+       } catch (const std::exception&) {
+               isRaised = true;
+       }
+
+       EXPECT_TRUE(isRaised);
+}
+
+TEST_F(PolicySDKTests, policy_provider)
+{
+       PolicyProvider provider("testProvider");
+       provider.add(std::make_shared<TestPolicyModel>());
+       provider.add(std::make_shared<TestPolicyModelFailed>());
+
+       EXPECT_EQ(2, provider.size());
+}
index 41538278a9fcb45716d8985fee65bd189460feae..8ba411b29b553ed16edced610bd87a302ead4719 100644 (file)
@@ -17,7 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <vist/service/vist.hpp>
-#include <vist/policy/core/policy-manager.hpp>
+#include <vist/policy/api.hpp>
 
 #include <iostream>
 #include <chrono>
@@ -42,8 +42,7 @@ TEST_F(CoreTests, query_select)
 
 TEST_F(CoreTests, query_update)
 {
-       auto& manager = policy::PolicyManager::Instance();
-       manager.enroll("admin");
+       policy::API::Admin::Enroll("admin");
 
        std::string statement = "SELECT * FROM policy WHERE name = 'bluetooth'";
        auto rows = Vist::Query(statement);
@@ -58,5 +57,5 @@ TEST_F(CoreTests, query_update)
        rows = Vist::Query(statement);
        EXPECT_EQ(rows[0]["value"], std::to_string(3));
 
-       manager.disenroll("admin");
+       policy::API::Admin::Disenroll("admin");
 }