From d614bd7ab9eec3c7757649bb9e9f73a0b4acb92a Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 18 Jul 2014 21:34:49 +0200 Subject: [PATCH] Implement Storage::save() using StorageSerializer and clean up There was a lot of mess in #includes directives and forward declarations of classes. It was cleaned out. InMemoryStorageBackend::Buckets were moved to separate file in order not to make a cyclic dependency. New exception class CannotCreateFile was added. Change-Id: I32b234ba0f4872791a9f931690c58e623de7096f --- src/common/exceptions/CannotCreateFileException.h | 55 ++++++++++++++++++++ src/service/storage/BucketDeserializer.cpp | 19 ++++--- src/service/storage/BucketDeserializer.h | 7 ++- src/service/storage/Buckets.h | 38 ++++++++++++++ src/service/storage/InMemoryStorageBackend.cpp | 63 +++++++++++++++++++++-- src/service/storage/InMemoryStorageBackend.h | 37 +++++++------ src/service/storage/Storage.cpp | 47 +++++++++-------- src/service/storage/Storage.h | 23 ++++----- src/service/storage/StorageBackend.h | 27 +++++----- src/service/storage/StorageDeserializer.cpp | 15 +++--- src/service/storage/StorageDeserializer.h | 20 ++++--- src/service/storage/StorageSerializer.cpp | 12 +++-- src/service/storage/StorageSerializer.h | 21 ++++---- 13 files changed, 280 insertions(+), 104 deletions(-) create mode 100644 src/common/exceptions/CannotCreateFileException.h create mode 100644 src/service/storage/Buckets.h diff --git a/src/common/exceptions/CannotCreateFileException.h b/src/common/exceptions/CannotCreateFileException.h new file mode 100644 index 0000000..bb3f937 --- /dev/null +++ b/src/common/exceptions/CannotCreateFileException.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file CannotCreateFileException.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines exception thrown when database file cannot be created + */ + +#ifndef SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ + +#include + +#include + +namespace Cynara { + +class CannotCreateFileException : public DatabaseException { +public: + CannotCreateFileException(const std::string &filename) : m_filename(filename) {}; + virtual ~CannotCreateFileException() = default; + + const std::string message(void) const { + if (m_message.empty()) { + m_message = "File " + filename() + " cannot be created"; + } + return m_message; + } + + const std::string &filename(void) const { + return m_filename; + } + +private: + mutable std::string m_message; + std::string m_filename; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ */ diff --git a/src/service/storage/BucketDeserializer.cpp b/src/service/storage/BucketDeserializer.cpp index 914f766..1bfac50 100644 --- a/src/service/storage/BucketDeserializer.cpp +++ b/src/service/storage/BucketDeserializer.cpp @@ -20,15 +20,20 @@ * @brief Methods implementation of Cynara::BucketDeserializer */ +#include +#include +#include +#include + #include -#include +#include +#include +#include + #include #include -#include -#include -#include -#include +#include "BucketDeserializer.h" namespace Cynara { @@ -36,7 +41,7 @@ PolicyCollection BucketDeserializer::loadPolicies(void) { PolicyCollection policies; // TODO: Get someone smart to do error checking on stream - for(std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { std::string line; std::getline(m_inStream, line, StorageSerializer::recordSeparator()); @@ -61,7 +66,7 @@ PolicyCollection BucketDeserializer::loadPolicies(void) { PolicyKey BucketDeserializer::parseKey(const std::string &line, std::size_t &beginToken) { std::array keyFeatures; - for(std::size_t tokenNum = 0; tokenNum < keyFeatures.size(); ++tokenNum) { + for (std::size_t tokenNum = 0; tokenNum < keyFeatures.size(); ++tokenNum) { auto endToken = line.find(StorageSerializer::fieldSeparator(), beginToken); if (endToken != std::string::npos) { keyFeatures[tokenNum] = line.substr(beginToken, endToken - beginToken); diff --git a/src/service/storage/BucketDeserializer.h b/src/service/storage/BucketDeserializer.h index a9b7b8c..393991e 100644 --- a/src/service/storage/BucketDeserializer.h +++ b/src/service/storage/BucketDeserializer.h @@ -22,12 +22,11 @@ #ifndef SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ #define SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ +#include +#include + #include #include -#include -#include - -#include namespace Cynara { diff --git a/src/service/storage/Buckets.h b/src/service/storage/Buckets.h new file mode 100644 index 0000000..1fdc249 --- /dev/null +++ b/src/service/storage/Buckets.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file Buckets.h + * @author Aleksander Zdyb + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Headers for Buckets + */ + +#ifndef SRC_SERVICE_STORAGE_BUCKETS_H_ +#define SRC_SERVICE_STORAGE_BUCKETS_H_ + +#include + +#include +#include + +namespace Cynara { + +typedef std::unordered_map Buckets; + +} /* namespace Cynara */ + +#endif /* SRC_SERVICE_STORAGE_BUCKETS_H_ */ diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index 1b7ae44..5d18219 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -20,21 +20,34 @@ * @brief Implementation of InMemoryStorageBackend */ +#include #include #include +#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include + #include #include -#include +#include #include "InMemoryStorageBackend.h" namespace Cynara { void InMemoryStorageBackend::load(void) { - std::string indexFilename = m_dbPath + "buckets"; + std::string indexFilename = m_dbPath + m_indexFileName; try { std::ifstream indexStream; @@ -49,12 +62,33 @@ void InMemoryStorageBackend::load(void) { LOGE("Reading cynara database failed."); } - if(!hasBucket(defaultPolicyBucketId)) { + if (!hasBucket(defaultPolicyBucketId)) { LOGN("Creating defaultBucket."); this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); } } +void InMemoryStorageBackend::save(void) { + + //create directory + int ret = mkdir(m_dbPath.c_str(), S_IRWXU); + if (ret < 0) { + int err = errno; + if (err != EEXIST) { + LOGE("Cannot create directory <%s>. Error [%d] : <%s>.", + m_dbPath.c_str(), err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + } + + std::ofstream indexStream; + openDumpFileStream(indexStream, m_dbPath + m_indexFileName); + + StorageSerializer storageSerializer(indexStream); + storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener, + this, std::placeholders::_1)); +} + PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) { return searchBucket(defaultPolicyBucketId, key); } @@ -116,7 +150,7 @@ void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const [key](PolicyPtr policy) -> bool { return policy->key() == key; }), policies.end()); - } catch(const std::out_of_range &) { + } catch (const std::out_of_range &) { throw BucketNotExistsException(bucketId); } } @@ -133,7 +167,7 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) { return false; }; - for(auto &bucketIter : buckets()) { + for (auto &bucketIter : buckets()) { // TODO: Move the erase code to PolicyCollection maybe? auto &bucket = bucketIter.second; auto &policies = bucket.policyCollection(); @@ -151,6 +185,16 @@ void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::st throw FileNotFoundException(filename); } +void InMemoryStorageBackend::openDumpFileStream(std::ofstream &stream, + const std::string &filename) { + stream.open(filename, std::ofstream::out | std::ofstream::trunc); + + if (!stream.is_open()) { + throw CannotCreateFileException(filename); + return; + } +} + std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( const PolicyBucketId &bucketId) { std::string bucketFilename = m_dbPath + "_" + bucketId; @@ -163,4 +207,13 @@ std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( } } +std::shared_ptr InMemoryStorageBackend::bucketDumpStreamOpener( + const PolicyBucketId &bucketId) { + std::string bucketFilename = m_dbPath + "_" + bucketId; + std::ofstream bucketStream; + + openDumpFileStream(bucketStream, bucketFilename); + return std::make_shared(bucketStream); +} + } /* namespace Cynara */ diff --git a/src/service/storage/InMemoryStorageBackend.h b/src/service/storage/InMemoryStorageBackend.h index 1791b00..5127bc6 100644 --- a/src/service/storage/InMemoryStorageBackend.h +++ b/src/service/storage/InMemoryStorageBackend.h @@ -20,34 +20,34 @@ * @brief Headers for InMemoryStorageBackend */ -#ifndef INMEMORYSTORAGEBACKEND_H_ -#define INMEMORYSTORAGEBACKEND_H_ +#ifndef SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ +#define SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ -#include #include -#include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "StorageBackend.h" +#include +#include +#include +#include namespace Cynara { class InMemoryStorageBackend : public StorageBackend { public: - typedef std::unordered_map Buckets; - InMemoryStorageBackend(const std::string &path) : m_dbPath(path) { } - virtual ~InMemoryStorageBackend() = default; virtual void load(void); + virtual void save(void); virtual PolicyBucket searchDefaultBucket(const PolicyKey &key); virtual PolicyBucket searchBucket(const PolicyBucketId &bucketId, const PolicyKey &key); @@ -63,15 +63,20 @@ protected: void openFileStream(std::ifstream &stream, const std::string &filename); std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId); + void openDumpFileStream(std::ofstream &stream, const std::string &filename); + std::shared_ptr bucketDumpStreamOpener(const PolicyBucketId &bucketId); + private: std::string m_dbPath; Buckets m_buckets; + const std::string m_indexFileName = "buckets"; protected: - virtual Buckets &buckets() { + virtual Buckets &buckets(void) { return m_buckets; } }; } /* namespace Cynara */ -#endif /* INMEMORYSTORAGEBACKEND_H_ */ + +#endif /* SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ */ diff --git a/src/service/storage/Storage.cpp b/src/service/storage/Storage.cpp index 319dbda..cfbd82d 100644 --- a/src/service/storage/Storage.cpp +++ b/src/service/storage/Storage.cpp @@ -21,16 +21,19 @@ * @brief This file implements policy rules storage procedures */ -#include "Storage.h" -#include "StorageBackend.h" -#include "types/pointers.h" -#include "types/PolicyType.h" -#include "exceptions/NotImplementedException.h" -#include "exceptions/DefaultBucketDeletionException.h" - -#include #include +#include +#include "exceptions/DefaultBucketDeletionException.h" +#include +#include +#include +#include +#include +#include +#include + +#include "Storage.h" namespace Cynara { @@ -58,19 +61,17 @@ PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey const auto &policyResult = policyRecord->result(); switch (policyResult.policyType()) { - case PredefinedPolicyType::DENY: - return policyResult; // Do not expect lower value than DENY - break; - case PredefinedPolicyType::BUCKET: { - auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); - auto minimumOfBucket = minimalPolicy(bucketResults, key); - proposeMinimal(minimumOfBucket); - continue; - } - break; - case PredefinedPolicyType::ALLOW: - default: - break; + case PredefinedPolicyType::DENY: + return policyResult; // Do not expect lower value than DENY + case PredefinedPolicyType::BUCKET: { + auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); + auto minimumOfBucket = minimalPolicy(bucketResults, key); + proposeMinimal(minimumOfBucket); + continue; + } + case PredefinedPolicyType::ALLOW: + default: + break; } proposeMinimal(policyResult); @@ -125,4 +126,8 @@ void Storage::load(void) { m_backend.load(); } +void Storage::save(void) { + m_backend.save(); +} + } // namespace Cynara diff --git a/src/service/storage/Storage.h b/src/service/storage/Storage.h index b1c7cb3..23955ff 100644 --- a/src/service/storage/Storage.h +++ b/src/service/storage/Storage.h @@ -21,24 +21,22 @@ * @brief This file is the implementation file of log system */ -#ifndef CYNARA_SERVICE_STORAGE_STORAGE_H -#define CYNARA_SERVICE_STORAGE_STORAGE_H +#ifndef SRC_SERVICE_STORAGE_STORAGE_H_ +#define SRC_SERVICE_STORAGE_STORAGE_H_ #include -#include #include -#include #include -#include "types/pointers.h" -#include "types/PolicyBucketId.h" -#include "types/PolicyResult.h" -#include "types/PolicyKey.h" +#include +#include +#include +#include +#include -namespace Cynara { +#include -class StorageBackend; -class PolicyBucket; +namespace Cynara { class Storage { @@ -54,6 +52,7 @@ public: void deleteBucket(const PolicyBucketId &bucketId); void load(void); + void save(void); protected: PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key); @@ -64,4 +63,4 @@ private: } // namespace Cynara -#endif /* CYNARA_SERVICE_STORAGE_STORAGE_H */ +#endif /* SRC_SERVICE_STORAGE_STORAGE_H_ */ diff --git a/src/service/storage/StorageBackend.h b/src/service/storage/StorageBackend.h index 97e0fd7..cc711f9 100644 --- a/src/service/storage/StorageBackend.h +++ b/src/service/storage/StorageBackend.h @@ -20,20 +20,19 @@ * @brief Headers for StorageBackend base class */ -#ifndef STORAGEBACKEND_H_ -#define STORAGEBACKEND_H_ +#ifndef SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ +#define SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ +#include -#include "types/pointers.h" -#include "types/PolicyBucket.h" -#include "types/PolicyBucketId.h" - -#include +#include +#include +#include +#include +#include namespace Cynara { -class PolicyKey; - class StorageBackend { public: virtual ~StorageBackend() {} @@ -43,8 +42,10 @@ public: virtual void insertPolicy(const PolicyBucketId &bucket, PolicyPtr policy) = 0; - virtual void createBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultPolicy) = 0; - virtual void updateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultPolicy) = 0; + virtual void createBucket(const PolicyBucketId &bucketId, + const PolicyResult &defaultPolicy) = 0; + virtual void updateBucket(const PolicyBucketId &bucketId, + const PolicyResult &defaultPolicy) = 0; virtual void deleteBucket(const PolicyBucketId &bucketId) = 0; virtual bool hasBucket(const PolicyBucketId &bucketId) = 0; @@ -52,7 +53,9 @@ public: virtual void deleteLinking(const PolicyBucketId &bucket) = 0; virtual void load(void) = 0; + virtual void save(void) = 0; }; } /* namespace Cynara */ -#endif /* STORAGEBACKEND_H_ */ + +#endif /* SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ */ diff --git a/src/service/storage/StorageDeserializer.cpp b/src/service/storage/StorageDeserializer.cpp index 0510670..66c8ff0 100644 --- a/src/service/storage/StorageDeserializer.cpp +++ b/src/service/storage/StorageDeserializer.cpp @@ -20,15 +20,18 @@ * @brief Implementation for Cynara::StorageDeserializer */ -#include +#include #include #include #include +#include + #include +#include #include -#include +#include "StorageDeserializer.h" namespace Cynara { @@ -36,10 +39,10 @@ StorageDeserializer::StorageDeserializer(std::istream &inStream, BucketStreamOpener bucketStreamOpener) : m_inStream(inStream), m_bucketStreamOpener(bucketStreamOpener) {} -void StorageDeserializer::initBuckets(InMemoryStorageBackend::Buckets &buckets) { +void StorageDeserializer::initBuckets(Buckets &buckets) { buckets.clear(); - for(std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { std::string line; std::getline(m_inStream, line, StorageSerializer::recordSeparator()); @@ -55,7 +58,7 @@ void StorageDeserializer::initBuckets(InMemoryStorageBackend::Buckets &buckets) } } -void StorageDeserializer::loadBuckets(InMemoryStorageBackend::Buckets &buckets) { +void StorageDeserializer::loadBuckets(Buckets &buckets) { for (auto &bucketIter : buckets) { const auto &bucketId = bucketIter.first; auto &bucket = bucketIter.second; @@ -88,7 +91,7 @@ PolicyType StorageDeserializer::parsePolicyType(const std::string &line, std::si std::size_t newBegin = 0; policyType = std::stoi(line.substr(beginToken), &newBegin, 16); beginToken += newBegin; - } catch(...) { + } catch (...) { throw BucketRecordCorruptedException(line); } diff --git a/src/service/storage/StorageDeserializer.h b/src/service/storage/StorageDeserializer.h index 2fd0341..c3680c4 100644 --- a/src/service/storage/StorageDeserializer.h +++ b/src/service/storage/StorageDeserializer.h @@ -22,21 +22,27 @@ #ifndef SRC_SERVICE_STORAGE_STORAGEDESERIALIZER_H_ #define SRC_SERVICE_STORAGE_STORAGEDESERIALIZER_H_ -#include -#include - +#include #include #include -#include +#include + +#include +#include +#include + +#include +#include namespace Cynara { class StorageDeserializer { public: - typedef std::function(const std::string &)> BucketStreamOpener; + typedef std::function(const std::string &)> + BucketStreamOpener; StorageDeserializer(std::istream &inStream, BucketStreamOpener m_bucketStreamOpener); - void initBuckets(InMemoryStorageBackend::Buckets &buckets); - void loadBuckets(InMemoryStorageBackend::Buckets &buckets); + void initBuckets(Buckets &buckets); + void loadBuckets(Buckets &buckets); static PolicyBucketId parseBucketId(const std::string &line, std::size_t &beginToken); static PolicyType parsePolicyType(const std::string &line, std::size_t &beginToken); diff --git a/src/service/storage/StorageSerializer.cpp b/src/service/storage/StorageSerializer.cpp index be8b9d4..f46d48e 100644 --- a/src/service/storage/StorageSerializer.cpp +++ b/src/service/storage/StorageSerializer.cpp @@ -20,13 +20,15 @@ * @brief Implementation of Cynara::StorageSerializer methods */ -#include #include -#include +#include #include -#include "types/PolicyBucket.h" -#include "types/PolicyCollection.h" +#include +#include +#include +#include +#include #include "StorageSerializer.h" @@ -37,7 +39,7 @@ char StorageSerializer::m_recordSeparator = '\n'; StorageSerializer::StorageSerializer(std::ostream &os) : m_outStream(os) {} -void StorageSerializer::dump(const InMemoryStorageBackend::Buckets &buckets, +void StorageSerializer::dump(const Buckets &buckets, BucketStreamOpener streamOpener) { for (const auto bucketIter : buckets) { diff --git a/src/service/storage/StorageSerializer.h b/src/service/storage/StorageSerializer.h index 789f263..80966e9 100644 --- a/src/service/storage/StorageSerializer.h +++ b/src/service/storage/StorageSerializer.h @@ -23,17 +23,20 @@ #ifndef SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_ #define SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_ -#include "InMemoryStorageBackend.h" -#include "types/PolicyBucketId.h" -#include "types/PolicyCollection.h" -#include "types/PolicyResult.h" - +#include +#include #include -namespace Cynara { +#include +#include +#include +#include +#include +#include -class PolicyBucket; -class PolicyKey; +#include + +namespace Cynara { class StorageSerializer { @@ -44,7 +47,7 @@ public: StorageSerializer(std::ostream &os); virtual ~StorageSerializer() = default; - virtual void dump(const InMemoryStorageBackend::Buckets &buckets, + virtual void dump(const Buckets &buckets, BucketStreamOpener streamOpener); virtual void dump(const PolicyBucket &bucket); -- 2.7.4