* @brief Implementation of InMemoryStorageBackend
*/
+#include <errno.h>
+#include <fstream>
+#include <functional>
+#include <memory>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unordered_map>
+#include <vector>
+
+#include <log/log.h>
+#include <exceptions/BucketNotExistsException.h>
+#include <exceptions/CannotCreateFileException.h>
+#include <exceptions/FileNotFoundException.h>
+#include <exceptions/UnexpectedErrorException.h>
+#include <types/PolicyBucket.h>
+#include <types/PolicyResult.h>
+#include <types/PolicyType.h>
+
+#include <storage/BucketDeserializer.h>
+#include <storage/StorageDeserializer.h>
+#include <storage/StorageSerializer.h>
+
#include "InMemoryStorageBackend.h"
namespace Cynara {
-InMemoryStorageBackend::InMemoryStorageBackend() {
- // Make sure, there's always default bucket
- this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
+void InMemoryStorageBackend::load(void) {
+ std::string indexFilename = m_dbPath + m_indexFileName;
+
+ try {
+ std::shared_ptr<std::ifstream> indexStream = std::make_shared<std::ifstream>();
+ openFileStream(indexStream, indexFilename);
+
+ StorageDeserializer storageDeserializer(indexStream,
+ std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
+
+ storageDeserializer.initBuckets(buckets());
+ storageDeserializer.loadBuckets(buckets());
+ } catch (const FileNotFoundException &) {
+ LOGE("Reading cynara database failed.");
+ }
+
+ if (!hasBucket(defaultPolicyBucketId)) {
+ LOGN("Creating defaultBucket.");
+ this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
+ }
}
-InMemoryStorageBackend::~InMemoryStorageBackend() {}
+void InMemoryStorageBackend::save(void) {
+
+ //create directory
+ int ret = mkdir(m_dbPath.c_str(), S_IRWXU);
+ if (ret < 0) {
+ int err = errno;
+ if (err != EEXIST) {
+ LOGE("Cannot create directory <%s>. Error [%d] : <%s>.",
+ m_dbPath.c_str(), err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+ }
+
+ std::shared_ptr<std::ofstream> indexStream = std::make_shared<std::ofstream>();
+ openDumpFileStream(indexStream, m_dbPath + m_indexFileName);
+
+ StorageSerializer storageSerializer(indexStream);
+ storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener,
+ this, std::placeholders::_1));
+}
PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
return searchBucket(defaultPolicyBucketId, key);
PolicyBucket InMemoryStorageBackend::searchBucket(const PolicyBucketId &bucketId,
const PolicyKey &key) {
- const auto &bucket = this->buckets().at(bucketId);
- return bucket.filtered(key);
+ try {
+ const auto &bucket = this->buckets().at(bucketId);
+ return bucket.filtered(key);
+ } catch (const std::out_of_range &) {
+ throw BucketNotExistsException(bucketId);
+ }
}
void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
[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);
}
}
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();
}
}
+void InMemoryStorageBackend::openFileStream(std::shared_ptr<std::ifstream> stream,
+ const std::string &filename) {
+ // TODO: Consider adding exceptions to streams and handling them:
+ // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ stream->open(filename);
+
+ if (!stream->is_open())
+ throw FileNotFoundException(filename);
+}
+
+void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr<std::ofstream> stream,
+ const std::string &filename) {
+ stream->open(filename, std::ofstream::out | std::ofstream::trunc);
+
+ if (!stream->is_open()) {
+ throw CannotCreateFileException(filename);
+ }
+}
+
+std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
+ const PolicyBucketId &bucketId) {
+ std::string bucketFilename = m_dbPath + "_" + bucketId;
+ std::shared_ptr<std::ifstream> bucketStream = std::make_shared<std::ifstream>();
+ try {
+ openFileStream(bucketStream, bucketFilename);
+ return std::make_shared<BucketDeserializer>(bucketStream);
+ } catch (const FileNotFoundException &) {
+ return nullptr;
+ }
+}
+
+std::shared_ptr<StorageSerializer> InMemoryStorageBackend::bucketDumpStreamOpener(
+ const PolicyBucketId &bucketId) {
+ std::string bucketFilename = m_dbPath + "_" + bucketId;
+ std::shared_ptr<std::ofstream> bucketStream = std::make_shared<std::ofstream>();
+
+ openDumpFileStream(bucketStream, bucketFilename);
+ return std::make_shared<StorageSerializer>(bucketStream);
+}
+
} /* namespace Cynara */