2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file InMemoryStorageBackend.cpp
18 * @author Aleksander Zdyb <a.zdyb@partner.samsung.com>
20 * @brief Implementation of InMemoryStorageBackend
28 #include <sys/types.h>
29 #include <unordered_map>
33 #include <exceptions/BucketNotExistsException.h>
34 #include <exceptions/CannotCreateFileException.h>
35 #include <exceptions/FileNotFoundException.h>
36 #include <exceptions/UnexpectedErrorException.h>
37 #include <types/PolicyBucket.h>
38 #include <types/PolicyResult.h>
39 #include <types/PolicyType.h>
41 #include <storage/BucketDeserializer.h>
42 #include <storage/StorageDeserializer.h>
43 #include <storage/StorageSerializer.h>
45 #include "InMemoryStorageBackend.h"
49 void InMemoryStorageBackend::load(void) {
50 std::string indexFilename = m_dbPath + m_indexFileName;
53 std::ifstream indexStream;
54 openFileStream(indexStream, indexFilename);
56 StorageDeserializer storageDeserializer(indexStream,
57 std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
59 storageDeserializer.initBuckets(buckets());
60 storageDeserializer.loadBuckets(buckets());
61 } catch (const FileNotFoundException &) {
62 LOGE("Reading cynara database failed.");
65 if (!hasBucket(defaultPolicyBucketId)) {
66 LOGN("Creating defaultBucket.");
67 this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
71 void InMemoryStorageBackend::save(void) {
74 int ret = mkdir(m_dbPath.c_str(), S_IRWXU);
78 LOGE("Cannot create directory <%s>. Error [%d] : <%s>.",
79 m_dbPath.c_str(), err, strerror(err));
80 throw UnexpectedErrorException(err, strerror(err));
84 std::ofstream indexStream;
85 openDumpFileStream(indexStream, m_dbPath + m_indexFileName);
87 StorageSerializer storageSerializer(indexStream);
88 storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener,
89 this, std::placeholders::_1));
92 PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
93 return searchBucket(defaultPolicyBucketId, key);
96 PolicyBucket InMemoryStorageBackend::searchBucket(const PolicyBucketId &bucketId,
97 const PolicyKey &key) {
99 const auto &bucket = this->buckets().at(bucketId);
100 return bucket.filtered(key);
101 } catch (const std::out_of_range &) {
102 throw BucketNotExistsException(bucketId);
106 void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
108 auto &bucket = buckets().at(bucketId);
109 auto &policies = bucket.policyCollection();
110 policies.push_back(policy);
111 } catch (const std::out_of_range &) {
112 throw BucketNotExistsException(bucketId);
116 void InMemoryStorageBackend::createBucket(const PolicyBucketId &bucketId,
117 const PolicyResult &defaultPolicy) {
118 PolicyBucket newBucket;
119 newBucket.setDefaultPolicy(defaultPolicy);
120 buckets().insert({ bucketId, newBucket });
123 void InMemoryStorageBackend::updateBucket(const PolicyBucketId &bucketId,
124 const PolicyResult &defaultPolicy) {
126 auto &bucket = buckets().at(bucketId);
127 bucket.setDefaultPolicy(defaultPolicy);
128 } catch (const std::out_of_range &) {
129 throw BucketNotExistsException(bucketId);
133 void InMemoryStorageBackend::deleteBucket(const PolicyBucketId &bucketId) {
134 auto bucketErased = buckets().erase(bucketId);
135 if (bucketErased == 0) {
136 throw BucketNotExistsException(bucketId);
140 bool InMemoryStorageBackend::hasBucket(const PolicyBucketId &bucketId) {
141 return buckets().find(bucketId) != buckets().end();
144 void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key) {
146 // TODO: Move the erase code to PolicyCollection maybe?
147 auto &bucket = buckets().at(bucketId);
148 auto &policies = bucket.policyCollection();
149 policies.erase(remove_if(policies.begin(), policies.end(),
150 [key](PolicyPtr policy) -> bool {
151 return policy->key() == key;
153 } catch (const std::out_of_range &) {
154 throw BucketNotExistsException(bucketId);
158 void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
159 auto bucketIdMatches = [&bucketId] (PolicyPtr policy) -> bool {
160 auto policyResult = policy->result();
162 // Check bucket id only if policy is a bucket policy
163 // TODO: Maybe move the test to PolicyResult
164 if (policyResult.policyType() == PredefinedPolicyType::BUCKET) {
165 return policyResult.metadata() == bucketId;
170 for (auto &bucketIter : buckets()) {
171 // TODO: Move the erase code to PolicyCollection maybe?
172 auto &bucket = bucketIter.second;
173 auto &policies = bucket.policyCollection();
174 policies.erase(remove_if(policies.begin(), policies.end(), bucketIdMatches),
179 void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::string &filename) {
180 // TODO: Consider adding exceptions to streams and handling them:
181 // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
182 stream.open(filename);
184 if (!stream.is_open())
185 throw FileNotFoundException(filename);
188 void InMemoryStorageBackend::openDumpFileStream(std::ofstream &stream,
189 const std::string &filename) {
190 stream.open(filename, std::ofstream::out | std::ofstream::trunc);
192 if (!stream.is_open()) {
193 throw CannotCreateFileException(filename);
198 std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
199 const PolicyBucketId &bucketId) {
200 std::string bucketFilename = m_dbPath + "_" + bucketId;
201 std::ifstream bucketStream;
203 openFileStream(bucketStream, bucketFilename);
204 return std::make_shared<BucketDeserializer>(bucketStream);
205 } catch (const FileNotFoundException &) {
210 std::shared_ptr<StorageSerializer> InMemoryStorageBackend::bucketDumpStreamOpener(
211 const PolicyBucketId &bucketId) {
212 std::string bucketFilename = m_dbPath + "_" + bucketId;
213 std::ofstream bucketStream;
215 openDumpFileStream(bucketStream, bucketFilename);
216 return std::make_shared<StorageSerializer>(bucketStream);
219 } /* namespace Cynara */