[Feature] Add libSimpleDbus, libLogger, libConfig source code to Vasum.
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests, run server.
Change-Id: I2466604ee744874237fb989695d4104d399cdca1
Signed-off-by: Dariusz Michaluk <d.michaluk@samsung.com>
ADD_DEFINITIONS(-DPROGRAM_VERSION="${VERSION}")
ADD_DEFINITIONS(-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}")
ADD_DEFINITIONS(-DUSE_EXEC)
+ADD_DEFINITIONS(-D__STDC_LIMIT_MACROS)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# Warn about documentation problems
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Client...")
FILE(GLOB project_SRCS *.cpp *.hpp *.h)
-FILE(GLOB common_SRCS ${COMMON_FOLDER}/utils/callback-guard.hpp
- ${COMMON_FOLDER}/utils/callback-guard.cpp
- ${COMMON_FOLDER}/utils/glib-loop.cpp
- ${COMMON_FOLDER}/utils/glib-loop.hpp
- ${COMMON_FOLDER}/base-exception.hpp
- ${COMMON_FOLDER}/base-exception.cpp
- ${COMMON_FOLDER}/utils/eventfd.hpp
- ${COMMON_FOLDER}/utils/eventfd.cpp
- ${COMMON_FOLDER}/utils/fd-utils.hpp
- ${COMMON_FOLDER}/utils/fd-utils.cpp
- ${COMMON_FOLDER}/epoll/*.hpp
- ${COMMON_FOLDER}/epoll/*.cpp
- ${COMMON_FOLDER}/ipc/*.hpp
- ${COMMON_FOLDER}/ipc/*.cpp
- ${COMMON_FOLDER}/ipc/internals/*.hpp
- ${COMMON_FOLDER}/ipc/internals/*.cpp)
+FILE(GLOB common_SRCS ${COMMON_FOLDER}/config/*.hpp ${COMMON_FOLDER}/config/*.cpp
+ ${COMMON_FOLDER}/config/sqlite3/*.hpp ${COMMON_FOLDER}/config/sqlite3/*.cpp
+ ${COMMON_FOLDER}/dbus/*.hpp ${COMMON_FOLDER}/dbus/*.cpp
+ ${COMMON_FOLDER}/epoll/*.hpp ${COMMON_FOLDER}/epoll/*.cpp
+ ${COMMON_FOLDER}/ipc/*.hpp ${COMMON_FOLDER}/ipc/*.cpp
+ ${COMMON_FOLDER}/ipc/internals/*.hpp ${COMMON_FOLDER}/ipc/internals/*.cpp
+ ${COMMON_FOLDER}/logger/*.hpp ${COMMON_FOLDER}/logger/*.cpp
+ ${COMMON_FOLDER}/utils/*.hpp ${COMMON_FOLDER}/utils/*.cpp
+ ${COMMON_FOLDER}/*.hpp ${COMMON_FOLDER}/*.cpp)
SET(_LIB_VERSION_ "0.0.1")
SET(_LIB_SOVERSION_ "0")
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
-PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libSimpleDbus libLogger libConfig libsystemd-daemon)
+PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libsystemd-daemon libsystemd-journal libcap-ng sqlite3)
INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(${SERVER_FOLDER})
/**
* @file
* @author Mateusz Malicki (m.malicki2@samsung.com)
- * @brief libSimpleDbus's wrapper
+ * @brief SimpleDbus's wrapper
*/
#include <config.hpp>
/**
* @file
* @author Mateusz Malicki (m.malicki2@samsung.com)
- * @brief libSimpleDbus's wrapper
+ * @brief SimpleDbus's wrapper
*/
#ifndef VASUM_CLIENT_DBUS_CONNECTION_HPP
namespace client {
/**
- * libSimpleDbus client definition.
+ * SimpleDbus client definition.
*
- * DbusConnection uses libSimpleDbus API.
+ * DbusConnection uses SimpleDbus API.
*/
class DbusConnection {
public:
template<typename Data>
void set(const std::shared_ptr<Data>& data)
{
- static_assert(config::isVisitable<Data>::value, "Use only libConfig's structures");
+ static_assert(config::isVisitable<Data>::value, "Use only Config's structures");
setImpl(data);
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
+ *
+ * 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
+ * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
+ * @brief Exceptions for the configuration
+ */
+
+#ifndef COMMON_CONFIG_EXCEPTION_HPP
+#define COMMON_CONFIG_EXCEPTION_HPP
+
+#include <stdexcept>
+
+namespace config {
+
+/**
+ * Base class for exceptions in configuration.
+ * Error occured during a config file parsing,
+ * e.g. syntax error
+ */
+struct ConfigException: public std::runtime_error {
+
+ ConfigException(const std::string& error) : std::runtime_error(error) {}
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_EXCEPTION_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Definition of a class for writing and reading data from a file descriptor
+ */
+
+#include "config.hpp"
+
+#include "config/fdstore.hpp"
+#include "config/exception.hpp"
+
+#include <cstring>
+#include <cerrno>
+#include <unistd.h>
+#include <chrono>
+#include <poll.h>
+
+namespace config {
+
+namespace {
+
+void waitForEvent(int fd,
+ short event,
+ const std::chrono::high_resolution_clock::time_point deadline)
+{
+ // Wait for the rest of the data
+ struct pollfd fds[1];
+ fds[0].fd = fd;
+ fds[0].events = event | POLLHUP;
+
+ for (;;) {
+ std::chrono::milliseconds timeoutMS =
+ std::chrono::duration_cast<std::chrono::milliseconds>(deadline - std::chrono::high_resolution_clock::now());
+ if (timeoutMS.count() < 0) {
+ throw ConfigException("Timeout");
+ }
+
+ int ret = ::poll(fds, 1 /*fds size*/, timeoutMS.count());
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ throw ConfigException("Error in poll: " + std::string(strerror(errno)));
+ }
+
+ if (ret == 0) {
+ throw ConfigException("Timeout");
+ }
+
+ if (fds[0].revents & POLLHUP) {
+ throw ConfigException("Peer disconnected");
+ }
+
+ // Here Comes the Sun
+ break;
+ }
+}
+
+} // namespace
+
+FDStore::FDStore(int fd)
+ : mFD(fd)
+{
+}
+
+FDStore::FDStore(const FDStore& store)
+ : mFD(store.mFD)
+{
+}
+
+FDStore::~FDStore()
+{
+}
+
+void FDStore::write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS)
+{
+ std::chrono::high_resolution_clock::time_point deadline = std::chrono::high_resolution_clock::now() +
+ std::chrono::milliseconds(timeoutMS);
+
+ size_t nTotal = 0;
+ for (;;) {
+ int n = ::write(mFD,
+ reinterpret_cast<const char*>(bufferPtr) + nTotal,
+ size - nTotal);
+ if (n >= 0) {
+ nTotal += n;
+ if (nTotal == size) {
+ // All data is written, break loop
+ break;
+ }
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+ // Neglected errors
+ } else {
+ throw ConfigException("Error during writing: " + std::string(strerror(errno)));
+ }
+
+ waitForEvent(mFD, POLLOUT, deadline);
+ }
+}
+
+void FDStore::read(void* bufferPtr, const size_t size, const unsigned int timeoutMS)
+{
+ std::chrono::high_resolution_clock::time_point deadline = std::chrono::high_resolution_clock::now() +
+ std::chrono::milliseconds(timeoutMS);
+
+ size_t nTotal = 0;
+ for (;;) {
+ int n = ::read(mFD,
+ reinterpret_cast<char*>(bufferPtr) + nTotal,
+ size - nTotal);
+ if (n >= 0) {
+ nTotal += n;
+ if (nTotal == size) {
+ // All data is read, break loop
+ break;
+ }
+ if (n == 0) {
+ throw ConfigException("Peer disconnected");
+ }
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+ // Neglected errors
+ } else {
+ throw ConfigException("Error during reading: " + std::string(strerror(errno)));
+ }
+
+ waitForEvent(mFD, POLLIN, deadline);
+ }
+}
+} // namespace config
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Declaration of a class for writing and reading data from a file descriptor
+ */
+
+#ifndef COMMON_CONFIG_FDSTORE_HPP
+#define COMMON_CONFIG_FDSTORE_HPP
+
+#include <cstddef>
+
+namespace config {
+
+class FDStore {
+
+public:
+ /**
+ * Constructor. One can pass any kind of file descriptor.
+ * Serialization is NOT written for network purposes,
+ * rather local communication.
+ *
+ * @param fd file descriptor
+ */
+ FDStore(int fd = -1);
+ FDStore(const FDStore& store);
+ ~FDStore();
+
+ /**
+ * Write data using the file descriptor
+ *
+ * @param bufferPtr buffer with the data
+ * @param size size of the buffer
+ * @param timeoutMS timeout in milliseconds
+ */
+ void write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS = 500);
+
+ /**
+ * Reads a value of the given type.
+ *
+ * @param bufferPtr buffer with the data
+ * @param size size of the buffer
+ * @param timeoutMS timeout in milliseconds
+ */
+ void read(void* bufferPtr, const size_t size, const unsigned int timeoutMS = 500);
+
+private:
+ int mFD;
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FDSTORE_HPP
+
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Mateusz Malicki (m.malicki2@samsung.com)
+ *
+ * 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
+ * @author Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief Macros for declare configuration fields
+ */
+
+#ifndef COMMON_CONFIG_FIELDS_UNION_HPP
+#define COMMON_CONFIG_FIELDS_UNION_HPP
+
+#include "config/fields.hpp"
+#include "config/exception.hpp"
+
+#include <utility>
+#include <boost/any.hpp>
+
+/**
+ * Use this macro to declare and register config fields
+ *
+ * Example:
+ * struct Foo {
+ * std::string bar;
+ *
+ * CONFIG_REGISTER
+ * (
+ * bar,
+ * )
+ * };
+ *
+ * struct Config
+ * {
+ * CONFIG_DECLARE_UNION
+ * (
+ * Foo,
+ * int
+ * )
+ * };
+ *
+ * Example of valid configuration:
+ * 1. {
+ * "type": "Foo",
+ * "value": { "bar": "some string" }
+ * }
+ * 2. {
+ * "type": "int",
+ * "value": 1
+ * }
+ *
+ *
+ * Usage:
+ * Config config;
+ * // ...
+ * if (config.isSet()) {
+ * if (config.is<Foo>()) {
+ * Foo& foo = config.as<Foo>();
+ * // ...
+ * }
+ * if (config.is<int>())) {
+ * int field = config.as<int>();
+ * // ...
+ * }
+ * } else {
+ * // Config is not set
+ * Foo foo({"some string"});
+ * config.set(foo);
+ * config.set(std::move(foo)); //< copy sic!
+ * config.set(Foo({"some string"}));
+ * }
+ */
+
+class DisbaleMoveAnyWrapper : public boost::any
+{
+ public:
+ DisbaleMoveAnyWrapper() {}
+ DisbaleMoveAnyWrapper(const DisbaleMoveAnyWrapper& any)
+ : boost::any(static_cast<const boost::any&>(any)) {};
+ DisbaleMoveAnyWrapper& operator=(DisbaleMoveAnyWrapper&& any) = delete;
+ DisbaleMoveAnyWrapper& operator=(const DisbaleMoveAnyWrapper& any) {
+ static_cast<boost::any&>(*this) = static_cast<const boost::any&>(any);
+ return *this;
+ }
+};
+
+#define CONFIG_DECLARE_UNION(...) \
+private: \
+ DisbaleMoveAnyWrapper mConfigDeclareField; \
+ \
+ template<typename Visitor> \
+ void visitOption(Visitor& v, const std::string& name) { \
+ GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \
+ throw config::ConfigException("Union type error. Unsupported type"); \
+ } \
+ template<typename Visitor> \
+ void visitOption(Visitor& v, const std::string& name) const { \
+ GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__) \
+ throw config::ConfigException("Union type error. Unsupported type"); \
+ } \
+ std::string getOptionName() const { \
+ GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__) \
+ return std::string(); \
+ } \
+ boost::any& getHolder() { \
+ return static_cast<boost::any&>(mConfigDeclareField); \
+ } \
+ const boost::any& getHolder() const { \
+ return static_cast<const boost::any&>(mConfigDeclareField); \
+ } \
+public: \
+ \
+ template<typename Visitor> \
+ void accept(Visitor v) { \
+ std::string name; \
+ v.visit("type", name); \
+ visitOption(v, name); \
+ } \
+ \
+ template<typename Visitor> \
+ void accept(Visitor v) const { \
+ const std::string name = getOptionName(); \
+ if (name.empty()) { \
+ throw config::ConfigException("Type is not set"); \
+ } \
+ v.visit("type", name); \
+ visitOption(v, name); \
+ } \
+ \
+ template<typename Type> \
+ bool is() const { \
+ return boost::any_cast<Type>(&getHolder()) != NULL; \
+ } \
+ template<typename Type> \
+ typename std::enable_if<!std::is_const<Type>::value, Type>::type& as() { \
+ if (getHolder().empty()) { \
+ throw config::ConfigException("Type is not set"); \
+ } \
+ return boost::any_cast<Type&>(getHolder()); \
+ } \
+ template<typename Type> \
+ const Type& as() const { \
+ if (getHolder().empty()) { \
+ throw config::ConfigException("Type is not set"); \
+ } \
+ return boost::any_cast<const Type&>(getHolder()); \
+ } \
+ bool isSet() { \
+ return !getOptionName().empty(); \
+ } \
+ template<typename Type> \
+ Type& set(const Type& src) { \
+ getHolder() = std::forward<const Type>(src); \
+ if (getOptionName().empty()) { \
+ throw config::ConfigException("Unsupported type"); \
+ } \
+ return as<Type>(); \
+ } \
+
+#define GENERATE_CODE(MACRO, ...) \
+ BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
+
+#define GENERATE_UNION_VISIT__(r, _, TYPE_) \
+ if (#TYPE_ == name) { \
+ v.visit("value", set(std::move(TYPE_()))); \
+ return; \
+ }
+
+#define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \
+ if (#TYPE_ == name) { \
+ v.visit("value", as<const TYPE_>()); \
+ return; \
+ }
+
+#define GENERATE_UNION_NAME__(r, _, TYPE_) \
+ if (is<TYPE_>()) { \
+ return #TYPE_; \
+ }
+
+#endif // COMMON_CONFIG_FIELDS_UNION_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Macros for registering configuration fields
+ */
+
+#ifndef COMMON_CONFIG_FIELDS_HPP
+#define COMMON_CONFIG_FIELDS_HPP
+
+#include <boost/preprocessor/variadic/to_list.hpp>
+#include <boost/preprocessor/list/for_each.hpp>
+
+#if BOOST_PP_VARIADICS != 1
+#error variadic macros not supported
+#endif
+
+/**
+ * Use this macro to register config fields.
+ *
+ * Example:
+ * struct Foo
+ * {
+ * std::string bar;
+ * std::vector<int> tab;
+ *
+ * // SubConfigA must also register config fields
+ * SubConfigA sub_a;
+ *
+ * // SubConfigB must also register config fields
+ * std::vector<SubConfigB> tab_sub;
+ *
+ * CONFIG_REGISTER
+ * (
+ * bar,
+ * tab,
+ * sub_a
+ * )
+ * };
+ */
+
+#define CONFIG_REGISTER_EMPTY \
+ template<typename Visitor> \
+ void accept(Visitor ) { \
+ } \
+ template<typename Visitor> \
+ void accept(Visitor ) const { \
+ } \
+
+#define CONFIG_REGISTER(...) \
+ template<typename Visitor> \
+ void accept(Visitor v) { \
+ GENERATE_ELEMENTS__(__VA_ARGS__) \
+ } \
+ template<typename Visitor> \
+ void accept(Visitor v) const { \
+ GENERATE_ELEMENTS__(__VA_ARGS__) \
+ } \
+
+#define GENERATE_ELEMENTS__(...) \
+ BOOST_PP_LIST_FOR_EACH(GENERATE_ELEMENT__, \
+ _, \
+ BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
+
+#define GENERATE_ELEMENT__(r, _, element) \
+ v.visit(#element, element); \
+
+#endif // COMMON_CONFIG_FIELDS_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak (j.olszak@samsung.com)
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Visitor for loading from FDStore
+ */
+
+#ifndef COMMON_CONFIG_FROM_FDSTORE_VISITOR_HPP
+#define COMMON_CONFIG_FROM_FDSTORE_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/fdstore.hpp"
+
+#include <string>
+
+namespace config {
+
+class FromFDStoreVisitor {
+public:
+ explicit FromFDStoreVisitor(int fd)
+ : mStore(fd)
+ {
+ }
+
+ FromFDStoreVisitor(const FromFDStoreVisitor&) = default;
+
+ FromFDStoreVisitor& operator=(const FromFDStoreVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string&, T& value)
+ {
+ readInternal(value);
+ }
+
+private:
+ FDStore mStore;
+
+ void readInternal(std::string& value)
+ {
+ size_t size;
+ readInternal(size);
+ value.resize(size);
+ mStore.read(&value.front(), size);
+ }
+
+ template<typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
+ void readInternal(T& value)
+ {
+ mStore.read(&value, sizeof(T));
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void readInternal(T& value)
+ {
+ FromFDStoreVisitor visitor(*this);
+ value.accept(visitor);
+ }
+
+ template<typename T>
+ void readInternal(std::vector<T>& values)
+ {
+ size_t vectorSize;
+ readInternal(vectorSize);
+ values.resize(vectorSize);
+
+ for (T& value : values) {
+ readInternal(value);
+ }
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FROM_FDSTORE_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Mateusz Malicki (m.malicki2@samsung.com)
+ *
+ * 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
+ * @author Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief GVariant visitor
+ */
+
+#ifndef COMMON_CONFIG_FROM_GVARIANT_VISITOR_HPP
+#define COMMON_CONFIG_FROM_GVARIANT_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/exception.hpp"
+#include "config/is-union.hpp"
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <cassert>
+#include <glib.h>
+
+namespace config {
+
+class FromGVariantVisitor {
+public:
+ explicit FromGVariantVisitor(GVariant* variant)
+ {
+ //Assume that the visited object is not a union
+ checkType(variant, G_VARIANT_TYPE_TUPLE);
+ mIter = g_variant_iter_new(variant);
+ }
+
+ FromGVariantVisitor(const FromGVariantVisitor& visitor)
+ : mIter(g_variant_iter_copy(visitor.mIter))
+ {
+ }
+
+ ~FromGVariantVisitor()
+ {
+ g_variant_iter_free(mIter);
+ }
+
+ FromGVariantVisitor& operator=(const FromGVariantVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, T& value)
+ {
+ auto child = makeUnique(g_variant_iter_next_value(mIter));
+ if (!child) {
+ throw config::ConfigException(
+ "GVariant doesn't match with config. Can't set '" + name + "'");
+ }
+ fromGVariant(child.get(), value);
+ }
+
+private:
+ GVariantIter* mIter;
+
+ static std::unique_ptr<GVariant, decltype(&g_variant_unref)> makeUnique(GVariant* variant)
+ {
+ return std::unique_ptr<GVariant, decltype(&g_variant_unref)>(variant, g_variant_unref);
+ }
+
+ static void checkType(GVariant* object, const GVariantType* type)
+ {
+ if (!g_variant_is_of_type(object, type)) {
+ throw ConfigException("Invalid field type");
+ }
+ }
+
+ static void fromGVariant(GVariant* object, std::int32_t& value)
+ {
+ checkType(object, G_VARIANT_TYPE_INT32);
+ value = g_variant_get_int32(object);
+ }
+
+ static void fromGVariant(GVariant* object, std::int64_t& value)
+ {
+ checkType(object, G_VARIANT_TYPE_INT64);
+ value = g_variant_get_int64(object);
+ }
+
+ static void fromGVariant(GVariant* object, std::uint32_t& value)
+ {
+ checkType(object, G_VARIANT_TYPE_UINT32);
+ value = g_variant_get_uint32(object);
+ }
+
+ static void fromGVariant(GVariant* object, std::uint64_t& value)
+ {
+ checkType(object, G_VARIANT_TYPE_UINT64);
+ value = g_variant_get_uint64(object);
+ }
+
+ static void fromGVariant(GVariant* object, bool& value)
+ {
+ checkType(object, G_VARIANT_TYPE_BOOLEAN);
+ value = g_variant_get_boolean(object);
+ }
+
+ static void fromGVariant(GVariant* object, double& value)
+ {
+ checkType(object, G_VARIANT_TYPE_DOUBLE);
+ value = g_variant_get_double(object);
+ }
+
+ static void fromGVariant(GVariant* object, std::string& value)
+ {
+ checkType(object, G_VARIANT_TYPE_STRING);
+ value = g_variant_get_string(object, NULL);
+ }
+
+ template<typename T>
+ static void fromGVariant(GVariant* object, std::vector<T>& value)
+ {
+ checkType(object, G_VARIANT_TYPE_ARRAY);
+ GVariantIter iter;
+ g_variant_iter_init(&iter, object);
+ int length = g_variant_iter_n_children(&iter);
+ value.resize(static_cast<size_t>(length));
+ for (int i = 0; i < length; ++i) {
+ auto child = makeUnique(g_variant_iter_next_value(&iter));
+ assert(child);
+ fromGVariant(child.get(), value[static_cast<size_t>(i)]);
+ }
+ }
+
+ template<typename T>
+ static typename std::enable_if<isUnion<T>::value>::type
+ fromGVariant(GVariant* object, T& value)
+ {
+ checkType(object, G_VARIANT_TYPE_VARIANT);
+ auto inner = makeUnique(g_variant_get_variant(object));
+
+ FromGVariantVisitor visitor(inner.get());
+ value.accept(visitor);
+ }
+
+ template<typename T>
+ static typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
+ fromGVariant(GVariant* object, T& value)
+ {
+ FromGVariantVisitor visitor(object);
+ value.accept(visitor);
+ }
+
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FROM_GVARIANT_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief JSON visitor
+ */
+
+#ifndef COMMON_CONFIG_FROM_JSON_VISITOR_HPP
+#define COMMON_CONFIG_FROM_JSON_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/exception.hpp"
+
+#include <json/json.h>
+#include <string>
+#include <vector>
+
+namespace config {
+
+class FromJsonVisitor {
+public:
+ explicit FromJsonVisitor(const std::string& jsonString)
+ : mObject(nullptr)
+ {
+ mObject = json_tokener_parse(jsonString.c_str());
+ if (mObject == nullptr) {
+ throw ConfigException("Json parsing error");
+ }
+ }
+
+ FromJsonVisitor(const FromJsonVisitor& visitor)
+ : mObject(json_object_get(visitor.mObject))
+ {
+ }
+
+ ~FromJsonVisitor()
+ {
+ json_object_put(mObject);
+ }
+
+ FromJsonVisitor& operator=(const FromJsonVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, T& value)
+ {
+ json_object* object = nullptr;
+ if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
+ throw ConfigException("Missing field '" + name + "'");
+ }
+ fromJsonObject(object, value);
+ }
+
+private:
+ json_object* mObject;
+
+
+ explicit FromJsonVisitor(json_object* object)
+ : mObject(json_object_get(object))
+ {
+ }
+
+ static void checkType(json_object* object, json_type type)
+ {
+ if (type != json_object_get_type(object)) {
+ throw ConfigException("Invalid field type");
+ }
+ }
+
+ static void fromJsonObject(json_object* object, std::int32_t& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 > INT32_MAX || value64 < INT32_MIN) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<std::int32_t>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, std::uint32_t& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 > UINT32_MAX || value64 < 0) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<std::uint32_t>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, std::int64_t& value)
+ {
+ checkType(object, json_type_int);
+ value = json_object_get_int64(object);
+ }
+
+ static void fromJsonObject(json_object* object, std::uint64_t& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 < 0) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<std::uint64_t>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, bool& value)
+ {
+ checkType(object, json_type_boolean);
+ value = json_object_get_boolean(object);
+ }
+
+ static void fromJsonObject(json_object* object, double& value)
+ {
+ checkType(object, json_type_double);
+ value = json_object_get_double(object);
+ }
+
+ static void fromJsonObject(json_object* object, std::string& value)
+ {
+ checkType(object, json_type_string);
+ value = json_object_get_string(object);
+ }
+
+ template<typename T>
+ static void fromJsonObject(json_object* object, std::vector<T>& value)
+ {
+ checkType(object, json_type_array);
+ int length = json_object_array_length(object);
+ value.resize(static_cast<size_t>(length));
+ for (int i = 0; i < length; ++i) {
+ fromJsonObject(json_object_array_get_idx(object, i), value[static_cast<size_t>(i)]);
+ }
+ }
+
+ template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
+ static void fromJsonObject(json_object* object, T& value)
+ {
+ checkType(object, json_type_object);
+ FromJsonVisitor visitor(object);
+ value.accept(visitor);
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FROM_JSON_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Krzysztof Dynowski (k.dynowski@samsumg.com)
+ *
+ * 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
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief KVStore visitor with defaults values from json
+ */
+
+#ifndef COMMON_CONFIG_FROM_KVJSON_VISITOR_HPP
+#define COMMON_CONFIG_FROM_KVJSON_VISITOR_HPP
+
+#include "config/from-kvstore-visitor.hpp"
+#include "config/is-union.hpp"
+#include <json/json.h>
+
+namespace config {
+
+class FromKVJsonVisitor {
+public:
+ FromKVJsonVisitor(KVStore& store, const std::string& json, const std::string& prefix)
+ : mStore(store)
+ , mKeyPrefix(prefix)
+ , mIsUnion(false)
+ {
+ mObject = json_tokener_parse(json.c_str());
+ if (mObject == nullptr) {
+ throw ConfigException("Json parsing error");
+ }
+ }
+
+
+ ~FromKVJsonVisitor() {
+ json_object_put(mObject);
+ }
+
+ FromKVJsonVisitor(const FromKVJsonVisitor& v) :
+ mStore(v.mStore),
+ mKeyPrefix(v.mKeyPrefix),
+ mObject(v.mObject ? json_object_get(v.mObject) : nullptr),
+ mIsUnion(v.mIsUnion)
+ {
+ }
+ FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, T& value) {
+ getValue(name, value);
+ }
+
+private:
+ KVStore& mStore;
+ std::string mKeyPrefix;
+ json_object* mObject;
+ bool mIsUnion;
+
+ // create visitor for field object (visitable object)
+ FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name, const bool isUnion) :
+ mStore(v.mStore),
+ mKeyPrefix(key(v.mKeyPrefix, name)),
+ mIsUnion(isUnion || v.mIsUnion)
+ {
+ json_object* object = nullptr;
+ if (v.mObject && !json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
+ if (!mIsUnion)
+ throw ConfigException("Missing json field " + mKeyPrefix);
+ }
+ mObject = object ? json_object_get(object) : nullptr;
+ }
+
+ // create visitor for vector i-th element (visitable object)
+ FromKVJsonVisitor(const FromKVJsonVisitor& v, int i, const bool isUnion) :
+ mStore(v.mStore),
+ mKeyPrefix(key(v.mKeyPrefix, std::to_string(i))),
+ mIsUnion(isUnion || v.mIsUnion)
+ {
+ json_object* object = nullptr;
+ if (v.mObject) {
+ object = json_object_array_get_idx(v.mObject, i);
+ checkType(object, json_type_object);
+ }
+ mObject = object ? json_object_get(object) : nullptr;
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ std::string k = key(mKeyPrefix, name);
+ if (mStore.exists(k)) {
+ t = mStore.get<T>(k);
+ }
+ else {
+ json_object* object = nullptr;
+ if (mObject) {
+ json_object_object_get_ex(mObject, name.c_str(), &object);
+ }
+ if (!object) {
+ throw ConfigException("Missing json field " + key(mKeyPrefix, name));
+ }
+ fromJsonObject(object, t);
+ }
+ }
+
+ template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, name, true);
+ t.accept(visitor);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, name, false);
+ t.accept(visitor);
+ }
+
+ int getArraySize(std::string& name, json_object* object)
+ {
+ if (mStore.exists(name)) {
+ return mStore.get<int>(name);
+ }
+ if (object) {
+ return json_object_array_length(object);
+ }
+ return -1;
+ }
+
+ template<typename T>
+ void getValue(const std::string& name, std::vector<T>& value)
+ {
+ json_object* object = nullptr;
+ if (mObject && json_object_object_get_ex(mObject, name.c_str(), &object)) {
+ checkType(object, json_type_array);
+ }
+
+ std::string k = key(mKeyPrefix, name);
+ int length = getArraySize(k, object);
+ if (length < 0) {
+ throw ConfigException("Missing array length " + k);
+ }
+ value.resize(static_cast<size_t>(length));
+ FromKVJsonVisitor visitor(*this, name, false);
+ if (mStore.exists(k)) {
+ json_object_put(visitor.mObject);
+ visitor.mObject = nullptr;
+ }
+ for (int i = 0; i < length; ++i) {
+ visitor.getValue(i, value[i]);
+ }
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void getValue(int i, T& t)
+ {
+ std::string k = key(mKeyPrefix, std::to_string(i));
+ if (mStore.exists(k)) {
+ t = mStore.get<T>(k);
+ }
+ else {
+ json_object* object = mObject ? json_object_array_get_idx(mObject, i) : nullptr;
+ if (!object) {
+ throw ConfigException("Missing json array elem " + k);
+ }
+ fromJsonObject(object, t);
+ }
+ }
+
+ template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
+ void getValue(int i, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, i, true);
+ t.accept(visitor);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
+ void getValue(int i, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, i, false);
+ t.accept(visitor);
+ }
+
+ template<typename T>
+ void getValue(int i, std::vector<T>& value)
+ {
+ std::string k = key(mKeyPrefix, std::to_string(i));
+ int length = getArraySize(k, mObject);
+ value.resize(static_cast<size_t>(length));
+ FromKVJsonVisitor visitor(*this, i, false);
+ if (mStore.exists(k)) {
+ json_object_put(visitor.mObject);
+ visitor.mObject = nullptr;
+ }
+ for (int i = 0; i < length; ++i) {
+ visitor.getValue(i, value[i]);
+ }
+ }
+
+ static void checkType(json_object* object, json_type type)
+ {
+ if (type != json_object_get_type(object)) {
+ throw ConfigException("Invalid field type " + std::to_string(type));
+ }
+ }
+
+ static void fromJsonObject(json_object* object, int& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 > INT32_MAX || value64 < INT32_MIN) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<int>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, std::int64_t& value)
+ {
+ checkType(object, json_type_int);
+ value = json_object_get_int64(object);
+ }
+
+ static void fromJsonObject(json_object* object, std::uint32_t& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 > UINT32_MAX || value64 < 0) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<std::uint32_t>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, std::uint64_t& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 < 0) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<std::uint64_t>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, bool& value)
+ {
+ checkType(object, json_type_boolean);
+ value = json_object_get_boolean(object);
+ }
+
+ static void fromJsonObject(json_object* object, double& value)
+ {
+ checkType(object, json_type_double);
+ value = json_object_get_double(object);
+ }
+
+ static void fromJsonObject(json_object* object, std::string& value)
+ {
+ checkType(object, json_type_string);
+ value = json_object_get_string(object);
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FROM_KVJSON_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak (j.olszak@samsung.com)
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Visitor for loading from KVStore
+ */
+
+#ifndef COMMON_CONFIG_FROM_KVSTORE_VISITOR_HPP
+#define COMMON_CONFIG_FROM_KVSTORE_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/kvstore.hpp"
+
+namespace config {
+
+class FromKVStoreVisitor {
+public:
+ FromKVStoreVisitor(KVStore& store, const std::string& prefix)
+ : mStore(store),
+ mKeyPrefix(prefix)
+ {
+ }
+
+ FromKVStoreVisitor& operator=(const FromKVStoreVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, T& value)
+ {
+ getInternal(key(mKeyPrefix, name), value);
+ }
+
+private:
+ KVStore& mStore;
+ std::string mKeyPrefix;
+
+ FromKVStoreVisitor(const FromKVStoreVisitor& visitor, const std::string& prefix)
+ : mStore(visitor.mStore),
+ mKeyPrefix(prefix)
+ {
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void getInternal(const std::string& name, T& value)
+ {
+ value = mStore.get<T>(name);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void getInternal(const std::string& name, T& value)
+ {
+ FromKVStoreVisitor visitor(*this, name);
+ value.accept(visitor);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void getInternal(const std::string& name, std::vector<T>& values)
+ {
+ values.clear();
+
+ size_t vectorSize = mStore.get<size_t>(name);
+ if (vectorSize == 0) {
+ return;
+ }
+
+ values.resize(vectorSize);
+ for (size_t i = 0; i < vectorSize; ++i) {
+ const std::string k = key(name, std::to_string(i));
+ getInternal(k, values[i]);
+ }
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_FROM_KVSTORE_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Filesystem helper functions
+ */
+
+#include "config/fs-utils.hpp"
+
+#include <fstream>
+#include <streambuf>
+
+
+namespace config {
+namespace fsutils {
+
+bool readFileContent(const std::string& path, std::string& result)
+{
+ std::ifstream file(path);
+
+ if (!file) {
+ return false;
+ }
+
+ file.seekg(0, std::ios::end);
+ std::streampos length = file.tellg();
+ if (length < 0) {
+ return false;
+ }
+ result.resize(static_cast<size_t>(length));
+ file.seekg(0, std::ios::beg);
+
+ file.read(&result[0], length);
+ if (!file) {
+ result.clear();
+ return false;
+ }
+
+ return true;
+}
+
+bool saveFileContent(const std::string& path, const std::string& content)
+{
+ std::ofstream file(path);
+ if (!file) {
+ return false;
+ }
+ file.write(content.data(), static_cast<std::streamsize>(content.size()));
+ if (!file) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace fsutils
+} // namespace config
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief src/config/manager.hpp
+ */
+
+#ifndef COMMON_CONFIG_FS_UTILS_HPP
+#define COMMON_CONFIG_FS_UTILS_HPP
+
+#include <string>
+
+namespace config {
+namespace fsutils {
+
+bool readFileContent(const std::string& path, std::string& result);
+bool saveFileContent(const std::string& path, const std::string& content);
+
+inline std::string readFileContent(const std::string& path) {
+ std::string content;
+ return readFileContent(path, content) ? content : std::string();
+}
+} // namespace fsutils
+} // namespace config
+
+#endif // COMMON_CONFIG_FS_UTILS_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Internal configuration helper
+ */
+
+#ifndef COMMON_CONFIG_IS_UNION_HPP
+#define COMMON_CONFIG_IS_UNION_HPP
+
+#include "config/is-visitable.hpp"
+
+namespace config {
+
+// generic member checker, start
+template <typename T, typename F>
+struct has_member_impl {
+ template <typename C>
+ static std::true_type check(typename F::template checker__<C>* =0);
+
+ template <typename C>
+ static std::false_type check(...);
+
+ static const bool value = std::is_same<decltype(check<T>(0)), std::true_type>::value;
+};
+
+template <typename T, typename F>
+struct has_member : public std::integral_constant<bool, has_member_impl<T, F>::value> {};
+// generic member checker, end
+
+
+template <typename X>
+struct check_union : isVisitable<X> {
+ template <typename T,
+ //list of function union must implement
+ const X& (T::*)() const = &T::as,
+ X& (T::*)(const X& src) = &T::set,
+ bool (T::*)() = &T::isSet
+ >
+ struct checker__ {};
+};
+template<typename T>
+struct isUnion : has_member<T, check_union<T>> {};
+
+//Note:
+// unfortunately, above generic has_member can't be used for isVisitable
+// because Vistable need 'accept' OR 'accept const', while has_member make exect match
+// e.g accept AND accept const
+
+} // namespace config
+
+#endif // COMMON_CONFIG_IS_UNION_HPP
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Internal configuration helper
+ */
+
+#ifndef COMMON_CONFIG_IS_VISITABLE_HPP
+#define COMMON_CONFIG_IS_VISITABLE_HPP
+
+#include <type_traits>
+
+namespace config {
+
+template <typename T>
+struct isVisitableHelper__ {
+ struct Visitor {};
+
+ template <typename C> static std::true_type
+ test(decltype(std::declval<C>().template accept(Visitor()))*);
+
+ template <typename C> static std::false_type
+ test(...);
+
+ static constexpr bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
+};
+
+/**
+ * Helper for compile-time checking against existance of template method 'accept'.
+ */
+template <typename T>
+struct isVisitable : public std::integral_constant<bool, isVisitableHelper__<T>::value> {};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_IS_VISITABLE_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Definition of a class for key-value storage in a sqlite3 database
+ */
+
+#include "config.hpp"
+
+#include "config/kvstore.hpp"
+#include "config/exception.hpp"
+
+#include <exception>
+#include <limits>
+#include <memory>
+#include <set>
+#include <cassert>
+
+namespace config {
+
+namespace {
+
+const int AUTO_DETERM_SIZE = -1;
+const int FIRST_COLUMN = 0;
+
+struct ScopedReset {
+ ScopedReset(std::unique_ptr<sqlite3::Statement>& stmtPtr)
+ : mStmtPtr(stmtPtr) {}
+ ~ScopedReset()
+ {
+ mStmtPtr->reset();
+ }
+private:
+ std::unique_ptr<sqlite3::Statement>& mStmtPtr;
+};
+
+/**
+ * Escape characters used by the GLOB function.
+ */
+void sqliteEscapeStr(::sqlite3_context* context, int argc, ::sqlite3_value** values)
+{
+ char* inBuff = (char*)sqlite3_value_text(values[0]);
+ if (argc != 1 || inBuff == NULL) {
+ sqlite3_result_error(context, "SQL function escapeSequence() called with invalid arguments.\n", -1);
+ return;
+ }
+
+ std::string in(inBuff);
+ static const std::set<char> toEscape({'?', '*', '[', ']'});
+
+ // Compute the out size
+ auto isEscapeChar = [&](char c) {
+ return toEscape.count(c) == 1;
+ };
+ size_t numEscape = std::count_if(in.begin(),
+ in.end(),
+ isEscapeChar);
+ if (numEscape == 0) {
+ sqlite3_result_text(context, in.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);
+ }
+
+ // Escape characters
+ std::string out(in.size() + 2 * numEscape, 'x');
+ for (size_t i = 0, j = 0;
+ i < in.size();
+ ++i, ++j) {
+ if (isEscapeChar(in[i])) {
+ out[j] = '[';
+ ++j;
+ out[j] = in[i];
+ ++j;
+ out[j] = ']';
+ } else {
+ out[j] = in[i];
+ }
+ }
+ sqlite3_result_text(context, out.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);
+}
+
+} // namespace
+
+KVStore::Transaction::Transaction(KVStore& kvStore)
+ : mLock(kvStore.mMutex)
+ , mKVStore(kvStore)
+ , mIsOuter(kvStore.mTransactionDepth == 0)
+{
+ if (mKVStore.mIsTransactionCommited) {
+ throw ConfigException("Previous transaction is not closed");
+ }
+ if (mIsOuter) {
+ mKVStore.mConn.exec("BEGIN EXCLUSIVE TRANSACTION");
+ }
+ ++mKVStore.mTransactionDepth;
+}
+
+KVStore::Transaction::~Transaction()
+{
+ --mKVStore.mTransactionDepth;
+ if (mIsOuter) {
+ if (mKVStore.mIsTransactionCommited) {
+ mKVStore.mIsTransactionCommited = false;
+ } else {
+ mKVStore.mConn.exec("ROLLBACK TRANSACTION");
+ }
+ }
+}
+
+void KVStore::Transaction::commit()
+{
+ if (mKVStore.mIsTransactionCommited) {
+ throw ConfigException("Transaction already commited");
+ }
+ if (mIsOuter) {
+ mKVStore.mConn.exec("COMMIT TRANSACTION");
+ mKVStore.mIsTransactionCommited = true;
+ }
+}
+
+KVStore::KVStore(const std::string& path)
+ : mTransactionDepth(0),
+ mIsTransactionCommited(false),
+ mPath(path),
+ mConn(path)
+{
+ setupDb();
+ createFunctions();
+ prepareStatements();
+}
+
+KVStore::~KVStore()
+{
+ assert(mTransactionDepth == 0);
+}
+
+void KVStore::setupDb()
+{
+ // called only from ctor, transaction is not needed
+ mConn.exec("CREATE TABLE IF NOT EXISTS data (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
+}
+
+void KVStore::prepareStatements()
+{
+ mGetValueStmt.reset(
+ new sqlite3::Statement(mConn, "SELECT value FROM data WHERE key = ? LIMIT 1"));
+ mGetKeyExistsStmt.reset(
+ // following line left in comment to have example of any subkey matching
+ //new sqlite3::Statement(mConn, "SELECT 1 FROM data WHERE key = ?1 OR key GLOB escapeStr(?1) || '.*' LIMIT 1"));
+ new sqlite3::Statement(mConn, "SELECT 1 FROM data WHERE key = ?1 LIMIT 1"));
+ mGetIsEmptyStmt.reset(
+ new sqlite3::Statement(mConn, "SELECT 1 FROM data LIMIT 1"));
+ mSetValueStmt.reset(
+ new sqlite3::Statement(mConn, "INSERT OR REPLACE INTO data (key, value) VALUES (?,?)"));
+ mRemoveValuesStmt.reset(
+ new sqlite3::Statement(mConn, "DELETE FROM data WHERE key = ?1 OR key GLOB escapeStr(?1) ||'.*' "));
+ mGetKeysStmt.reset(
+ new sqlite3::Statement(mConn, "SELECT key FROM data"));
+}
+
+void KVStore::createFunctions()
+{
+ int ret = sqlite3_create_function(mConn.get(), "escapeStr", 1, SQLITE_ANY, 0, &sqliteEscapeStr, 0, 0);
+ if (ret != SQLITE_OK) {
+ throw ConfigException("Error during creating functions: " + mConn.getErrorMessage());
+ }
+}
+
+void KVStore::clear()
+{
+ Transaction transaction(*this);
+ mConn.exec("DELETE FROM data");
+ transaction.commit();
+}
+
+bool KVStore::isEmpty()
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mGetIsEmptyStmt);
+
+ int ret = ::sqlite3_step(mGetIsEmptyStmt->get());
+ if (ret != SQLITE_DONE && ret != SQLITE_ROW) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+
+ transaction.commit();
+ return ret == SQLITE_DONE;
+}
+
+bool KVStore::exists(const std::string& key)
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mGetKeyExistsStmt);
+
+ ::sqlite3_bind_text(mGetKeyExistsStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);
+
+ int ret = ::sqlite3_step(mGetKeyExistsStmt->get());
+ if (ret != SQLITE_DONE && ret != SQLITE_ROW) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+
+ transaction.commit();
+ return ret == SQLITE_ROW;
+}
+
+void KVStore::remove(const std::string& key)
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mRemoveValuesStmt);
+
+ ::sqlite3_bind_text(mRemoveValuesStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);
+
+ if (::sqlite3_step(mRemoveValuesStmt->get()) != SQLITE_DONE) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+ transaction.commit();
+}
+
+void KVStore::setInternal(const std::string& key, const std::string& value)
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mSetValueStmt);
+
+ ::sqlite3_bind_text(mSetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);
+ ::sqlite3_bind_text(mSetValueStmt->get(), 2, value.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);
+
+
+ if (::sqlite3_step(mSetValueStmt->get()) != SQLITE_DONE) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+ transaction.commit();
+}
+
+void KVStore::setInternal(const std::string& key, const std::initializer_list<std::string>& values)
+{
+ setInternal(key, std::vector<std::string>(values));
+}
+
+void KVStore::setInternal(const std::string& key, const std::vector<std::string>& values)
+{
+ if (values.size() > std::numeric_limits<unsigned int>::max()) {
+ throw ConfigException("Too many values to insert");
+ }
+
+ Transaction transaction(*this);
+
+ remove(key);
+
+ // Save vector's capacity
+ setInternal(key, values.size());
+
+ // Save vector's elements
+ for (unsigned int i = 0; i < values.size(); ++i) {
+ setInternal(config::key(key, std::to_string(i)),
+ values[i]);
+ }
+ transaction.commit();
+}
+
+std::string KVStore::getInternal(const std::string& key, std::string*)
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mGetValueStmt);
+
+ ::sqlite3_bind_text(mGetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);
+
+ int ret = ::sqlite3_step(mGetValueStmt->get());
+ if (ret == SQLITE_DONE) {
+ throw ConfigException("No value corresponding to the key: " + key + "@" + mPath);
+ }
+ if (ret != SQLITE_ROW) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+
+ std::string value = reinterpret_cast<const char*>(
+ sqlite3_column_text(mGetValueStmt->get(), FIRST_COLUMN));
+
+ transaction.commit();
+ return value;
+}
+
+std::vector<std::string> KVStore::getInternal(const std::string& key, std::vector<std::string>*)
+{
+ Transaction transaction(*this);
+
+ unsigned int valuesSize = get<unsigned int>(key);
+ std::vector<std::string> values(valuesSize);
+ if (valuesSize == 0) {
+ transaction.commit();
+ return values;
+ }
+
+ for (unsigned int i = 0; i < values.size(); ++i) {
+ values[i] = getInternal(config::key(key, std::to_string(i)),
+ static_cast<std::string*>(nullptr));
+
+ }
+
+ transaction.commit();
+ return values;
+}
+
+std::vector<std::string> KVStore::getKeys()
+{
+ Transaction transaction(*this);
+ ScopedReset scopedReset(mGetKeysStmt);
+
+ std::vector<std::string> result;
+
+ for (;;) {
+ int ret = ::sqlite3_step(mGetKeysStmt->get());
+ if (ret == SQLITE_DONE) {
+ break;
+ }
+ if (ret != SQLITE_ROW) {
+ throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+ }
+ const char* key = reinterpret_cast<const char*>(sqlite3_column_text(mGetKeysStmt->get(),
+ FIRST_COLUMN));
+ result.push_back(key);
+ }
+
+ transaction.commit();
+ return result;
+}
+
+} // namespace config
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Declaration of a class for key-value storage in a sqlite3 database
+ */
+
+#ifndef COMMON_CONFIG_KVSTORE_HPP
+#define COMMON_CONFIG_KVSTORE_HPP
+
+#include "config/sqlite3/connection.hpp"
+#include "config/sqlite3/statement.hpp"
+
+#include <algorithm>
+#include <initializer_list>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <atomic>
+
+namespace config {
+
+class KVStore {
+
+public:
+ /**
+ * A guard struct for thread synchronization and transaction management.
+ */
+ class Transaction {
+ public:
+ Transaction(KVStore& store);
+ ~Transaction();
+
+ Transaction(const Transaction&) = delete;
+ Transaction& operator=(const Transaction&) = delete;
+
+ void commit();
+ private:
+ std::unique_lock<std::recursive_mutex> mLock;
+ KVStore& mKVStore;
+ bool mIsOuter;
+ };
+
+ /**
+ * @param path configuration database file path
+ */
+ explicit KVStore(const std::string& path);
+ ~KVStore();
+
+ KVStore(const KVStore&) = delete;
+ KVStore& operator=(const KVStore&) = delete;
+
+ /**
+ * Clears all the stored data
+ */
+ void clear();
+
+ /**
+ * @return Is there any data stored
+ */
+ bool isEmpty();
+
+ /**
+ * @param key string regexp of the stored values
+ *
+ * @return Does this key exist in the database
+ */
+ bool exists(const std::string& key);
+
+ /**
+ * Removes values corresponding to the passed key.
+ * Many values may correspond to one key, so many values may
+ * need to be deleted
+ *
+ * @param key string regexp of the stored values
+ */
+ void remove(const std::string& key);
+
+ /**
+ * Stores a single value corresponding to the passed key
+ *
+ * @param key string key of the value
+ * @param value value corresponding to the key
+ */
+ template<typename T>
+ void set(const std::string& key, const T& value)
+ {
+ return setInternal(key, value);
+ }
+
+ /**
+ * Gets the value corresponding to the key.
+ * Uses stringstreams to parse.
+ *
+ * @param key string key of the value
+ * @tparam T = std::string desired type of the return value
+ * @return value corresponding to the key
+ */
+ template<typename T = std::string>
+ T get(const std::string& key)
+ {
+ return getInternal(key, static_cast<T*>(nullptr));
+ }
+
+ /**
+ * Returns all stored keys.
+ */
+ std::vector<std::string> getKeys();
+
+private:
+ typedef std::lock_guard<std::recursive_mutex> Lock;
+
+ std::recursive_mutex mMutex;
+ size_t mTransactionDepth;
+ bool mIsTransactionCommited;
+
+ void setInternal(const std::string& key, const std::string& value);
+ void setInternal(const std::string& key, const std::initializer_list<std::string>& values);
+ void setInternal(const std::string& key, const std::vector<std::string>& values);
+ template<typename T>
+ void setInternal(const std::string& key, const T& value);
+ template<typename T>
+ void setInternal(const std::string& key, const std::vector<T>& values);
+
+ std::string getInternal(const std::string& key, std::string*);
+ std::vector<std::string> getInternal(const std::string& key, std::vector<std::string>*);
+ template<typename T>
+ T getInternal(const std::string& key, T*);
+ template<typename T>
+ std::vector<T> getInternal(const std::string& key, std::vector<T>*);
+
+ std::string mPath;
+ sqlite3::Connection mConn;
+ std::unique_ptr<sqlite3::Statement> mGetValueStmt;
+ std::unique_ptr<sqlite3::Statement> mGetKeyExistsStmt;
+ std::unique_ptr<sqlite3::Statement> mGetIsEmptyStmt;
+ std::unique_ptr<sqlite3::Statement> mGetValueListStmt;
+ std::unique_ptr<sqlite3::Statement> mSetValueStmt;
+ std::unique_ptr<sqlite3::Statement> mRemoveValuesStmt;
+ std::unique_ptr<sqlite3::Statement> mGetKeysStmt;
+
+ void setupDb();
+ void prepareStatements();
+ void createFunctions();
+};
+
+namespace {
+template<typename T>
+std::string toString(const T& value)
+{
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+}
+
+template<typename T>
+T fromString(const std::string& strValue)
+{
+ std::istringstream iss(strValue);
+ T value;
+ iss >> value;
+ return value;
+}
+
+} // namespace
+
+template<typename T>
+void KVStore::setInternal(const std::string& key, const T& value)
+{
+ setInternal(key, toString(value));
+}
+
+template<typename T>
+void KVStore::setInternal(const std::string& key, const std::vector<T>& values)
+{
+ std::vector<std::string> strValues(values.size());
+
+ std::transform(values.begin(),
+ values.end(),
+ strValues.begin(),
+ toString<T>);
+
+ setInternal(key, strValues);
+}
+
+template<typename T>
+T KVStore::getInternal(const std::string& key, T*)
+{
+ return fromString<T>(getInternal(key, static_cast<std::string*>(nullptr)));
+}
+
+template<typename T>
+std::vector<T> KVStore::getInternal(const std::string& key, std::vector<T>*)
+{
+ std::vector<std::string> strValues = getInternal(key, static_cast<std::vector<std::string>*>(nullptr));
+ std::vector<T> values(strValues.size());
+
+ std::transform(strValues.begin(),
+ strValues.end(),
+ values.begin(),
+ fromString<T>);
+
+ return values;
+}
+
+/**
+ * Concatenates all parameters into one std::string.
+ * Uses '.' to connect the terms.
+ * @param args components of the string
+ * @tparam delim optional delimiter
+ * @tparam typename ... Args any type implementing str
+ * @return string created from he args
+ */
+template<char delim = '.', typename Arg1, typename ... Args>
+std::string key(const Arg1& a1, const Args& ... args)
+{
+ std::string ret = toString(a1);
+ std::initializer_list<std::string> strings {toString(args)...};
+ for (const std::string& s : strings) {
+ ret += delim + s;
+ }
+
+ return ret;
+}
+
+/**
+ * Function added for key function completeness.
+ *
+ * @tparam delim = '.' parameter not used, added for consistency
+ * @return empty string
+ */
+template<char delim = '.'>
+std::string key()
+{
+ return std::string();
+}
+
+} // namespace config
+
+#endif // COMMON_CONFIG_KVSTORE_HPP
+
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Configuration management functions
+ */
+
+#ifndef COMMON_CONFIG_MANAGER_HPP
+#define COMMON_CONFIG_MANAGER_HPP
+
+#include "config/to-gvariant-visitor.hpp"
+#include "config/to-json-visitor.hpp"
+#include "config/to-kvstore-visitor.hpp"
+#include "config/to-fdstore-visitor.hpp"
+#include "config/from-gvariant-visitor.hpp"
+#include "config/from-json-visitor.hpp"
+#include "config/from-kvstore-visitor.hpp"
+#include "config/from-fdstore-visitor.hpp"
+#include "config/from-kvjson-visitor.hpp"
+#include "config/fs-utils.hpp"
+#include "config/is-union.hpp"
+
+namespace config {
+
+/**
+ * Fills the configuration with data stored in the GVariant
+ *
+ * @param gvariant configuration in GVariant type
+ * @param config visitable structure to fill
+ */
+template <class Config>
+void loadFromGVariant(GVariant* gvariant, Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+ static_assert(!isUnion<Config>::value, "Don't use CONFIG_DECLARE_UNION in top level config");
+
+ FromGVariantVisitor visitor(gvariant);
+ config.accept(visitor);
+}
+
+/**
+ * Saves the config in a GVariant
+ *
+ * @param config visitable structure to convert
+ */
+template <class Config>
+GVariant* saveToGVariant(const Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+ static_assert(!isUnion<Config>::value, "Don't use CONFIG_DECLARE_UNION in top level config");
+
+ ToGVariantVisitor visitor;
+ config.accept(visitor);
+ return visitor.toVariant();
+}
+
+/**
+ * Fills the configuration with data stored in the json string
+ *
+ * @param jsonString configuration in a json format
+ * @param config visitable structure to fill
+ */
+template <class Config>
+void loadFromJsonString(const std::string& jsonString, Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ FromJsonVisitor visitor(jsonString);
+ config.accept(visitor);
+}
+
+/**
+ * Creates a string representation of the configuration in json format
+ *
+ * @param config visitable structure to convert
+ */
+template <class Config>
+std::string saveToJsonString(const Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ ToJsonVisitor visitor;
+ config.accept(visitor);
+ return visitor.toString();
+}
+
+/**
+ * Loads the config from a json file
+ *
+ * @param filename path to the file
+ * @param config visitable structure to load
+ */
+template <class Config>
+void loadFromJsonFile(const std::string& filename, Config& config)
+{
+ std::string content;
+ if (!fsutils::readFileContent(filename, content)) {
+ throw ConfigException("Could not load " + filename);
+ }
+ try {
+ loadFromJsonString(content, config);
+ } catch (ConfigException& e) {
+ throw ConfigException("Error in " + filename + ": " + e.what());
+ }
+}
+
+/**
+ * Saves the config in a json file
+ *
+ * @param filename path to the file
+ * @param config visitable structure to save
+ */
+template <class Config>
+void saveToJsonFile(const std::string& filename, const Config& config)
+{
+ const std::string content = saveToJsonString(config);
+ if (!fsutils::saveFileContent(filename, content)) {
+ throw ConfigException("Could not save " + filename);
+ }
+}
+
+/**
+ * Loads a visitable configuration from KVStore.
+ *
+ * @param filename path to the KVStore db
+ * @param config visitable structure to load
+ * @param configName name of the configuration inside the KVStore db
+ */
+template <class Config>
+void loadFromKVStore(const std::string& filename, Config& config, const std::string& configName)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ KVStore store(filename);
+ KVStore::Transaction transaction(store);
+ FromKVStoreVisitor visitor(store, configName);
+ config.accept(visitor);
+ transaction.commit();
+}
+
+/**
+ * Saves the config to a KVStore.
+ *
+ * @param filename path to the KVStore db
+ * @param config visitable structure to save
+ * @param configName name of the config inside the KVStore db
+ */
+template <class Config>
+void saveToKVStore(const std::string& filename, const Config& config, const std::string& configName)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ KVStore store(filename);
+ KVStore::Transaction transaction(store);
+ ToKVStoreVisitor visitor(store, configName);
+ config.accept(visitor);
+ transaction.commit();
+}
+
+/**
+ * Load the config from KVStore with defaults given in json
+ *
+ * @param kvfile path to the KVStore db
+ * @param jsonfile path to json file with defaults
+ * @param config visitable structure to save
+ * @param kvConfigName name of the config inside the KVStore db
+ */
+template <class Config>
+void loadFromKVStoreWithJson(const std::string& kvfile,
+ const std::string& json,
+ Config& config,
+ const std::string& kvConfigName)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ KVStore store(kvfile);
+ KVStore::Transaction transaction(store);
+ FromKVJsonVisitor visitor(store, json, kvConfigName);
+ config.accept(visitor);
+ transaction.commit();
+}
+
+/**
+ * Load the config from KVStore with defaults given in json file
+ *
+ * @param kvfile path to the KVStore db
+ * @param jsonfile path to json file with defaults
+ * @param config visitable structure to save
+ * @param kvConfigName name of the config inside the KVStore db
+ */
+template <class Config>
+void loadFromKVStoreWithJsonFile(const std::string& kvfile,
+ const std::string& jsonfile,
+ Config& config,
+ const std::string& kvConfigName)
+{
+ std::string content;
+ if (!fsutils::readFileContent(jsonfile, content)) {
+ throw ConfigException("Could not load " + jsonfile);
+ }
+ try {
+ loadFromKVStoreWithJson(kvfile, content, config, kvConfigName);
+ } catch (ConfigException& e) {
+ throw ConfigException("Error in " + jsonfile + ": " + e.what());
+ }
+}
+
+/**
+ * Load binary data from a file/socket/pipe represented by the fd
+ *
+ * @param fd file descriptor
+ * @param config visitable structure to load
+ */
+template <class Config>
+void loadFromFD(const int fd, Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ FromFDStoreVisitor visitor(fd);
+ config.accept(visitor);
+}
+
+/**
+ * Save binary data to a file/socket/pipe represented by the fd
+ *
+ * @param fd file descriptor
+ * @param config visitable structure to save
+ */
+template <class Config>
+void saveToFD(const int fd, const Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ ToFDStoreVisitor visitor(fd);
+ config.accept(visitor);
+}
+
+} // namespace config
+
+#endif // COMMON_CONFIG_MANAGER_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Definition of the class managing a sqlite3 database connection
+ */
+
+
+#include "config/sqlite3/connection.hpp"
+#include "config/exception.hpp"
+
+namespace config {
+namespace sqlite3 {
+
+Connection::Connection(const std::string& path)
+{
+ if (path.empty()) {
+ // Sqlite creates temporary database in case of empty path
+ // but we want to forbid this.
+ throw ConfigException("Error opening the database: empty path");
+ }
+ if (::sqlite3_open_v2(path.c_str(),
+ &mDbPtr,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+ NULL) != SQLITE_OK) {
+ throw ConfigException("Error opening the database: " + getErrorMessage());
+ }
+
+ if (mDbPtr == NULL) {
+ throw ConfigException("Error opening the database: Unable to allocate memory.");
+ }
+}
+
+Connection::~Connection()
+{
+ if (::sqlite3_close(mDbPtr) != SQLITE_OK) {
+ throw ConfigException("Error during closing the database. Error: " + getErrorMessage());
+ }
+}
+
+void Connection::exec(const std::string& query)
+{
+ char* mess;
+ if (::sqlite3_exec(mDbPtr, query.c_str(), 0, 0, &mess) != SQLITE_OK) {
+ throw ConfigException("Error during executing statement " + std::string(mess));
+ }
+}
+
+::sqlite3* Connection::get()
+{
+ return mDbPtr;
+}
+
+std::string Connection::getErrorMessage()
+{
+ return std::string(sqlite3_errmsg(mDbPtr));
+}
+
+} // namespace sqlite3
+} // namespace config
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Declaration of the class managing a sqlite3 database connection
+ */
+
+#ifndef COMMON_CONFIG_SQLITE3_CONNECTION_HPP
+#define COMMON_CONFIG_SQLITE3_CONNECTION_HPP
+
+#include <sqlite3.h>
+#include <string>
+
+namespace config {
+namespace sqlite3 {
+
+struct Connection {
+ /**
+ * @param path database file path
+ */
+ Connection(const std::string& path);
+ Connection(const Connection&) = delete;
+ ~Connection();
+
+ /**
+ * @return pointer to the corresponding sqlite3 database object
+ */
+ ::sqlite3* get();
+
+ /**
+ * @return last error message in the database
+ */
+ std::string getErrorMessage();
+
+ /**
+ * Executes the query in the database.
+ *
+ * @param query query to be executed
+ */
+ void exec(const std::string& query);
+
+private:
+ ::sqlite3* mDbPtr;
+};
+
+} // namespace sqlite3
+} // namespace config
+
+#endif // COMMON_CONFIG_SQLITE3_CONNECTION_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Definition of the class managing a sqlite3 statement
+ */
+
+#include "config/sqlite3/statement.hpp"
+#include "config/exception.hpp"
+
+
+namespace config {
+namespace sqlite3 {
+
+Statement::Statement(sqlite3::Connection& connRef, const std::string& query)
+ : mConnRef(connRef)
+{
+ if (::sqlite3_prepare_v2(connRef.get(),
+ query.c_str(),
+ query.size(),
+ &mStmtPtr,
+ NULL)
+ != SQLITE_OK) {
+ throw ConfigException("Error during preparing statement " +
+ mConnRef.getErrorMessage());
+ }
+
+ if (mStmtPtr == NULL) {
+ throw ConfigException("Wrong query: " + query);
+ }
+}
+
+Statement::Statement::~Statement()
+{
+ if (::sqlite3_finalize(mStmtPtr) != SQLITE_OK) {
+ throw ConfigException("Error during finalizing statement " +
+ mConnRef.getErrorMessage());
+ }
+}
+
+sqlite3_stmt* Statement::get()
+{
+ return mStmtPtr;
+}
+
+void Statement::reset()
+{
+ if (::sqlite3_clear_bindings(mStmtPtr) != SQLITE_OK) {
+ throw ConfigException("Error unbinding statement: " +
+ mConnRef.getErrorMessage());
+ }
+
+ if (::sqlite3_reset(mStmtPtr) != SQLITE_OK) {
+ throw ConfigException("Error reseting statement: " +
+ mConnRef.getErrorMessage());
+ }
+}
+
+} // namespace sqlite3
+} // namespace config
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Declaration of the class managing a sqlite3 statement
+ */
+
+#ifndef COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+#define COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+
+#include "config/sqlite3/connection.hpp"
+
+#include <sqlite3.h>
+#include <string>
+
+namespace config {
+namespace sqlite3 {
+
+struct Statement {
+
+ /**
+ * @param connRef reference to the Connection object
+ * @param query query to be executed
+ */
+ Statement(sqlite3::Connection& connRef, const std::string& query);
+ ~Statement();
+
+ /**
+ * @return pointer to the sqlite3 statement
+ */
+ sqlite3_stmt* get();
+
+ /**
+ * Clears the bindings and resets the statement.
+ * After this the statement can be executed again
+ */
+ void reset();
+
+private:
+ ::sqlite3_stmt* mStmtPtr;
+ sqlite3::Connection& mConnRef;
+};
+
+} // namespace sqlite3
+} // namespace config
+
+#endif // COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak (j.olszak@samsung.com)
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Visitor for saving to FDStore
+ */
+
+#ifndef COMMON_CONFIG_TO_FDSTORE_VISITOR_HPP
+#define COMMON_CONFIG_TO_FDSTORE_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/fdstore.hpp"
+
+#include <string>
+
+namespace config {
+
+class ToFDStoreVisitor {
+
+public:
+ ToFDStoreVisitor(int fd)
+ : mStore(fd)
+ {
+ }
+
+ ToFDStoreVisitor(const ToFDStoreVisitor&) = default;
+
+ ToFDStoreVisitor& operator=(const ToFDStoreVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string&, const T& value)
+ {
+ writeInternal(value);
+ }
+
+private:
+ FDStore mStore;
+
+ void writeInternal(const std::string& value)
+ {
+ writeInternal(value.size());
+ mStore.write(value.c_str(), value.size());
+ }
+
+ template<typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
+ void writeInternal(const T& value)
+ {
+ mStore.write(&value, sizeof(T));
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void writeInternal(const T& value)
+ {
+ ToFDStoreVisitor visitor(*this);
+ value.accept(visitor);
+ }
+
+ template<typename T>
+ void writeInternal(const std::vector<T>& values)
+ {
+ writeInternal(values.size());
+ for (const T& value : values) {
+ writeInternal(value);
+ }
+ }
+
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_TO_FDSTORE_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Mateusz Malicki (m.malicki2@samsung.com)
+ *
+ * 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
+ * @author Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief GVariant visitor
+ */
+
+#ifndef COMMON_CONFIG_TO_GVARIANT_VISITOR_HPP
+#define COMMON_CONFIG_TO_GVARIANT_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/is-union.hpp"
+
+#include <string>
+#include <vector>
+#include <glib.h>
+
+namespace config {
+
+class ToGVariantVisitor {
+
+public:
+ ToGVariantVisitor()
+ : mBuilder(g_variant_builder_new(G_VARIANT_TYPE_TUPLE))
+ {
+ }
+
+ ToGVariantVisitor(const ToGVariantVisitor& visitor)
+ : mBuilder(visitor.mBuilder ? g_variant_builder_ref(visitor.mBuilder) : nullptr)
+ {
+ }
+
+ ~ToGVariantVisitor()
+ {
+ if (mBuilder) {
+ g_variant_builder_unref(mBuilder);
+ }
+ }
+
+ ToGVariantVisitor& operator=(const ToGVariantVisitor&) = delete;
+
+ GVariant* toVariant()
+ {
+ if (mBuilder) {
+ GVariant* ret = g_variant_builder_end(mBuilder);
+ g_variant_builder_unref(mBuilder);
+ mBuilder = nullptr;
+ return ret;
+ }
+ return nullptr;
+ }
+
+ template<typename T>
+ void visit(const std::string& /* name */, const T& value)
+ {
+ writeInternal(value);
+ }
+private:
+ GVariantBuilder* mBuilder;
+
+ void writeInternal(std::int32_t value) { add("i", value); };
+ void writeInternal(std::int64_t value) { add("x", value); };
+ void writeInternal(std::uint32_t value) { add("u", value); };
+ void writeInternal(std::uint64_t value) { add("t", value); };
+ void writeInternal(bool value) { add("b", value); };
+ void writeInternal(double value) { add("d", value); };
+ void writeInternal(const std::string& value) { add("s", value.c_str()); };
+
+ template<typename T>
+ void writeInternal(const std::vector<T>& value)
+ {
+ if (!value.empty()) {
+ g_variant_builder_open(mBuilder, G_VARIANT_TYPE_ARRAY);
+ for (const T& v : value) {
+ writeInternal(v);
+ }
+ g_variant_builder_close(mBuilder);
+ } else {
+ g_variant_builder_add(mBuilder, "as", NULL);
+ }
+ }
+
+ template<typename T>
+ typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
+ writeInternal(const T& value)
+ {
+ ToGVariantVisitor visitor;
+ value.accept(visitor);
+ g_variant_builder_add_value(mBuilder, visitor.toVariant());
+ }
+
+ template<typename T>
+ typename std::enable_if<isVisitable<T>::value && isUnion<T>::value>::type
+ writeInternal(const T& value)
+ {
+ ToGVariantVisitor visitor;
+ value.accept(visitor);
+ add("v", visitor.toVariant());
+ }
+
+ template<typename Value>
+ void add(const char* type, Value value) {
+ g_variant_builder_add(mBuilder, type, value);
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_TO_GVARIANT_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief JSON visitor
+ */
+
+#ifndef COMMON_CONFIG_TO_JSON_VISITOR_HPP
+#define COMMON_CONFIG_TO_JSON_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/exception.hpp"
+
+#include <json/json.h>
+#include <string>
+#include <vector>
+
+namespace config {
+
+class ToJsonVisitor {
+
+public:
+ ToJsonVisitor()
+ : mObject(json_object_new_object())
+ {
+ }
+
+ ToJsonVisitor(const ToJsonVisitor& visitor)
+ : mObject(json_object_get(visitor.mObject))
+ {
+ }
+
+ ~ToJsonVisitor()
+ {
+ json_object_put(mObject);
+ }
+
+ ToJsonVisitor& operator=(const ToJsonVisitor&) = delete;
+
+ std::string toString() const
+ {
+ return json_object_to_json_string(mObject);
+ }
+
+ template<typename T>
+ void visit(const std::string& name, const T& value)
+ {
+ json_object_object_add(mObject, name.c_str(), toJsonObject(value));
+ }
+private:
+ json_object* mObject;
+
+
+ json_object* detach()
+ {
+ json_object* ret = mObject;
+ mObject = nullptr;
+ return ret;
+ }
+
+ static json_object* toJsonObject(std::int32_t value)
+ {
+ return json_object_new_int(value);
+ }
+
+ static json_object* toJsonObject(std::int64_t value)
+ {
+ return json_object_new_int64(value);
+ }
+
+ static json_object* toJsonObject(std::uint32_t value)
+ {
+ if (value > INT32_MAX) {
+ throw ConfigException("Value out of range");
+ }
+ return json_object_new_int(value);
+ }
+
+ static json_object* toJsonObject(std::uint64_t value)
+ {
+ if (value > INT64_MAX) {
+ throw ConfigException("Value out of range");
+ }
+ return json_object_new_int64(value);
+ }
+
+ static json_object* toJsonObject(bool value)
+ {
+ return json_object_new_boolean(value);
+ }
+
+ static json_object* toJsonObject(double value)
+ {
+ return json_object_new_double(value);
+ }
+
+ static json_object* toJsonObject(const std::string& value)
+ {
+ return json_object_new_string(value.c_str());
+ }
+
+ template<typename T>
+ static json_object* toJsonObject(const std::vector<T>& value)
+ {
+ json_object* array = json_object_new_array();
+ for (const T& v : value) {
+ json_object_array_add(array, toJsonObject(v));
+ }
+ return array;
+ }
+
+ template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
+ static json_object* toJsonObject(const T& value)
+ {
+ ToJsonVisitor visitor;
+ value.accept(visitor);
+ return visitor.detach();
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_TO_JSON_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak (j.olszak@samsung.com)
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Visitor for saving to KVStore
+ */
+
+#ifndef COMMON_CONFIG_TO_KVSTORE_VISITOR_HPP
+#define COMMON_CONFIG_TO_KVSTORE_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/kvstore.hpp"
+
+namespace config {
+
+class ToKVStoreVisitor {
+
+public:
+ ToKVStoreVisitor(KVStore& store, const std::string& prefix)
+ : mStore(store),
+ mKeyPrefix(prefix)
+ {
+ }
+
+ ToKVStoreVisitor& operator=(const ToKVStoreVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, const T& value)
+ {
+ setInternal(key(mKeyPrefix, name), value);
+ }
+
+private:
+ KVStore& mStore;
+ std::string mKeyPrefix;
+
+ ToKVStoreVisitor(const ToKVStoreVisitor& visitor, const std::string& prefix)
+ : mStore(visitor.mStore),
+ mKeyPrefix(prefix)
+ {
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void setInternal(const std::string& name, const T& value)
+ {
+ mStore.set(name, value);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void setInternal(const std::string& name, const T& value)
+ {
+ ToKVStoreVisitor visitor(*this, name);
+ value.accept(visitor);
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void setInternal(const std::string& name, const std::vector<T>& values)
+ {
+ mStore.remove(name);
+ mStore.set(name, values.size());
+ for (size_t i = 0; i < values.size(); ++i) {
+ setInternal(key(name, std::to_string(i)), values[i]);
+ }
+ }
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_TO_KVSTORE_VISITOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Dbus connection class
+ */
+
+#include "config.hpp"
+#include "dbus/connection.hpp"
+#include "dbus/exception.hpp"
+#include "utils/callback-wrapper.hpp"
+#include "utils/scoped-gerror.hpp"
+#include "utils/glib-utils.hpp"
+#include "logger/logger.hpp"
+
+using namespace vasum::utils;
+
+namespace dbus {
+
+
+namespace {
+
+const std::string SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket";
+const std::string INTROSPECT_INTERFACE = "org.freedesktop.DBus.Introspectable";
+const std::string INTROSPECT_METHOD = "Introspect";
+
+class MethodResultBuilderImpl : public MethodResultBuilder {
+public:
+ MethodResultBuilderImpl(GDBusMethodInvocation* invocation)
+ : mInvocation(invocation), mResultSet(false) {}
+ ~MethodResultBuilderImpl()
+ {
+ if (!mResultSet) {
+ setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented");
+ }
+ }
+ void set(GVariant* parameters)
+ {
+ g_dbus_method_invocation_return_value(mInvocation, parameters);
+ mResultSet = true;
+ }
+ void setVoid()
+ {
+ set(NULL);
+ }
+ void setError(const std::string& name, const std::string& message)
+ {
+ g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str());
+ mResultSet = true;
+ }
+private:
+ GDBusMethodInvocation* mInvocation;
+ bool mResultSet;
+};
+
+void throwDbusException(const ScopedGError& e)
+{
+ if (e->domain == g_io_error_quark()) {
+ if (e->code == G_IO_ERROR_DBUS_ERROR) {
+ throw DbusCustomException(e->message);
+ } else {
+ throw DbusIOException(e->message);
+ }
+ } else if (e->domain == g_dbus_error_quark()) {
+ throw DbusOperationException(e->message);
+ } else if (e->domain == g_markup_error_quark()) {
+ throw DbusInvalidArgumentException(e->message);
+ } else {
+ throw DbusException(e->message);
+ }
+}
+
+class AsyncMethodCallResultImpl : public AsyncMethodCallResult {
+public:
+ AsyncMethodCallResultImpl(GVariant* result, const ScopedGError& error)
+ : mResult(result), mError(error) {}
+ ~AsyncMethodCallResultImpl()
+ {
+ if (mResult) {
+ g_variant_unref(mResult);
+ }
+ }
+ GVariant* get()
+ {
+ if (mError) {
+ throwDbusException(mError);
+ }
+ return mResult;
+ }
+private:
+ GVariant* mResult;
+ const ScopedGError& mError;
+};
+
+} // namespace
+
+DbusConnection::Pointer DbusConnection::create(const std::string& address)
+{
+ return Pointer(new DbusConnection(address));
+}
+
+DbusConnection::Pointer DbusConnection::createSystem()
+{
+ return create(SYSTEM_BUS_ADDRESS);
+}
+
+DbusConnection::DbusConnection(const std::string& address)
+ : mConnection(NULL)
+ , mNameId(0)
+{
+ ScopedGError error;
+ const GDBusConnectionFlags flags =
+ static_cast<GDBusConnectionFlags>(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION);
+ // TODO: this is possible deadlock if the dbus
+ // socket exists but there is no dbus-daemon
+ mConnection = g_dbus_connection_new_for_address_sync(address.c_str(),
+ flags,
+ NULL,
+ NULL,
+ &error);
+ if (error) {
+ error.strip();
+ LOGE("Could not connect to " << address << "; " << error);
+ throwDbusException(error);
+ }
+}
+
+DbusConnection::~DbusConnection()
+{
+ // Close connection in a glib thread (because of a bug in glib)
+ GDBusConnection* connection = mConnection;
+ guint nameId = mNameId;
+
+ auto closeConnection = [=]() {
+ if (nameId) {
+ g_bus_unown_name(nameId);
+ }
+ g_object_unref(connection);
+ LOGT("Connection deleted");
+ };
+ executeInGlibThread(closeConnection, mGuard);
+}
+
+void DbusConnection::setName(const std::string& name,
+ const VoidCallback& onNameAcquired,
+ const VoidCallback& onNameLost)
+{
+ mNameId = g_bus_own_name_on_connection(mConnection,
+ name.c_str(),
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ &DbusConnection::onNameAcquired,
+ &DbusConnection::onNameLost,
+ createCallbackWrapper(
+ NameCallbacks(onNameAcquired, onNameLost),
+ mGuard.spawn()),
+ &deleteCallbackWrapper<NameCallbacks>);
+}
+
+void DbusConnection::onNameAcquired(GDBusConnection*, const gchar* name, gpointer userData)
+{
+ LOGD("Name acquired " << name);
+ const NameCallbacks& callbacks = getCallbackFromPointer<NameCallbacks>(userData);
+ if (callbacks.nameAcquired) {
+ callbacks.nameAcquired();
+ }
+}
+
+void DbusConnection::onNameLost(GDBusConnection*, const gchar* name, gpointer userData)
+{
+ LOGD("Name lost " << name);
+ const NameCallbacks& callbacks = getCallbackFromPointer<NameCallbacks>(userData);
+ if (callbacks.nameLost) {
+ callbacks.nameLost();
+ }
+}
+
+void DbusConnection::emitSignal(const std::string& objectPath,
+ const std::string& interface,
+ const std::string& name,
+ GVariant* parameters)
+{
+ ScopedGError error;
+ g_dbus_connection_emit_signal(mConnection,
+ NULL,
+ objectPath.c_str(),
+ interface.c_str(),
+ name.c_str(),
+ parameters,
+ &error);
+ if (error) {
+ error.strip();
+ LOGE("Emit signal failed; " << error);
+ throwDbusException(error);
+ }
+}
+
+DbusConnection::SubscriptionId DbusConnection::signalSubscribe(const SignalCallback& callback,
+ const std::string& senderBusName)
+{
+ return g_dbus_connection_signal_subscribe(mConnection,
+ senderBusName.empty() ? NULL : senderBusName.c_str(),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ &DbusConnection::onSignal,
+ createCallbackWrapper(callback,
+ mGuard.spawn()),
+ &deleteCallbackWrapper<SignalCallback>);
+}
+
+void DbusConnection::signalUnsubscribe(DbusConnection::SubscriptionId subscriptionId)
+{
+ g_dbus_connection_signal_unsubscribe(mConnection, subscriptionId);
+}
+
+void DbusConnection::onSignal(GDBusConnection*,
+ const gchar* sender,
+ const gchar* object,
+ const gchar* interface,
+ const gchar* name,
+ GVariant* parameters,
+ gpointer userData)
+{
+ const SignalCallback& callback = getCallbackFromPointer<SignalCallback>(userData);
+
+ LOGD("Signal: " << sender << "; " << object << "; " << interface << "; " << name);
+
+ if (callback) {
+ callback(sender, object, interface, name, parameters);
+ }
+}
+
+std::string DbusConnection::introspect(const std::string& busName, const std::string& objectPath)
+{
+ GVariantPtr result = DbusConnection::callMethod(busName,
+ objectPath,
+ INTROSPECT_INTERFACE,
+ INTROSPECT_METHOD,
+ NULL,
+ "(s)");
+ const gchar* xml;
+ g_variant_get(result.get(), "(&s)", &xml);
+ return xml;
+}
+
+void DbusConnection::registerObject(const std::string& objectPath,
+ const std::string& objectDefinitionXml,
+ const MethodCallCallback& callback)
+{
+ ScopedGError error;
+ GDBusNodeInfo* nodeInfo = g_dbus_node_info_new_for_xml(objectDefinitionXml.c_str(), &error);
+ if (nodeInfo != NULL && (nodeInfo->interfaces == NULL ||
+ nodeInfo->interfaces[0] == NULL ||
+ nodeInfo->interfaces[1] != NULL)) {
+ g_dbus_node_info_unref(nodeInfo);
+ g_set_error(&error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Expected exactly one interface");
+ }
+ if (error) {
+ error.strip();
+ LOGE("Invalid xml; " << error);
+ throwDbusException(error);
+ }
+ GDBusInterfaceInfo* interfaceInfo = nodeInfo->interfaces[0];
+
+ GDBusInterfaceVTable vtable;
+ vtable.method_call = &DbusConnection::onMethodCall;
+ vtable.get_property = NULL;
+ vtable.set_property = NULL;
+
+ g_dbus_connection_register_object(mConnection,
+ objectPath.c_str(),
+ interfaceInfo,
+ &vtable,
+ createCallbackWrapper(callback, mGuard.spawn()),
+ &deleteCallbackWrapper<MethodCallCallback>,
+ &error);
+ g_dbus_node_info_unref(nodeInfo);
+ if (error) {
+ error.strip();
+ LOGE("Register object failed; " << error);
+ throwDbusException(error);
+ }
+}
+
+void DbusConnection::onMethodCall(GDBusConnection*,
+ const gchar*,
+ const gchar* objectPath,
+ const gchar* interface,
+ const gchar* method,
+ GVariant* parameters,
+ GDBusMethodInvocation* invocation,
+ gpointer userData)
+{
+ const MethodCallCallback& callback = getCallbackFromPointer<MethodCallCallback>(userData);
+
+ LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method);
+
+ MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation));
+ if (callback) {
+ callback(objectPath, interface, method, parameters, resultBuilder);
+ }
+}
+
+GVariantPtr DbusConnection::callMethod(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interface,
+ const std::string& method,
+ GVariant* parameters,
+ const std::string& replyType,
+ int timeoutMs)
+{
+ ScopedGError error;
+ GVariant* result = g_dbus_connection_call_sync(mConnection,
+ busName.c_str(),
+ objectPath.c_str(),
+ interface.c_str(),
+ method.c_str(),
+ parameters,
+ replyType.empty() ? NULL
+ : G_VARIANT_TYPE(replyType.c_str()),
+ G_DBUS_CALL_FLAGS_NONE,
+ timeoutMs,
+ NULL,
+ &error);
+ if (error) {
+ error.strip();
+ LOGE("Call method failed; " << error);
+ throwDbusException(error);
+ }
+ return GVariantPtr(result, g_variant_unref);
+}
+
+void DbusConnection::callMethodAsync(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interface,
+ const std::string& method,
+ GVariant* parameters,
+ const std::string& replyType,
+ const AsyncMethodCallCallback& callback,
+ int timeoutMs)
+{
+ g_dbus_connection_call(mConnection,
+ busName.c_str(),
+ objectPath.c_str(),
+ interface.c_str(),
+ method.c_str(),
+ parameters,
+ replyType.empty() ? NULL
+ : G_VARIANT_TYPE(replyType.c_str()),
+ G_DBUS_CALL_FLAGS_NONE,
+ timeoutMs,
+ NULL,
+ &DbusConnection::onAsyncReady,
+ createCallbackWrapper(callback, mGuard.spawn()));
+}
+
+void DbusConnection::onAsyncReady(GObject* source,
+ GAsyncResult* asyncResult,
+ gpointer userData)
+{
+ std::unique_ptr<void, void(*)(void*)>
+ autoDeleteCallback(userData, &deleteCallbackWrapper<AsyncMethodCallCallback>);
+ GDBusConnection* connection = reinterpret_cast<GDBusConnection*>(source);
+ const AsyncMethodCallCallback& callback =
+ getCallbackFromPointer<AsyncMethodCallCallback>(userData);
+
+ ScopedGError error;
+ GVariant* result = g_dbus_connection_call_finish(connection, asyncResult, &error);
+ if (error) {
+ error.strip();
+ LOGE("Call method failed; " << error);
+ }
+ AsyncMethodCallResultImpl asyncMethodCallResult(result, error);
+ if (callback) {
+ try {
+ callback(asyncMethodCallResult);
+ } catch (DbusException& e) {
+ // Drop dbus exceptions (thrown from asyncMethodCallResult.get()).
+ // We can not ignore other exceptions - they must be catched inside callback,
+ // otherwise std::terminate will be called.
+ LOGW("Uncaugth dbus exception: " << e.what());
+ }
+ }
+}
+
+} // namespace dbus
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Dbus connection class
+ */
+
+#ifndef COMMON_DBUS_CONNECTION_HPP
+#define COMMON_DBUS_CONNECTION_HPP
+
+#include "utils/callback-guard.hpp"
+
+#include <memory>
+#include <string>
+#include <functional>
+#include <gio/gio.h>
+
+
+namespace dbus {
+
+
+typedef std::unique_ptr<GVariant, void(*)(GVariant*)> GVariantPtr;
+
+/**
+ * An interface used to set a result to a method call.
+ */
+class MethodResultBuilder {
+public:
+ typedef std::shared_ptr<MethodResultBuilder> Pointer;
+
+ virtual ~MethodResultBuilder() {}
+ virtual void set(GVariant* parameters) = 0;
+ virtual void setVoid() = 0;
+ virtual void setError(const std::string& name, const std::string& message) = 0;
+};
+
+/**
+ * An interface used to get result from async response.
+ */
+class AsyncMethodCallResult {
+public:
+ virtual ~AsyncMethodCallResult() {}
+ virtual GVariant* get() = 0; // throws DbusException on error
+};
+
+/**
+ * Dbus connection.
+ * Provides a functionality that allows to call dbus methods,
+ * register dbus interfaces, etc.
+ *
+ * TODO divide to interface and implementation header
+ */
+class DbusConnection {
+public:
+ typedef std::unique_ptr<DbusConnection> Pointer;
+
+ typedef std::function<void()> VoidCallback;
+
+ typedef std::function<void(const std::string& objectPath,
+ const std::string& interface,
+ const std::string& methodName,
+ GVariant* parameters,
+ MethodResultBuilder::Pointer result
+ )> MethodCallCallback;
+
+ typedef std::function<void(const std::string& senderBusName,
+ const std::string& objectPath,
+ const std::string& interface,
+ const std::string& signalName,
+ GVariant* parameters
+ )> SignalCallback;
+
+ typedef std::function<void(AsyncMethodCallResult& asyncMethodCallResult
+ )> AsyncMethodCallCallback;
+
+ typedef unsigned int SubscriptionId;
+
+ /**
+ * Creates a connection to the dbus with given address.
+ */
+ static Pointer create(const std::string& address);
+
+ /**
+ * Creates a connection to the system dbus.
+ */
+ static Pointer createSystem();
+
+ ~DbusConnection();
+
+ /**
+ * Sets a name to the dbus connection.
+ * It allows other client to call methods using this name.
+ */
+ void setName(const std::string& name,
+ const VoidCallback& onNameAcquired,
+ const VoidCallback& onNameLost);
+
+ /**
+ * Emits dbus signal.
+ */
+ void emitSignal(const std::string& objectPath,
+ const std::string& interface,
+ const std::string& name,
+ GVariant* parameters);
+
+ /**
+ * Subscribes to a signal.
+ * Empty sender means subscribe to all signals
+ * Returns a subscription identifier that can be used to unsubscribe signal
+ */
+ SubscriptionId signalSubscribe(const SignalCallback& callback, const std::string& senderBusName);
+
+ /**
+ * Unsubscribes from a signal.
+ */
+ void signalUnsubscribe(SubscriptionId subscriptionId);
+
+ /**
+ * Registers an object with given definition.
+ * Api calls will be handled by given callback.
+ */
+ void registerObject(const std::string& objectPath,
+ const std::string& objectDefinitionXml,
+ const MethodCallCallback& callback);
+
+ /**
+ * Call a dbus method
+ */
+ GVariantPtr callMethod(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interface,
+ const std::string& method,
+ GVariant* parameters,
+ const std::string& replyType,
+ int timeoutMs = -1);
+
+ /**
+ * Async call a dbus method
+ */
+ void callMethodAsync(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interface,
+ const std::string& method,
+ GVariant* parameters,
+ const std::string& replyType,
+ const AsyncMethodCallCallback& callback,
+ int timeoutMs = -1);
+
+ /**
+ * Returns an xml with meta description of specified dbus object.
+ */
+ std::string introspect(const std::string& busName, const std::string& objectPath);
+
+private:
+ struct NameCallbacks {
+ VoidCallback nameAcquired;
+ VoidCallback nameLost;
+
+ NameCallbacks(const VoidCallback& acquired, const VoidCallback& lost)
+ : nameAcquired(acquired), nameLost(lost) {}
+ };
+
+ vasum::utils::CallbackGuard mGuard;
+ GDBusConnection* mConnection;
+ guint mNameId;
+
+ DbusConnection(const std::string& address);
+
+ static void onNameAcquired(GDBusConnection* connection, const gchar* name, gpointer userData);
+ static void onNameLost(GDBusConnection* connection, const gchar* name, gpointer userData);
+ static void onSignal(GDBusConnection* connection,
+ const gchar* sender,
+ const gchar* object,
+ const gchar* interface,
+ const gchar* name,
+ GVariant* parameters,
+ gpointer userData);
+ static void onMethodCall(GDBusConnection* connection,
+ const gchar* sender,
+ const gchar* objectPath,
+ const gchar* interface,
+ const gchar* method,
+ GVariant* parameters,
+ GDBusMethodInvocation* invocation,
+ gpointer userData);
+ static void onAsyncReady(GObject* source,
+ GAsyncResult* asyncResult,
+ gpointer userData);
+};
+
+
+} // namespace dbus
+
+#endif // COMMON_DBUS_CONNECTION_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Dbus exceptions
+ */
+
+#ifndef COMMON_DBUS_EXCEPTION_HPP
+#define COMMON_DBUS_EXCEPTION_HPP
+
+#include <stdexcept>
+
+namespace dbus {
+
+/**
+ * Base class for dbus exceptions
+ */
+struct DbusException: public std::runtime_error {
+
+ DbusException(const std::string& error = "") : std::runtime_error(error) {}
+};
+
+/**
+ * Dbus IO exception (connection failed, connection lost, etc)
+ */
+struct DbusIOException: public DbusException {
+
+ DbusIOException(const std::string& error = "") : DbusException(error) {}
+};
+
+/**
+ * Dbus operation failed exception
+ */
+struct DbusOperationException: public DbusException {
+
+ DbusOperationException(const std::string& error = "") : DbusException(error) {}
+};
+
+/**
+ * Dbus custom exception triggered by user logic
+ */
+struct DbusCustomException: public DbusException {
+
+ DbusCustomException(const std::string& error = "") : DbusException(error) {}
+};
+
+/**
+ * Dbus invalid argument exception
+ */
+struct DbusInvalidArgumentException: public DbusException {
+
+ DbusInvalidArgumentException(const std::string& error = "") : DbusException(error) {}
+};
+
+} // namespace dbus
+
+#endif // COMMON_DBUS_EXCEPTION_HPP
/**
* This class wraps communication via UX sockets for client applications.
- * It uses serialization mechanism from libConfig.
+ * It uses serialization mechanism from Config.
*
* For message format @see ipc::Processor
*/
* This class wraps communication via UX sockets
*
* It's intended to be used both in Client and Service classes.
-* It uses a serialization mechanism from libConfig.
+* It uses a serialization mechanism from Config.
* Library user will only have to pass the types that each call will send and receive
*
* Message format:
/**
* This class wraps communication via UX sockets.
- * It uses serialization mechanism from libConfig.
+ * It uses serialization mechanism from Config.
*
* For message format @see ipc::Processor
*/
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Systemd journal backend for logger
+ */
+
+#include "config.hpp"
+#include "logger/backend-journal.hpp"
+
+#define SD_JOURNAL_SUPPRESS_LOCATION
+#include <systemd/sd-journal.h>
+
+namespace logger {
+
+namespace {
+
+inline int toJournalPriority(LogLevel logLevel)
+{
+ switch (logLevel) {
+ case LogLevel::ERROR:
+ return LOG_ERR; // 3
+ case LogLevel::WARN:
+ return LOG_WARNING; // 4
+ case LogLevel::INFO:
+ return LOG_INFO; // 6
+ case LogLevel::DEBUG:
+ return LOG_DEBUG; // 7
+ case LogLevel::TRACE:
+ return LOG_DEBUG; // 7
+ case LogLevel::HELP:
+ return LOG_DEBUG; // 7
+ default:
+ return LOG_DEBUG; // 7
+ }
+}
+
+} // namespace
+
+void SystemdJournalBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+{
+ sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel),
+ "CODE_FILE=%s", file.c_str(),
+ "CODE_LINE=%d", line,
+ "CODE_FUNC=%s", func.c_str(),
+ "MESSAGE=%s", message.c_str(),
+ NULL);
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Systemd journal backend for logger
+ */
+
+#ifndef COMMON_LOGGER_BACKEND_JOURNAL_HPP
+#define COMMON_LOGGER_BACKEND_JOURNAL_HPP
+
+#include "logger/backend.hpp"
+
+namespace logger {
+
+/**
+ * systemd journal logging backend
+ */
+class SystemdJournalBackend : public LogBackend {
+public:
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_BACKEND_JOURNAL_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Broda <p.broda@partner.samsung.com>
+ *
+ * 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
+ * @author Pawel Broda (p.broda@partner.samsung.com)
+ * @brief Null backend for logger
+ */
+
+#ifndef COMMON_LOGGER_BACKEND_NULL_HPP
+#define COMMON_LOGGER_BACKEND_NULL_HPP
+
+#include "logger/backend.hpp"
+
+namespace logger {
+
+/**
+ * Null logging backend
+ */
+class NullLogger : public LogBackend {
+public:
+ void log(LogLevel /*logLevel*/,
+ const std::string& /*file*/,
+ const unsigned int& /*line*/,
+ const std::string& /*func*/,
+ const std::string& /*message*/) override {}
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_BACKEND_NULL_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Broda <p.broda@partner.samsung.com>
+ *
+ * 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
+ * @author Pawel Broda (p.broda@partner.samsung.com)
+ * @brief Stderr backend for logger
+ */
+
+#include "config.hpp"
+#include "logger/backend-stderr.hpp"
+#include "logger/formatter.hpp"
+
+#include <boost/tokenizer.hpp>
+
+namespace logger {
+
+void StderrBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+{
+ typedef boost::char_separator<char> charSeparator;
+ typedef boost::tokenizer<charSeparator> tokenizer;
+
+ // example log string
+ // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing
+
+ const std::string logColor = LogFormatter::getConsoleColor(logLevel);
+ const std::string defaultColor = LogFormatter::getDefaultConsoleColor();
+ const std::string header = LogFormatter::getHeader(logLevel, file, line, func);
+ tokenizer tokens(message, charSeparator("\n"));
+ for (const auto& messageLine : tokens) {
+ if (!messageLine.empty()) {
+ fprintf(stderr,
+ "%s%s%s%s\n",
+ logColor.c_str(),
+ header.c_str(),
+ messageLine.c_str(),
+ defaultColor.c_str());
+ }
+ }
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Broda <p.broda@partner.samsung.com>
+ *
+ * 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
+ * @author Pawel Broda (p.broda@partner.samsung.com)
+ * @brief Stderr backend for logger
+ */
+
+#ifndef COMMON_LOGGER_BACKEND_STDERR_HPP
+#define COMMON_LOGGER_BACKEND_STDERR_HPP
+
+#include "logger/backend.hpp"
+
+namespace logger {
+
+/**
+ * Stderr logging backend
+ */
+class StderrBackend : public LogBackend {
+public:
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_BACKEND_STDERR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Broda <p.broda@partner.samsung.com>
+ *
+ * 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
+ * @author Pawel Broda (p.broda@partner.samsung.com)
+ * @brief Logging backend
+ */
+
+#ifndef COMMON_LOGGER_BACKEND_HPP
+#define COMMON_LOGGER_BACKEND_HPP
+
+#include "logger/level.hpp"
+
+#include <string>
+
+namespace logger {
+
+/**
+ * Abstract class for logger
+ */
+class LogBackend {
+public:
+ virtual void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) = 0;
+ virtual ~LogBackend() {}
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_BACKEND_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Console color for StderrBackend logger
+ */
+
+#include "config.hpp"
+#include "logger/ccolor.hpp"
+
+#include <stdio.h>
+
+namespace logger {
+
+std::string getConsoleEscapeSequence(Attributes attr, Color color)
+{
+ char command[10];
+
+ // Command is the control command to the terminal
+ snprintf(command, sizeof(command), "%c[%d;%dm", 0x1B, attr, color);
+ return std::string(command);
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Console color for StderrBackend logger
+ */
+
+#ifndef COMMON_LOGGER_CCOLOR_HPP
+#define COMMON_LOGGER_CCOLOR_HPP
+
+#include <string>
+
+namespace logger {
+
+enum class Color : unsigned int {
+ DEFAULT = 0,
+ BLACK = 90,
+ RED = 91,
+ GREEN = 92,
+ YELLOW = 93,
+ BLUE = 94,
+ MAGENTA = 95,
+ CYAN = 96,
+ WHITE = 97
+};
+
+enum class Attributes : unsigned int {
+ DEFAULT = 0,
+ BOLD = 1
+};
+
+std::string getConsoleEscapeSequence(Attributes attr, Color color);
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_CCOLOR_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Helper formatter for logger
+ */
+
+#include "config.hpp"
+#include "logger/formatter.hpp"
+#include "logger/ccolor.hpp"
+
+#include <sys/time.h>
+#include <cassert>
+#include <sstream>
+#include <iomanip>
+#include <thread>
+#include <atomic>
+
+namespace logger {
+
+namespace {
+
+const int TIME_COLUMN_LENGTH = 12;
+const int SEVERITY_COLUMN_LENGTH = 8;
+const int THREAD_COLUMN_LENGTH = 3;
+const int FILE_COLUMN_LENGTH = 60;
+
+std::atomic<unsigned int> gNextThreadId(1);
+thread_local unsigned int gThisThreadId(0);
+
+} // namespace
+
+unsigned int LogFormatter::getCurrentThread(void)
+{
+ unsigned int id = gThisThreadId;
+ if (id == 0) {
+ gThisThreadId = id = gNextThreadId++;
+ }
+
+ return id;
+}
+
+std::string LogFormatter::getCurrentTime(void)
+{
+ char time[TIME_COLUMN_LENGTH + 1];
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ struct tm* tm = localtime(&tv.tv_sec);
+ snprintf(time,
+ sizeof(time),
+ "%02d:%02d:%02d.%03d",
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ int(tv.tv_usec / 1000));
+
+ return std::string(time);
+}
+
+std::string LogFormatter::getConsoleColor(LogLevel logLevel)
+{
+ switch (logLevel) {
+ case LogLevel::ERROR:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::RED);
+ case LogLevel::WARN:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW);
+ case LogLevel::INFO:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE);
+ case LogLevel::DEBUG:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN);
+ case LogLevel::TRACE:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK);
+ case LogLevel::HELP:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA);
+ default:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
+ }
+}
+
+std::string LogFormatter::getDefaultConsoleColor(void)
+{
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
+}
+
+std::string LogFormatter::stripProjectDir(const std::string& file,
+ const std::string& rootDir)
+{
+ // If rootdir is empty then return full name
+ if (rootDir.empty()) {
+ return file;
+ }
+ const std::string sourceDir = rootDir + "/";
+ // If file does not belong to rootDir then also return full name
+ if (0 != file.compare(0, sourceDir.size(), sourceDir)) {
+ return file;
+ }
+ return file.substr(sourceDir.size());
+}
+
+std::string LogFormatter::getHeader(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func)
+{
+ std::ostringstream logLine;
+ logLine << getCurrentTime() << ' '
+ << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']'
+ << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": "
+ << std::left << std::setw(FILE_COLUMN_LENGTH)
+ << file + ':' + std::to_string(line) + ' ' + func + ':';
+ return logLine.str();
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk <d.michaluk@samsung.com>
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief Helper formatter for logger
+ */
+
+#ifndef COMMON_LOGGER_FORMATTER_HPP
+#define COMMON_LOGGER_FORMATTER_HPP
+
+#include "logger/level.hpp"
+
+#include <string>
+
+namespace logger {
+
+class LogFormatter {
+public:
+ static unsigned int getCurrentThread(void);
+ static std::string getCurrentTime(void);
+ static std::string getConsoleColor(LogLevel logLevel);
+ static std::string getDefaultConsoleColor(void);
+ static std::string stripProjectDir(const std::string& file,
+ const std::string& rootDir);
+ static std::string getHeader(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func);
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_FORMATTER_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Functions to handle LogLevel
+ */
+
+#include "config.hpp"
+#include "logger/level.hpp"
+
+#include <stdexcept>
+#include <boost/algorithm/string.hpp>
+
+namespace logger {
+
+LogLevel parseLogLevel(const std::string& level)
+{
+ if (boost::iequals(level, "ERROR")) {
+ return LogLevel::ERROR;
+ } else if (boost::iequals(level, "WARN")) {
+ return LogLevel::WARN;
+ } else if (boost::iequals(level, "INFO")) {
+ return LogLevel::INFO;
+ } else if (boost::iequals(level, "DEBUG")) {
+ return LogLevel::DEBUG;
+ } else if (boost::iequals(level, "TRACE")) {
+ return LogLevel::TRACE;
+ } else if (boost::iequals(level, "HELP")) {
+ return LogLevel::HELP;
+ } else {
+ throw std::runtime_error("Invalid LogLevel to parse");
+ }
+}
+
+std::string toString(const LogLevel logLevel)
+{
+ switch (logLevel) {
+ case LogLevel::ERROR:
+ return "ERROR";
+ case LogLevel::WARN:
+ return "WARN";
+ case LogLevel::INFO:
+ return "INFO";
+ case LogLevel::DEBUG:
+ return "DEBUG";
+ case LogLevel::TRACE:
+ return "TRACE";
+ case LogLevel::HELP:
+ return "HELP";
+ default:
+ return "UNKNOWN";
+ }
+}
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Dariusz Michaluk (d.michaluk@samsung.com)
+ *
+ * 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
+ * @author Dariusz Michaluk (d.michaluk@samsung.com)
+ * @brief LogLevel
+ */
+
+#ifndef COMMON_LOGGER_LEVEL_HPP
+#define COMMON_LOGGER_LEVEL_HPP
+
+#include <string>
+
+namespace logger {
+
+enum class LogLevel {
+ TRACE,
+ DEBUG,
+ INFO,
+ WARN,
+ ERROR,
+ HELP
+};
+
+/**
+ * @param logLevel LogLevel
+ * @return std::sting representation of the LogLevel value
+ */
+std::string toString(const LogLevel logLevel);
+
+/**
+ * @param level string representation of log level
+ * @return parsed LogLevel value
+ */
+LogLevel parseLogLevel(const std::string& level);
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_LEVEL_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Lukasz Kostyra <l.kostyra@samsung.com>
+ *
+ * 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
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @brief Scope logger class implementation
+ */
+
+#include "logger/logger-scope.hpp"
+#include "logger/logger.hpp"
+
+namespace logger {
+
+SStreamWrapper::operator std::string() const
+{
+ return mSStream.str();
+}
+
+LoggerScope::LoggerScope(const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& message,
+ const std::string& rootDir):
+ mFile(file),
+ mLine(line),
+ mFunc(func),
+ mMessage(message),
+ mRootDir(rootDir)
+{
+ logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage, mFile,
+ mLine, mFunc, mRootDir);
+}
+
+LoggerScope::~LoggerScope()
+{
+ logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage, mFile,
+ mLine, mFunc, mRootDir);
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Lukasz Kostyra <l.kostyra@samsung.com>
+ *
+ * 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
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @brief Scope logger class declaration
+ */
+
+#ifndef COMMON_LOGGER_LOGGER_SCOPE_HPP
+#define COMMON_LOGGER_LOGGER_SCOPE_HPP
+
+#include <string>
+#include <sstream>
+
+namespace logger {
+
+class SStreamWrapper
+{
+public:
+ operator std::string() const;
+
+ template <typename T>
+ SStreamWrapper& operator<<(const T& b)
+ {
+ this->mSStream << b;
+ return *this;
+ }
+
+private:
+ std::ostringstream mSStream;
+};
+
+/**
+ * Class specifically for scope debug logging. Should be used at the beggining of a scope.
+ * Constructor marks scope enterance, destructor marks scope leave.
+ */
+class LoggerScope
+{
+public:
+ LoggerScope(const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& message,
+ const std::string& rootDir);
+ ~LoggerScope();
+
+private:
+ const std::string mFile;
+ const unsigned int mLine;
+ const std::string mFunc;
+ const std::string mMessage;
+ const std::string mRootDir;
+};
+
+} // namespace logger
+
+// macro to automatically create LoggerScope object
+#define LOGS(MSG) logger::LoggerScope logScopeObj(__FILE__, __LINE__, __func__, \
+ logger::SStreamWrapper() << MSG, \
+ PROJECT_SOURCE_DIR)
+
+#endif // COMMON_LOGGER_LOGGER_SCOPE_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Broda <p.broda@partner.samsung.com>
+ *
+ * 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
+ * @author Pawel Broda (p.broda@partner.samsung.com)
+ * @brief Logger
+ */
+
+#include "config.hpp"
+#include "logger/logger.hpp"
+#include "logger/formatter.hpp"
+#include "logger/backend-null.hpp"
+
+#include <memory>
+#include <mutex>
+
+namespace logger {
+
+namespace {
+
+volatile LogLevel gLogLevel = LogLevel::DEBUG;
+std::unique_ptr<LogBackend> gLogBackendPtr(new NullLogger());
+std::mutex gLogMutex;
+
+} // namespace
+
+void Logger::logMessage(LogLevel logLevel,
+ const std::string& message,
+ const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& rootDir)
+{
+ std::string sfile = LogFormatter::stripProjectDir(file, rootDir);
+ std::unique_lock<std::mutex> lock(gLogMutex);
+ gLogBackendPtr->log(logLevel, sfile, line, func, message);
+}
+
+void Logger::setLogLevel(const LogLevel level)
+{
+ gLogLevel = level;
+}
+
+void Logger::setLogLevel(const std::string& level)
+{
+ gLogLevel = parseLogLevel(level);
+}
+
+LogLevel Logger::getLogLevel(void)
+{
+ return gLogLevel;
+}
+
+void Logger::setLogBackend(LogBackend* pBackend)
+{
+ std::unique_lock<std::mutex> lock(gLogMutex);
+ gLogBackendPtr.reset(pBackend);
+}
+
+} // namespace logger
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Logger
+ */
+
+#ifndef COMMON_LOGGER_LOGGER_HPP
+#define COMMON_LOGGER_LOGGER_HPP
+
+#include "logger/level.hpp"
+
+#include <sstream>
+#include <string>
+
+#ifndef PROJECT_SOURCE_DIR
+#define PROJECT_SOURCE_DIR ""
+#endif
+
+namespace logger {
+
+class LogBackend;
+
+class Logger {
+public:
+ static void logMessage(LogLevel logLevel,
+ const std::string& message,
+ const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& rootDir);
+
+ static void setLogLevel(const LogLevel level);
+ static void setLogLevel(const std::string& level);
+ static LogLevel getLogLevel(void);
+ static void setLogBackend(LogBackend* pBackend);
+};
+
+} // namespace logger
+
+#define LOG(SEVERITY, MESSAGE) \
+ do { \
+ if (logger::Logger::getLogLevel() <= logger::LogLevel::SEVERITY) { \
+ std::ostringstream messageStream__; \
+ messageStream__ << MESSAGE; \
+ logger::Logger::logMessage(logger::LogLevel::SEVERITY, \
+ messageStream__.str(), \
+ __FILE__, \
+ __LINE__, \
+ __func__, \
+ PROJECT_SOURCE_DIR); \
+ } \
+ } while (0)
+
+#define LOGE(MESSAGE) LOG(ERROR, MESSAGE)
+#define LOGW(MESSAGE) LOG(WARN, MESSAGE)
+#define LOGI(MESSAGE) LOG(INFO, MESSAGE)
+#define LOGD(MESSAGE) LOG(DEBUG, MESSAGE)
+#define LOGH(MESSAGE) LOG(HELP, MESSAGE)
+#define LOGT(MESSAGE) LOG(TRACE, MESSAGE)
+
+#endif // COMMON_LOGGER_LOGGER_HPP
#include <stack>
#include <type_traits>
#include <cstdlib>
+#include <sys/socket.h>
#include <linux/netlink.h>
namespace vasum {
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief C++ wrapper of glib main loop
+ */
+
+#include "config.hpp"
+#include "utils/glib-utils.hpp"
+#include "utils/callback-wrapper.hpp"
+
+#include <glib-object.h>
+
+namespace vasum {
+namespace utils {
+
+namespace {
+
+gboolean onIddle(gpointer data)
+{
+ const VoidCallback& callback = getCallbackFromPointer<VoidCallback>(data);
+ callback();
+ return FALSE;
+}
+
+} // namespace
+
+void executeInGlibThread(const VoidCallback& callback, const CallbackGuard& guard)
+{
+ if (!callback) {
+ return;
+ }
+ g_idle_add_full(G_PRIORITY_DEFAULT,
+ &onIddle,
+ utils::createCallbackWrapper(callback, guard.spawn()),
+ &utils::deleteCallbackWrapper<VoidCallback>);
+
+}
+
+
+} // namespace utils
+} // namespace vasum
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Miscellaneous helpers for the Glib library
+ */
+
+#ifndef COMMON_UTILS_GLIB_UTILS_HPP
+#define COMMON_UTILS_GLIB_UTILS_HPP
+
+#include "utils/callback-guard.hpp"
+
+namespace vasum {
+namespace utils {
+
+typedef std::function<void()> VoidCallback;
+
+/**
+ * Executes a callback in glib thread (adds an iddle event to glib)
+ */
+void executeInGlibThread(const VoidCallback& callback, const CallbackGuard& guard);
+
+
+} // namespace utils
+} // namespace vasum
+
+#endif // COMMON_UTILS_GLIB_UTILS_HPP
BuildRequires: libjson-devel >= 0.10
BuildRequires: libcap-ng-devel
BuildRequires: lxc-devel
-BuildRequires: pkgconfig(libConfig)
-BuildRequires: pkgconfig(libLogger)
-BuildRequires: pkgconfig(libSimpleDbus)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libsystemd-journal)
BuildRequires: pkgconfig(libsystemd-daemon)
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex)
PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0 libsystemd-journal libsystemd-daemon
- libcap-ng libLogger libSimpleDbus libConfig)
+ libcap-ng sqlite3)
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(${CLIENT_FOLDER})
#include <string>
#include <vector>
#include <tuple>
+#include <sys/socket.h>
#include <linux/if_link.h>
#include <sys/types.h>
FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex)
PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0 libsystemd-daemon
- libsystemd-journal libcap-ng libLogger libSimpleDbus libConfig)
+ libsystemd-journal libcap-ng sqlite3)
INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER}
${SOCKET_TEST_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
#include <config.hpp>
#include "socket-test.hpp"
-#include <logger/config.hpp>
+#include <config.hpp>
#include <logger/logger.hpp>
#include <logger/backend-journal.hpp>
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Zone Daemon...")
FILE(GLOB project_SRCS *.cpp *.hpp)
-FILE(GLOB common_SRCS ${COMMON_FOLDER}/dbus/*.cpp ${COMMON_FOLDER}/dbus/*.hpp
- ${COMMON_FOLDER}/log/*.cpp ${COMMON_FOLDER}/log/*.hpp
- ${COMMON_FOLDER}/utils/*.cpp ${COMMON_FOLDER}/utils/*.hpp
+FILE(GLOB common_SRCS ${COMMON_FOLDER}/dbus/*.cpp ${COMMON_FOLDER}/dbus/*.hpp
+ ${COMMON_FOLDER}/logger/*.cpp ${COMMON_FOLDER}/logger/*.hpp
+ ${COMMON_FOLDER}/utils/*.cpp ${COMMON_FOLDER}/utils/*.hpp
${COMMON_FOLDER}/*.cpp)
## Setup target ################################################################
## Link libraries ##############################################################
FIND_PACKAGE (Boost COMPONENTS program_options system filesystem)
-PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal libcap-ng
- libLogger libSimpleDbus libConfig)
+PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal libcap-ng)
+
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${ZONE_DAEMON_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})