From 0ded5caa100a6802eb2f3e45e7b2073f0cef95eb Mon Sep 17 00:00:00 2001
From: Pawel Wieczorek
Date: Wed, 27 Aug 2014 09:18:02 +0200
Subject: [PATCH 01/16] Implement mechanism assuring integrity of database
There is also added mechanism for cleaning up Cynara's database
directory upon loading policies to memory.
There is added test checking whether mechanism behaves as intended.
Change-Id: I926d1aebf394c092e00731b73717e0e1c55bad0c
---
packaging/cynara.spec | 3 +-
src/storage/CMakeLists.txt | 1 +
src/storage/InMemoryStorageBackend.cpp | 46 +++-
src/storage/InMemoryStorageBackend.h | 10 +-
src/storage/Integrity.cpp | 232 +++++++++++++++++++++
src/storage/Integrity.h | 71 +++++++
test/CMakeLists.txt | 1 +
test/db/db6/_ | 0
test/db/db6/_additional | 1 +
test/db/db6/_additional~ | 0
test/db/db6/_~ | 0
test/db/db6/buckets | 2 +
test/db/db6/buckets~ | 2 +
test/db/db6/guard | 0
.../fakeinmemorystoragebackend.h | 2 +-
.../inmemeorystoragebackendfixture.h | 2 +
.../inmemorystoragebackend.cpp | 38 +++-
17 files changed, 396 insertions(+), 15 deletions(-)
create mode 100644 src/storage/Integrity.cpp
create mode 100644 src/storage/Integrity.h
create mode 100644 test/db/db6/_
create mode 100644 test/db/db6/_additional
create mode 100644 test/db/db6/_additional~
create mode 100644 test/db/db6/_~
create mode 100644 test/db/db6/buckets
create mode 100644 test/db/db6/buckets~
create mode 100644 test/db/db6/guard
diff --git a/packaging/cynara.spec b/packaging/cynara.spec
index 213c94e..68d52ce 100644
--- a/packaging/cynara.spec
+++ b/packaging/cynara.spec
@@ -283,7 +283,7 @@ cp ./conf/creds.conf %{buildroot}/%{conf_path}/creds.conf
mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants
mkdir -p %{buildroot}/%{state_path}
-mkdir -p %{buildroot}/%{tests_dir}
+mkdir -p %{buildroot}/%{tests_dir}/empty_db
cp -a db* %{buildroot}/%{tests_dir}
ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket
ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket
@@ -494,6 +494,7 @@ fi
%manifest cynara-tests.manifest
%attr(755,root,root) /usr/bin/cynara-tests
%attr(755,root,root) %{tests_dir}/db*/*
+%dir %attr(755,root,root) %{tests_dir}/empty_db
%files -n libcynara-creds-commons
%manifest libcynara-creds-commons.manifest
diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt
index 620dc2d..7bccc8c 100644
--- a/src/storage/CMakeLists.txt
+++ b/src/storage/CMakeLists.txt
@@ -25,6 +25,7 @@ SET(CYNARA_LIB_CYNARA_STORAGE_PATH ${CYNARA_PATH}/storage)
SET(LIB_CYNARA_STORAGE_SOURCES
${CYNARA_LIB_CYNARA_STORAGE_PATH}/BucketDeserializer.cpp
${CYNARA_LIB_CYNARA_STORAGE_PATH}/InMemoryStorageBackend.cpp
+ ${CYNARA_LIB_CYNARA_STORAGE_PATH}/Integrity.cpp
${CYNARA_LIB_CYNARA_STORAGE_PATH}/Storage.cpp
${CYNARA_LIB_CYNARA_STORAGE_PATH}/StorageDeserializer.cpp
${CYNARA_LIB_CYNARA_STORAGE_PATH}/StorageSerializer.cpp
diff --git a/src/storage/InMemoryStorageBackend.cpp b/src/storage/InMemoryStorageBackend.cpp
index af18926..a2366e8 100644
--- a/src/storage/InMemoryStorageBackend.cpp
+++ b/src/storage/InMemoryStorageBackend.cpp
@@ -30,7 +30,6 @@
#include
#include
#include
-#include
#include
#include
@@ -43,6 +42,7 @@
#include
#include
+#include
#include
#include
@@ -50,17 +50,28 @@
namespace Cynara {
-const std::string InMemoryStorageBackend::m_indexFileName = "buckets";
+const std::string InMemoryStorageBackend::m_indexFilename = "buckets";
+const std::string InMemoryStorageBackend::m_backupFilenameSuffix = "~";
+const std::string InMemoryStorageBackend::m_bucketFilenamePrefix = "_";
void InMemoryStorageBackend::load(void) {
- std::string indexFilename = m_dbPath + m_indexFileName;
+ Integrity integrity(m_dbPath, m_indexFilename, m_backupFilenameSuffix, m_bucketFilenamePrefix);
+ bool isBackupValid = integrity.backupGuardExists();
+ std::string bucketSuffix = "";
+ std::string indexFilename = m_dbPath + m_indexFilename;
+
+ if (isBackupValid) {
+ bucketSuffix += m_backupFilenameSuffix;
+ indexFilename += m_backupFilenameSuffix;
+ }
try {
auto indexStream = std::make_shared();
openFileStream(indexStream, indexFilename);
StorageDeserializer storageDeserializer(indexStream,
- std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
+ std::bind(&InMemoryStorageBackend::bucketStreamOpener, this,
+ std::placeholders::_1, bucketSuffix));
storageDeserializer.initBuckets(buckets());
storageDeserializer.loadBuckets(buckets());
@@ -74,6 +85,13 @@ void InMemoryStorageBackend::load(void) {
LOGN("Creating defaultBucket.");
this->buckets().insert({ defaultPolicyBucketId, PolicyBucket(defaultPolicyBucketId) });
}
+
+ if (isBackupValid) {
+ integrity.revalidatePrimaryDatabase(buckets());
+ }
+ //in case there were unnecessary files in db directory
+ integrity.deleteNonIndexedFiles(std::bind(&InMemoryStorageBackend::hasBucket, this,
+ std::placeholders::_1));
}
void InMemoryStorageBackend::save(void) {
@@ -90,11 +108,19 @@ void InMemoryStorageBackend::save(void) {
}
auto indexStream = std::make_shared();
- openDumpFileStream(indexStream, m_dbPath + m_indexFileName);
+ std::string indexFilename = m_dbPath + m_indexFilename;
+ openDumpFileStream(indexStream, indexFilename + m_backupFilenameSuffix);
StorageSerializer storageSerializer(indexStream);
storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener,
this, std::placeholders::_1));
+
+ Integrity integrity(m_dbPath, m_indexFilename, m_backupFilenameSuffix, m_bucketFilenamePrefix);
+
+ integrity.syncDatabase(buckets(), true);
+ integrity.createBackupGuard();
+ integrity.revalidatePrimaryDatabase(buckets());
+ //guard is removed during revalidation
}
PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
@@ -181,8 +207,9 @@ void InMemoryStorageBackend::openFileStream(std::shared_ptr strea
// stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
stream->open(filename);
- if (!stream->is_open())
+ if (!stream->is_open()) {
throw FileNotFoundException(filename);
+ }
}
void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr stream,
@@ -195,8 +222,8 @@ void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr s
}
std::shared_ptr InMemoryStorageBackend::bucketStreamOpener(
- const PolicyBucketId &bucketId) {
- std::string bucketFilename = m_dbPath + "_" + bucketId;
+ const PolicyBucketId &bucketId, const std::string &filenameSuffix) {
+ std::string bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId + filenameSuffix;
auto bucketStream = std::make_shared();
try {
openFileStream(bucketStream, bucketFilename);
@@ -208,7 +235,8 @@ std::shared_ptr InMemoryStorageBackend::bucketStreamOpener(
std::shared_ptr InMemoryStorageBackend::bucketDumpStreamOpener(
const PolicyBucketId &bucketId) {
- std::string bucketFilename = m_dbPath + "_" + bucketId;
+ std::string bucketFilename = m_dbPath + m_bucketFilenamePrefix +
+ bucketId + m_backupFilenameSuffix;
auto bucketStream = std::make_shared();
openDumpFileStream(bucketStream, bucketFilename);
diff --git a/src/storage/InMemoryStorageBackend.h b/src/storage/InMemoryStorageBackend.h
index cc35f95..d03dd6c 100644
--- a/src/storage/InMemoryStorageBackend.h
+++ b/src/storage/InMemoryStorageBackend.h
@@ -62,15 +62,19 @@ public:
protected:
InMemoryStorageBackend() {}
void openFileStream(std::shared_ptr stream, const std::string &filename);
- std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId);
+ std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId,
+ const std::string &fileNameSuffix);
- void openDumpFileStream(std::shared_ptr stream, const std::string &filename);
+ virtual void openDumpFileStream(std::shared_ptr stream,
+ const std::string &filename);
std::shared_ptr bucketDumpStreamOpener(const PolicyBucketId &bucketId);
private:
std::string m_dbPath;
Buckets m_buckets;
- static const std::string m_indexFileName;
+ static const std::string m_indexFilename;
+ static const std::string m_backupFilenameSuffix;
+ static const std::string m_bucketFilenamePrefix;
protected:
virtual Buckets &buckets(void) {
diff --git a/src/storage/Integrity.cpp b/src/storage/Integrity.cpp
new file mode 100644
index 0000000..8057e9c
--- /dev/null
+++ b/src/storage/Integrity.cpp
@@ -0,0 +1,232 @@
+/*
+ * 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 src/storage/Integrity.cpp
+ * @author Pawel Wieczorek
+ * @version 0.1
+ * @brief Implementation of Cynara::Integrity
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "Integrity.h"
+
+namespace Cynara {
+
+const std::string Integrity::m_guardFilename = "guard";
+
+bool Integrity::backupGuardExists(void) const {
+ struct stat buffer;
+ std::string guardFilename = m_dbPath + m_guardFilename;
+
+ int ret = stat(guardFilename.c_str(), &buffer);
+
+ if (ret == 0) {
+ return true;
+ } else {
+ int err = errno;
+ if (err != ENOENT) {
+ LOGE("'stat' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+ return false;
+ }
+}
+
+void Integrity::createBackupGuard(void) const {
+ syncElement(m_dbPath + m_guardFilename, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC);
+ syncDirectory(m_dbPath);
+}
+
+void Integrity::syncDatabase(const Buckets &buckets, bool syncBackup) {
+ std::string suffix = "";
+
+ if (syncBackup) {
+ suffix += m_backupFilenameSuffix;
+ }
+
+ for (const auto &bucketIter : buckets) {
+ const auto &bucketId = bucketIter.first;
+ const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId + suffix;
+
+ syncElement(bucketFilename);
+ }
+
+ syncElement(m_dbPath + m_indexFilename + suffix);
+ syncDirectory(m_dbPath);
+}
+
+void Integrity::revalidatePrimaryDatabase(const Buckets &buckets) {
+ createPrimaryHardLinks(buckets);
+ syncDatabase(buckets, false);
+
+ deleteHardLink(m_dbPath + m_guardFilename);
+ syncDirectory(m_dbPath);
+
+ deleteBackupHardLinks(buckets);
+}
+
+void Integrity::deleteNonIndexedFiles(BucketPresenceTester tester) {
+ DIR *dirPtr = nullptr;
+ struct dirent *direntPtr;
+
+ if ((dirPtr = opendir(m_dbPath.c_str())) == nullptr) {
+ int err = errno;
+ LOGE("'opendir' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ return;
+ }
+
+ while (errno = 0, (direntPtr = readdir(dirPtr)) != nullptr) {
+ std::string filename = direntPtr->d_name;
+ //ignore all special files (working dir, parent dir, index)
+ if ("." == filename || ".." == filename || "buckets" == filename) {
+ continue;
+ }
+
+ std::string bucketId;
+ auto nameLength = filename.length();
+ auto prefixLength = m_bucketFilenamePrefix.length();
+
+ //remove if it is impossible that it is a bucket file
+ if (nameLength < prefixLength) {
+ deleteHardLink(m_dbPath + filename);
+ continue;
+ }
+
+ //remove if there is no bucket filename prefix
+ //0 is returned from string::compare() if strings are equal
+ if (0 != filename.compare(0, prefixLength, m_bucketFilenamePrefix)) {
+ deleteHardLink(m_dbPath + filename);
+ continue;
+ }
+
+ //remove if bucket is not in index
+ bucketId = filename.substr(prefixLength);
+ if (!tester(bucketId)) {
+ deleteHardLink(m_dbPath + filename);
+ }
+ }
+
+ if (errno) {
+ int err = errno;
+ LOGE("'readdir' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ return;
+ }
+}
+
+void Integrity::syncElement(const std::string &filename, int flags, mode_t mode) {
+ int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode));
+
+ if (fileFd < 0) {
+ int err = errno;
+ if (err != EEXIST) {
+ LOGE("'open' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ } else {
+ throw CannotCreateFileException(filename);
+ }
+ }
+
+ int ret = fsync(fileFd);
+
+ if (ret < 0) {
+ int err = errno;
+ LOGE("'fsync' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+
+ ret = close(fileFd);
+
+ if (ret < 0) {
+ int err = errno;
+ LOGE("'close' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+}
+
+// from: man 2 fsync
+// Calling fsync() does not necessarily ensure that the entry in the directory containing
+// the file has also reached disk. For that an explicit fsync() on a file descriptor for
+// the directory is also needed.
+void Integrity::syncDirectory(const std::string &dirname, mode_t mode) {
+ syncElement(dirname, O_DIRECTORY, mode);
+}
+
+void Integrity::createPrimaryHardLinks(const Buckets &buckets) {
+ for (const auto &bucketIter : buckets) {
+ const auto &bucketId = bucketIter.first;
+ const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId;
+
+ deleteHardLink(bucketFilename);
+ createHardLink(bucketFilename + m_backupFilenameSuffix, bucketFilename);
+ }
+
+ const auto &indexFilename = m_dbPath + m_indexFilename;
+
+ deleteHardLink(indexFilename);
+ createHardLink(indexFilename + m_backupFilenameSuffix, indexFilename);
+}
+
+void Integrity::deleteBackupHardLinks(const Buckets &buckets) {
+ for (const auto &bucketIter : buckets) {
+ const auto &bucketId = bucketIter.first;
+ const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix +
+ bucketId + m_backupFilenameSuffix;
+
+ deleteHardLink(bucketFilename);
+ }
+
+ deleteHardLink(m_dbPath + m_indexFilename + m_backupFilenameSuffix);
+}
+
+void Integrity::createHardLink(const std::string &oldName, const std::string &newName) {
+ int ret = link(oldName.c_str(), newName.c_str());
+
+ if (ret < 0) {
+ int err = errno;
+ throw UnexpectedErrorException(err, strerror(err));
+ LOGN("Trying to link to non-existent file: <%s>", oldName.c_str());
+ }
+}
+
+void Integrity::deleteHardLink(const std::string &filename) {
+ int ret = unlink(filename.c_str());
+
+ if (ret < 0) {
+ int err = errno;
+ if (err != ENOENT) {
+ LOGE("'unlink' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ } else {
+ LOGN("Trying to unlink non-existent file: <%s>", filename.c_str());
+ }
+ }
+}
+
+} /* namespace Cynara */
diff --git a/src/storage/Integrity.h b/src/storage/Integrity.h
new file mode 100644
index 0000000..4b677b0
--- /dev/null
+++ b/src/storage/Integrity.h
@@ -0,0 +1,71 @@
+/*
+ * 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 src/storage/Integrity.h
+ * @author Pawel Wieczorek
+ * @version 0.1
+ * @brief Headers for Cynara::Integrity
+ */
+
+#ifndef SRC_STORAGE_INTEGRITY_H_
+#define SRC_STORAGE_INTEGRITY_H_
+
+#include
+#include
+
+#include
+
+namespace Cynara {
+
+class Integrity
+{
+public:
+ typedef std::function BucketPresenceTester;
+ Integrity(const std::string &path, const std::string &index, const std::string &backupSuffix,
+ const std::string &bucketPrefix)
+ : m_dbPath(path), m_indexFilename(index), m_backupFilenameSuffix(backupSuffix),
+ m_bucketFilenamePrefix(bucketPrefix) {
+ }
+ virtual ~Integrity() {};
+
+ virtual bool backupGuardExists(void) const;
+ virtual void createBackupGuard(void) const;
+ virtual void syncDatabase(const Buckets &buckets, bool syncBackup);
+ virtual void revalidatePrimaryDatabase(const Buckets &buckets);
+ virtual void deleteNonIndexedFiles(BucketPresenceTester tester);
+
+protected:
+ static void syncElement(const std::string &filename, int flags = O_RDONLY,
+ mode_t mode = S_IRUSR | S_IWUSR);
+ static void syncDirectory(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR);
+
+ void createPrimaryHardLinks(const Buckets &buckets);
+ void deleteBackupHardLinks(const Buckets &buckets);
+
+ static void createHardLink(const std::string &oldName, const std::string &newName);
+ static void deleteHardLink(const std::string &filename);
+
+private:
+ const std::string m_dbPath;
+ const std::string m_indexFilename;
+ const std::string m_backupFilenameSuffix;
+ const std::string m_bucketFilenamePrefix;
+ static const std::string m_guardFilename;
+};
+
+} // namespace Cynara
+
+#endif /* SRC_STORAGE_INTEGRITY_H_ */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ffddd87..063098f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -32,6 +32,7 @@ SET(CYNARA_SOURCES_FOR_TESTS
${CYNARA_SRC}/helpers/creds-commons/creds-commons.cpp
${CYNARA_SRC}/storage/BucketDeserializer.cpp
${CYNARA_SRC}/storage/InMemoryStorageBackend.cpp
+ ${CYNARA_SRC}/storage/Integrity.cpp
${CYNARA_SRC}/storage/Storage.cpp
${CYNARA_SRC}/storage/StorageDeserializer.cpp
${CYNARA_SRC}/storage/StorageSerializer.cpp
diff --git a/test/db/db6/_ b/test/db/db6/_
new file mode 100644
index 0000000..e69de29
diff --git a/test/db/db6/_additional b/test/db/db6/_additional
new file mode 100644
index 0000000..cbeab67
--- /dev/null
+++ b/test/db/db6/_additional
@@ -0,0 +1 @@
+client1;user1;privilege1;0x0;
diff --git a/test/db/db6/_additional~ b/test/db/db6/_additional~
new file mode 100644
index 0000000..e69de29
diff --git a/test/db/db6/_~ b/test/db/db6/_~
new file mode 100644
index 0000000..e69de29
diff --git a/test/db/db6/buckets b/test/db/db6/buckets
new file mode 100644
index 0000000..19d7a93
--- /dev/null
+++ b/test/db/db6/buckets
@@ -0,0 +1,2 @@
+;0x0
+additional;0xFFFF
diff --git a/test/db/db6/buckets~ b/test/db/db6/buckets~
new file mode 100644
index 0000000..19d7a93
--- /dev/null
+++ b/test/db/db6/buckets~
@@ -0,0 +1,2 @@
+;0x0
+additional;0xFFFF
diff --git a/test/db/db6/guard b/test/db/db6/guard
new file mode 100644
index 0000000..e69de29
diff --git a/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h b/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h
index 1c80dea..52b4fe3 100644
--- a/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h
+++ b/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h
@@ -29,7 +29,7 @@
class FakeInMemoryStorageBackend : public Cynara::InMemoryStorageBackend {
public:
using Cynara::InMemoryStorageBackend::InMemoryStorageBackend;
- MOCK_METHOD0(buckets, Cynara::Buckets&());
+ MOCK_METHOD0(buckets, Cynara::Buckets&(void));
};
diff --git a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h
index 3f08dea..2ec2920 100644
--- a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h
+++ b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h
@@ -67,6 +67,8 @@ protected:
// TODO: consider defaulting accessor with ON_CALL
Cynara::Buckets m_buckets;
+ static const std::string m_indexFileName;
+ static const std::string m_backupFileNameSuffix;
};
diff --git a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp
index 11c0968..c0fd640 100644
--- a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp
+++ b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp
@@ -40,6 +40,9 @@
using namespace Cynara;
+const std::string InMemeoryStorageBackendFixture::m_indexFileName = "buckets";
+const std::string InMemeoryStorageBackendFixture::m_backupFileNameSuffix = "~";
+
TEST_F(InMemeoryStorageBackendFixture, defaultPolicyIsDeny) {
using ::testing::ReturnRef;
@@ -192,7 +195,7 @@ TEST_F(InMemeoryStorageBackendFixture, deletePolicyFromNonexistentBucket) {
// Database dir is empty
TEST_F(InMemeoryStorageBackendFixture, load_no_db) {
using ::testing::ReturnRef;
- auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db1/";
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/empty_db/";
FakeInMemoryStorageBackend backend(testDbPath);
EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
backend.load();
@@ -252,3 +255,36 @@ TEST_F(InMemeoryStorageBackendFixture, second_bucket_corrupted) {
backend.load();
ASSERT_DB_VIRGIN(m_buckets);
}
+
+/**
+ * @brief Database was corrupted, restore from backup (which is present)
+ * @test Scenario:
+ * - There still is guard file in earlier prepared Cynara's policy database directory (db6)
+ * - Execution of load() should use backup files (present, with different contents than primaries)
+ * - Loaded database is checked - backup files were empty, so should recently loaded policies
+ */
+TEST_F(InMemeoryStorageBackendFixture, load_from_backup) {
+ using ::testing::ReturnRef;
+ using ::testing::IsEmpty;
+ using ::testing::InSequence;
+
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db6/";
+ FakeInMemoryStorageBackend backend(testDbPath);
+
+ {
+ // Calls are expected in a specific order
+ InSequence s;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+ }
+
+ std::vector bucketIds = { "", "additional" };
+ for(const auto &bucketId : bucketIds) {
+ SCOPED_TRACE(bucketId);
+ const auto bucketIter = m_buckets.find(bucketId);
+ ASSERT_NE(m_buckets.end(), bucketIter);
+
+ const auto &bucketPolicies = bucketIter->second;
+ ASSERT_THAT(bucketPolicies, IsEmpty());
+ }
+}
--
2.7.4
From d1b33eecd1065cf626efc5380dcfc2da6a7c1359 Mon Sep 17 00:00:00 2001
From: Pawel Wieczorek
Date: Thu, 13 Nov 2014 12:07:20 +0100
Subject: [PATCH 02/16] Ensure creation of minimal database
This patch changes default behaviour of migration tool during package
upgrade. Previously, Cynara's state path was left untouched. Now
creation of minimal database is ensured. No changes are made if it
already existed.
Change-Id: I25158aec7d7b436ac1446d43277afe1337bfe4e5
---
migration/cynara-db-migration.sh | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/migration/cynara-db-migration.sh b/migration/cynara-db-migration.sh
index 0cf5edd..8cbebbf 100644
--- a/migration/cynara-db-migration.sh
+++ b/migration/cynara-db-migration.sh
@@ -94,9 +94,10 @@ migrate_db() {
failure
fi
- :
- # : is a null command, as functions may not be empty.
- # Actual body will be added if database structure changes.
+ # Create minimal database if there was none:
+ if [ ! -d "${STATE_PATH}/${DB_DIR}" ]; then
+ create_db
+ fi
}
remove_db() {
--
2.7.4
From 8dd72120e13a4192408b8940b85ef40d980a3fdd Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Thu, 13 Nov 2014 14:25:56 +0100
Subject: [PATCH 03/16] Fix segfault in dump_buckets test
Change-Id: If614900c9710dc0600c48622051afb484709155f
---
test/storage/serializer/serialize.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/storage/serializer/serialize.cpp b/test/storage/serializer/serialize.cpp
index cceed78..938283d 100644
--- a/test/storage/serializer/serialize.cpp
+++ b/test/storage/serializer/serialize.cpp
@@ -48,8 +48,8 @@ public:
// Fake StorageSerializer for Cynara::PolicyBucket
class FakeStorageSerializer : public Cynara::StorageSerializer {
public:
- FakeStorageSerializer() : Cynara::StorageSerializer(outStream),
- outStream(new std::ostringstream()) {}
+ FakeStorageSerializer(std::shared_ptr o) : Cynara::StorageSerializer(o),
+ outStream(o) {}
MOCK_METHOD1(dump, void(const Cynara::PolicyBucket &bucket));
std::shared_ptr outStream;
};
@@ -82,7 +82,8 @@ TEST_F(StorageSerializerFixture, dump_buckets) {
using ::testing::UnorderedElementsAreArray;
// Will be returned as serializer for buckets
- auto fakeBucketSerializer = std::make_shared();
+ auto fakeBucketSerializer = std::make_shared(
+ std::make_shared());
buckets = {
{ "bucket1", PolicyBucket("bucket1", PredefinedPolicyType::DENY) },
--
2.7.4
From 656f1a804ecf28619a0f7ea91ce26b43d27ec075 Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Wed, 12 Nov 2014 16:30:35 +0100
Subject: [PATCH 04/16] Remove unnecessary Protocol shared pointers
ProtocolFramePtr and ProtocolFrameHeaderPtr was used unnecessary
(no shared ownership required).
Change-Id: I71d4bf797450a46bc35e2321ff8d01a6508bcf88
---
src/common/protocol/ProtocolAdmin.cpp | 76 ++++++++++++-------------
src/common/protocol/ProtocolClient.cpp | 26 ++++-----
src/common/protocol/ProtocolFrame.cpp | 4 +-
src/common/protocol/ProtocolFrame.h | 8 +--
src/common/protocol/ProtocolFrameHeader.h | 2 -
src/common/protocol/ProtocolFrameSerializer.cpp | 16 +++---
src/common/protocol/ProtocolFrameSerializer.h | 4 +-
7 files changed, 66 insertions(+), 70 deletions(-)
diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp
index 7d7d0f9..ca17e34 100644
--- a/src/common/protocol/ProtocolAdmin.cpp
+++ b/src/common/protocol/ProtocolAdmin.cpp
@@ -228,14 +228,14 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckRequestPtr requ
request->key().user().value().c_str(), request->key().privilege().value().c_str(),
request->startBucket().c_str(), request->recursive());
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpAdminCheckRequest);
- ProtocolSerialization::serialize(*frame, request->key().client().value());
- ProtocolSerialization::serialize(*frame, request->key().user().value());
- ProtocolSerialization::serialize(*frame, request->key().privilege().value());
- ProtocolSerialization::serialize(*frame, request->startBucket());
- ProtocolSerialization::serialize(*frame, request->recursive());
+ ProtocolSerialization::serialize(frame, OpAdminCheckRequest);
+ ProtocolSerialization::serialize(frame, request->key().client().value());
+ ProtocolSerialization::serialize(frame, request->key().user().value());
+ ProtocolSerialization::serialize(frame, request->key().privilege().value());
+ ProtocolSerialization::serialize(frame, request->startBucket());
+ ProtocolSerialization::serialize(frame, request->recursive());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
@@ -246,12 +246,12 @@ void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketReque
request->bucketId().c_str(), request->result().policyType(),
request->result().metadata().c_str());
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpInsertOrUpdateBucket);
- ProtocolSerialization::serialize(*frame, request->bucketId());
- ProtocolSerialization::serialize(*frame, request->result().policyType());
- ProtocolSerialization::serialize(*frame, request->result().metadata());
+ ProtocolSerialization::serialize(frame, OpInsertOrUpdateBucket);
+ ProtocolSerialization::serialize(frame, request->bucketId());
+ ProtocolSerialization::serialize(frame, request->result().policyType());
+ ProtocolSerialization::serialize(frame, request->result().metadata());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
@@ -260,10 +260,10 @@ void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr re
LOGD("Serializing RemoveBucketRequest: sequenceNumber [%" PRIu16 "], bucketId <%s>",
request->sequenceNumber(), request->bucketId().c_str());
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpRemoveBucket);
- ProtocolSerialization::serialize(*frame, request->bucketId());
+ ProtocolSerialization::serialize(frame, OpRemoveBucket);
+ ProtocolSerialization::serialize(frame, request->bucketId());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
@@ -273,39 +273,39 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req
"insertOrUpdate count [%zu], remove count [%zu]", request->sequenceNumber(),
request->policiesToBeInsertedOrUpdated().size(), request->policiesToBeRemoved().size());
- ProtocolFramePtr frame =
+ ProtocolFrame frame =
ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpSetPolicies);
+ ProtocolSerialization::serialize(frame, OpSetPolicies);
- ProtocolSerialization::serialize(*frame,
+ ProtocolSerialization::serialize(frame,
static_cast(request->policiesToBeInsertedOrUpdated().size()));
for (auto policyBucket : request->policiesToBeInsertedOrUpdated()) {
- ProtocolSerialization::serialize(*frame, policyBucket.first);
- ProtocolSerialization::serialize(*frame,
+ ProtocolSerialization::serialize(frame, policyBucket.first);
+ ProtocolSerialization::serialize(frame,
static_cast(policyBucket.second.size()));
for (auto policy : policyBucket.second) {
// PolicyKey
- ProtocolSerialization::serialize(*frame, policy.key().client().value());
- ProtocolSerialization::serialize(*frame, policy.key().user().value());
- ProtocolSerialization::serialize(*frame, policy.key().privilege().value());
+ ProtocolSerialization::serialize(frame, policy.key().client().value());
+ ProtocolSerialization::serialize(frame, policy.key().user().value());
+ ProtocolSerialization::serialize(frame, policy.key().privilege().value());
// PolicyResult
- ProtocolSerialization::serialize(*frame, policy.result().policyType());
- ProtocolSerialization::serialize(*frame, policy.result().metadata());
+ ProtocolSerialization::serialize(frame, policy.result().policyType());
+ ProtocolSerialization::serialize(frame, policy.result().metadata());
}
}
- ProtocolSerialization::serialize(*frame,
+ ProtocolSerialization::serialize(frame,
static_cast(request->policiesToBeRemoved().size()));
for (auto policyBucket : request->policiesToBeRemoved()) {
- ProtocolSerialization::serialize(*frame, policyBucket.first);
- ProtocolSerialization::serialize(*frame,
+ ProtocolSerialization::serialize(frame, policyBucket.first);
+ ProtocolSerialization::serialize(frame,
static_cast(policyBucket.second.size()));
for (auto policyKey : policyBucket.second) {
// PolicyKey
- ProtocolSerialization::serialize(*frame, policyKey.client().value());
- ProtocolSerialization::serialize(*frame, policyKey.user().value());
- ProtocolSerialization::serialize(*frame, policyKey.privilege().value());
+ ProtocolSerialization::serialize(frame, policyKey.client().value());
+ ProtocolSerialization::serialize(frame, policyKey.user().value());
+ ProtocolSerialization::serialize(frame, policyKey.privilege().value());
}
}
@@ -318,12 +318,12 @@ void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response
response->sequenceNumber(), response->m_resultRef.policyType(),
response->m_resultRef.metadata().c_str());
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(
response->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpCheckPolicyResponse);
- ProtocolSerialization::serialize(*frame, response->m_resultRef.policyType());
- ProtocolSerialization::serialize(*frame, response->m_resultRef.metadata());
+ ProtocolSerialization::serialize(frame, OpCheckPolicyResponse);
+ ProtocolSerialization::serialize(frame, response->m_resultRef.policyType());
+ ProtocolSerialization::serialize(frame, response->m_resultRef.metadata());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
@@ -332,11 +332,11 @@ void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response)
LOGD("Serializing CodeResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], "
"code [%" PRIu16 "]", OpCodeResponse, response->sequenceNumber(), response->m_code);
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(
response->sequenceNumber());
- ProtocolSerialization::serialize(*frame, OpCodeResponse);
- ProtocolSerialization::serialize(*frame, static_cast(response->m_code));
+ ProtocolSerialization::serialize(frame, OpCodeResponse);
+ ProtocolSerialization::serialize(frame, static_cast(response->m_code));
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp
index 94811dd..c643789 100644
--- a/src/common/protocol/ProtocolClient.cpp
+++ b/src/common/protocol/ProtocolClient.cpp
@@ -141,52 +141,52 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue)
}
void ProtocolClient::execute(RequestContextPtr context, CancelRequestPtr request) {
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
LOGD("Serializing CancelRequest op [%" PRIu8 "]", OpCancelRequest);
- ProtocolSerialization::serialize(*frame, OpCancelRequest);
+ ProtocolSerialization::serialize(frame, OpCancelRequest);
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) {
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber());
LOGD("Serializing CheckRequest: client <%s>, user <%s>, privilege <%s>",
request->key().client().value().c_str(), request->key().user().value().c_str(),
request->key().privilege().value().c_str());
- ProtocolSerialization::serialize(*frame, OpCheckPolicyRequest);
- ProtocolSerialization::serialize(*frame, request->key().client().value());
- ProtocolSerialization::serialize(*frame, request->key().user().value());
- ProtocolSerialization::serialize(*frame, request->key().privilege().value());
+ ProtocolSerialization::serialize(frame, OpCheckPolicyRequest);
+ ProtocolSerialization::serialize(frame, request->key().client().value());
+ ProtocolSerialization::serialize(frame, request->key().user().value());
+ ProtocolSerialization::serialize(frame, request->key().privilege().value());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr response) {
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(
response->sequenceNumber());
LOGD("Serializing CancelResponse: op [%" PRIu8 "]", OpCancelResponse);
- ProtocolSerialization::serialize(*frame, OpCancelResponse);
+ ProtocolSerialization::serialize(frame, OpCancelResponse);
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) {
- ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(
+ ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(
response->sequenceNumber());
LOGD("Serializing CheckResponse: op [%" PRIu8 "], policyType [%" PRIu16 "], metadata <%s>",
OpCheckPolicyResponse, response->m_resultRef.policyType(),
response->m_resultRef.metadata().c_str());
- ProtocolSerialization::serialize(*frame, OpCheckPolicyResponse);
- ProtocolSerialization::serialize(*frame, response->m_resultRef.policyType());
- ProtocolSerialization::serialize(*frame, response->m_resultRef.metadata());
+ ProtocolSerialization::serialize(frame, OpCheckPolicyResponse);
+ ProtocolSerialization::serialize(frame, response->m_resultRef.policyType());
+ ProtocolSerialization::serialize(frame, response->m_resultRef.metadata());
ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
}
diff --git a/src/common/protocol/ProtocolFrame.cpp b/src/common/protocol/ProtocolFrame.cpp
index 560217e..736be30 100644
--- a/src/common/protocol/ProtocolFrame.cpp
+++ b/src/common/protocol/ProtocolFrame.cpp
@@ -28,7 +28,7 @@
namespace Cynara {
-ProtocolFrame::ProtocolFrame(ProtocolFrameHeaderPtr frameHeader, BinaryQueuePtr data) :
+ProtocolFrame::ProtocolFrame(ProtocolFrameHeader frameHeader, BinaryQueuePtr data) :
m_frameHeader(frameHeader), m_frameBodyContent(data) {
}
@@ -38,7 +38,7 @@ void ProtocolFrame::read(size_t num, void *bytes) {
void ProtocolFrame::write(size_t num, const void *bytes) {
m_frameBodyContent->appendCopy(bytes, num);
- m_frameHeader->increaseFrameLength(num);
+ m_frameHeader.increaseFrameLength(num);
}
} /* namespace Cynara */
diff --git a/src/common/protocol/ProtocolFrame.h b/src/common/protocol/ProtocolFrame.h
index 3d85cc0..73f22e9 100644
--- a/src/common/protocol/ProtocolFrame.h
+++ b/src/common/protocol/ProtocolFrame.h
@@ -39,10 +39,10 @@ class ProtocolFrameSerializer;
class ProtocolFrame: public IStream {
public:
- ProtocolFrame(ProtocolFrameHeaderPtr frameHeader, BinaryQueuePtr headerContent);
+ ProtocolFrame(ProtocolFrameHeader frameHeader, BinaryQueuePtr headerContent);
virtual ~ProtocolFrame() {};
- ProtocolFrameHeaderPtr frameHeader(void) {
+ ProtocolFrameHeader &frameHeader(void) {
return m_frameHeader;
}
@@ -50,7 +50,7 @@ public:
virtual void write(size_t num, const void *bytes);
private:
- ProtocolFrameHeaderPtr m_frameHeader;
+ ProtocolFrameHeader m_frameHeader;
BinaryQueuePtr m_frameBodyContent;
BinaryQueue &bodyContent(void) {
@@ -60,8 +60,6 @@ private:
friend class ProtocolFrameSerializer;
};
-typedef std::shared_ptr ProtocolFramePtr;
-
} /* namespace Cynara */
#endif /* SRC_COMMON_PROTOCOL_PROTOCOLFRAME_H_ */
diff --git a/src/common/protocol/ProtocolFrameHeader.h b/src/common/protocol/ProtocolFrameHeader.h
index ff92bf9..7b85465 100644
--- a/src/common/protocol/ProtocolFrameHeader.h
+++ b/src/common/protocol/ProtocolFrameHeader.h
@@ -107,8 +107,6 @@ private:
friend class ProtocolFrameSerializer;
};
-typedef std::shared_ptr ProtocolFrameHeaderPtr;
-
} /* namespace Cynara */
#endif /* SRC_COMMON_PROTOCOL_PROTOCOLFRAMEHEADER_H_ */
diff --git a/src/common/protocol/ProtocolFrameSerializer.cpp b/src/common/protocol/ProtocolFrameSerializer.cpp
index 88a07d3..0599f02 100644
--- a/src/common/protocol/ProtocolFrameSerializer.cpp
+++ b/src/common/protocol/ProtocolFrameSerializer.cpp
@@ -65,19 +65,19 @@ void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader
}
}
-ProtocolFramePtr ProtocolFrameSerializer::startSerialization(ProtocolFrameSequenceNumber sequenceNumber) {
+ProtocolFrame ProtocolFrameSerializer::startSerialization(ProtocolFrameSequenceNumber sequenceNumber) {
LOGD("Serialization started");
BinaryQueuePtr headerQueue = std::make_shared();
BinaryQueuePtr bodyQueue = std::make_shared();
- ProtocolFrameHeaderPtr header = std::make_shared(headerQueue);
- header->setSequenceNumber(sequenceNumber);
- header->increaseFrameLength(ProtocolFrameHeader::frameHeaderLength());
- return std::make_shared(header, bodyQueue);
+ ProtocolFrameHeader header(headerQueue);
+ header.setSequenceNumber(sequenceNumber);
+ header.increaseFrameLength(ProtocolFrameHeader::frameHeaderLength());
+ return ProtocolFrame(header, bodyQueue);
}
-void ProtocolFrameSerializer::finishSerialization(ProtocolFramePtr frame, BinaryQueue &data) {
- ProtocolFrameHeader &frameHeader = *frame->frameHeader();
+void ProtocolFrameSerializer::finishSerialization(ProtocolFrame &frame, BinaryQueue &data) {
+ ProtocolFrameHeader &frameHeader = frame.frameHeader();
ProtocolSerialization::serializeNoSize(frameHeader, ProtocolFrameHeader::m_signature);
ProtocolSerialization::serialize(frameHeader, frameHeader.m_frameLength);
ProtocolSerialization::serialize(frameHeader, frameHeader.m_sequenceNumber);
@@ -87,7 +87,7 @@ void ProtocolFrameSerializer::finishSerialization(ProtocolFramePtr frame, Binary
(int)frameHeader.m_sequenceNumber);
data.appendMoveFrom(frameHeader.headerContent());
- data.appendMoveFrom(frame->bodyContent());
+ data.appendMoveFrom(frame.bodyContent());
}
} /* namespace Cynara */
diff --git a/src/common/protocol/ProtocolFrameSerializer.h b/src/common/protocol/ProtocolFrameSerializer.h
index 8961e14..f2e201e 100644
--- a/src/common/protocol/ProtocolFrameSerializer.h
+++ b/src/common/protocol/ProtocolFrameSerializer.h
@@ -34,8 +34,8 @@ class ProtocolFrameSerializer {
public:
static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueue &data);
- static ProtocolFramePtr startSerialization(ProtocolFrameSequenceNumber sequenceNumber);
- static void finishSerialization(ProtocolFramePtr frame, BinaryQueue &data);
+ static ProtocolFrame startSerialization(ProtocolFrameSequenceNumber sequenceNumber);
+ static void finishSerialization(ProtocolFrame &frame, BinaryQueue &data);
};
} /* namespace Cynara */
--
2.7.4
From 481d3058557b53ed807fce6ba6412da683e0f392 Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Wed, 12 Nov 2014 17:07:55 +0100
Subject: [PATCH 05/16] Reorganize ProtocolAdmin and ProtocolClient
Private methods of ProtocolAdmin and ProtocolClient lost an argument,
which was used only to pass member value from the same class.
Change-Id: I5657d38cf9ccd47892082479eeae92d62f894227
---
src/common/protocol/ProtocolAdmin.cpp | 90 +++++++++++++++++-----------------
src/common/protocol/ProtocolAdmin.h | 12 ++---
src/common/protocol/ProtocolClient.cpp | 34 ++++++-------
src/common/protocol/ProtocolClient.h | 8 +--
4 files changed, 73 insertions(+), 71 deletions(-)
diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp
index ca17e34..2d4c879 100644
--- a/src/common/protocol/ProtocolAdmin.cpp
+++ b/src/common/protocol/ProtocolAdmin.cpp
@@ -50,53 +50,54 @@ ProtocolPtr ProtocolAdmin::clone(void) {
return std::make_shared();
}
-RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(void) {
std::string clientId, userId, privilegeId;
PolicyBucketId startBucket;
bool recursive;
- ProtocolDeserialization::deserialize(frame, clientId);
- ProtocolDeserialization::deserialize(frame, userId);
- ProtocolDeserialization::deserialize(frame, privilegeId);
- ProtocolDeserialization::deserialize(frame, startBucket);
- ProtocolDeserialization::deserialize(frame, recursive);
+ ProtocolDeserialization::deserialize(m_frameHeader, clientId);
+ ProtocolDeserialization::deserialize(m_frameHeader, userId);
+ ProtocolDeserialization::deserialize(m_frameHeader, privilegeId);
+ ProtocolDeserialization::deserialize(m_frameHeader, startBucket);
+ ProtocolDeserialization::deserialize(m_frameHeader, recursive);
LOGD("Deserialized AdminCheckRequest: clientId <%s>, userId <%s>, privilegeId <%s>, "
"startBucket <%s>, recursive [%d]", clientId.c_str(), userId.c_str(),
privilegeId.c_str(), startBucket.c_str(), recursive);
return std::make_shared(PolicyKey(clientId, userId, privilegeId),
- startBucket, recursive, frame.sequenceNumber());
+ startBucket, recursive,
+ m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(void) {
PolicyBucketId policyBucketId;
PolicyType policyType;
PolicyResult::PolicyMetadata policyMetaData;
- ProtocolDeserialization::deserialize(frame, policyBucketId);
- ProtocolDeserialization::deserialize(frame, policyType);
- ProtocolDeserialization::deserialize(frame, policyMetaData);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyType);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyMetaData);
LOGD("Deserialized InsertOrUpdateBucketRequest: bucketId <%s>, "
"result.type [%" PRIu16 "], result.meta <%s>", policyBucketId.c_str(),
policyType, policyMetaData.c_str());
return std::make_shared(policyBucketId,
- PolicyResult(policyType, policyMetaData), frame.sequenceNumber());
+ PolicyResult(policyType, policyMetaData), m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(void) {
PolicyBucketId policyBucketId;
- ProtocolDeserialization::deserialize(frame, policyBucketId);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId);
LOGD("Deserialized RemoveBucketRequest: bucketId <%s>", policyBucketId.c_str());
- return std::make_shared(policyBucketId, frame.sequenceNumber());
+ return std::make_shared(policyBucketId, m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(void) {
ProtocolFrameFieldsCount toBeInsertedOrUpdatedCount, toBeRemovedCount;
ProtocolFrameFieldsCount policyCount;
PolicyKeyFeature::ValueType clientId, user, privilege;
@@ -105,19 +106,19 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra
std::map> toBeInsertedOrUpdatedPolicies;
std::map> toBeRemovedPolicies;
- ProtocolDeserialization::deserialize(frame, toBeInsertedOrUpdatedCount);
+ ProtocolDeserialization::deserialize(m_frameHeader, toBeInsertedOrUpdatedCount);
for (ProtocolFrameFieldsCount b = 0; b < toBeInsertedOrUpdatedCount; ++b) {
PolicyBucketId policyBucketId;
- ProtocolDeserialization::deserialize(frame, policyBucketId);
- ProtocolDeserialization::deserialize(frame, policyCount);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyCount);
for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) {
// PolicyKey
- ProtocolDeserialization::deserialize(frame, clientId);
- ProtocolDeserialization::deserialize(frame, user);
- ProtocolDeserialization::deserialize(frame, privilege);
+ ProtocolDeserialization::deserialize(m_frameHeader, clientId);
+ ProtocolDeserialization::deserialize(m_frameHeader, user);
+ ProtocolDeserialization::deserialize(m_frameHeader, privilege);
// PolicyResult
- ProtocolDeserialization::deserialize(frame, policyType);
- ProtocolDeserialization::deserialize(frame, metadata);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyType);
+ ProtocolDeserialization::deserialize(m_frameHeader, metadata);
toBeInsertedOrUpdatedPolicies[policyBucketId].push_back(
Policy(PolicyKey(clientId, user, privilege),
@@ -125,16 +126,16 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra
}
}
- ProtocolDeserialization::deserialize(frame, toBeRemovedCount);
+ ProtocolDeserialization::deserialize(m_frameHeader, toBeRemovedCount);
for (ProtocolFrameFieldsCount b = 0; b < toBeRemovedCount; ++b) {
PolicyBucketId policyBucketId;
- ProtocolDeserialization::deserialize(frame, policyBucketId);
- ProtocolDeserialization::deserialize(frame, policyCount);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId);
+ ProtocolDeserialization::deserialize(m_frameHeader, policyCount);
for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) {
// PolicyKey
- ProtocolDeserialization::deserialize(frame, clientId);
- ProtocolDeserialization::deserialize(frame, user);
- ProtocolDeserialization::deserialize(frame, privilege);
+ ProtocolDeserialization::deserialize(m_frameHeader, clientId);
+ ProtocolDeserialization::deserialize(m_frameHeader, user);
+ ProtocolDeserialization::deserialize(m_frameHeader, privilege);
toBeRemovedPolicies[policyBucketId].push_back(PolicyKey(clientId, user, privilege));
}
@@ -144,7 +145,8 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra
"remove count [%" PRIu16 "]", toBeInsertedOrUpdatedCount, toBeRemovedCount);
return std::make_shared(toBeInsertedOrUpdatedPolicies,
- toBeRemovedPolicies, frame.sequenceNumber());
+ toBeRemovedPolicies,
+ m_frameHeader.sequenceNumber());
}
RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
@@ -158,13 +160,13 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
LOGD("Deserialized opCode [%" PRIu8 "]", opCode);
switch (opCode) {
case OpAdminCheckRequest:
- return deserializeAdminCheckRequest(m_frameHeader);
+ return deserializeAdminCheckRequest();
case OpInsertOrUpdateBucket:
- return deserializeInsertOrUpdateBucketRequest(m_frameHeader);
+ return deserializeInsertOrUpdateBucketRequest();
case OpRemoveBucket:
- return deserializeRemoveBucketRequest(m_frameHeader);
+ return deserializeRemoveBucketRequest();
case OpSetPolicies:
- return deserializeSetPoliciesRequest(m_frameHeader);
+ return deserializeSetPoliciesRequest();
default:
throw InvalidProtocolException(InvalidProtocolException::WrongOpCode);
break;
@@ -174,29 +176,29 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
return nullptr;
}
-ResponsePtr ProtocolAdmin::deserializeCheckResponse(ProtocolFrameHeader &frame) {
+ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) {
PolicyType result;
PolicyResult::PolicyMetadata additionalInfo;
- ProtocolDeserialization::deserialize(frame, result);
- ProtocolDeserialization::deserialize(frame, additionalInfo);
+ ProtocolDeserialization::deserialize(m_frameHeader, result);
+ ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo);
const PolicyResult policyResult(result, additionalInfo);
LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>",
policyResult.policyType(), policyResult.metadata().c_str());
- return std::make_shared(policyResult, frame.sequenceNumber());
+ return std::make_shared(policyResult, m_frameHeader.sequenceNumber());
}
-ResponsePtr ProtocolAdmin::deserializeCodeResponse(ProtocolFrameHeader &frame) {
+ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) {
ProtocolResponseCode responseCode;
- ProtocolDeserialization::deserialize(frame, responseCode);
+ ProtocolDeserialization::deserialize(m_frameHeader, responseCode);
LOGD("Deserialized CodeResponse: code [%" PRIu16 "], ", responseCode);
return std::make_shared(static_cast(responseCode),
- frame.sequenceNumber());
+ m_frameHeader.sequenceNumber());
}
ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
@@ -210,9 +212,9 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
LOGD("Deserialized opCode [%" PRIu8 "]", opCode);
switch (opCode) {
case OpCheckPolicyResponse:
- return deserializeCheckResponse(m_frameHeader);
+ return deserializeCheckResponse();
case OpCodeResponse:
- return deserializeCodeResponse(m_frameHeader);
+ return deserializeCodeResponse();
default:
throw InvalidProtocolException(InvalidProtocolException::WrongOpCode);
break;
diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h
index 2d1e702..3f7fcc9 100644
--- a/src/common/protocol/ProtocolAdmin.h
+++ b/src/common/protocol/ProtocolAdmin.h
@@ -47,13 +47,13 @@ public:
virtual void execute(RequestContextPtr context, CodeResponsePtr response);
private:
- RequestPtr deserializeAdminCheckRequest(ProtocolFrameHeader &frame);
- RequestPtr deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame);
- RequestPtr deserializeRemoveBucketRequest(ProtocolFrameHeader &frame);
- RequestPtr deserializeSetPoliciesRequest(ProtocolFrameHeader &frame);
+ RequestPtr deserializeAdminCheckRequest(void);
+ RequestPtr deserializeInsertOrUpdateBucketRequest(void);
+ RequestPtr deserializeRemoveBucketRequest(void);
+ RequestPtr deserializeSetPoliciesRequest(void);
- ResponsePtr deserializeCheckResponse(ProtocolFrameHeader &frame);
- ResponsePtr deserializeCodeResponse(ProtocolFrameHeader &frame);
+ ResponsePtr deserializeCheckResponse(void);
+ ResponsePtr deserializeCodeResponse(void);
};
} // namespace Cynara
diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp
index c643789..c130809 100644
--- a/src/common/protocol/ProtocolClient.cpp
+++ b/src/common/protocol/ProtocolClient.cpp
@@ -54,23 +54,23 @@ ProtocolPtr ProtocolClient::clone(void) {
return std::make_shared();
}
-RequestPtr ProtocolClient::deserializeCancelRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolClient::deserializeCancelRequest(void) {
LOGD("Deserialized CancelRequest");
- return std::make_shared(frame.sequenceNumber());
+ return std::make_shared(m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolClient::deserializeCheckRequest(ProtocolFrameHeader &frame) {
+RequestPtr ProtocolClient::deserializeCheckRequest(void) {
std::string clientId, userId, privilegeId;
- ProtocolDeserialization::deserialize(frame, clientId);
- ProtocolDeserialization::deserialize(frame, userId);
- ProtocolDeserialization::deserialize(frame, privilegeId);
+ ProtocolDeserialization::deserialize(m_frameHeader, clientId);
+ ProtocolDeserialization::deserialize(m_frameHeader, userId);
+ ProtocolDeserialization::deserialize(m_frameHeader, privilegeId);
LOGD("Deserialized CheckRequest: client <%s>, user <%s>, privilege <%s>",
clientId.c_str(), userId.c_str(), privilegeId.c_str());
return std::make_shared(PolicyKey(clientId, userId, privilegeId),
- frame.sequenceNumber());
+ m_frameHeader.sequenceNumber());
}
RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
@@ -85,9 +85,9 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
LOGD("Deserialized opCode [%" PRIu8 "]", opCode);
switch (opCode) {
case OpCheckPolicyRequest:
- return deserializeCheckRequest(m_frameHeader);
+ return deserializeCheckRequest();
case OpCancelRequest:
- return deserializeCancelRequest(m_frameHeader);
+ return deserializeCancelRequest();
default:
throw InvalidProtocolException(InvalidProtocolException::WrongOpCode);
break;
@@ -97,24 +97,24 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
return nullptr;
}
-ResponsePtr ProtocolClient::deserializeCancelResponse(ProtocolFrameHeader &frame) {
+ResponsePtr ProtocolClient::deserializeCancelResponse(void) {
LOGD("Deserialized CancelResponse");
- return std::make_shared(frame.sequenceNumber());
+ return std::make_shared(m_frameHeader.sequenceNumber());
}
-ResponsePtr ProtocolClient::deserializeCheckResponse(ProtocolFrameHeader &frame) {
+ResponsePtr ProtocolClient::deserializeCheckResponse(void) {
PolicyType result;
PolicyResult::PolicyMetadata additionalInfo;
- ProtocolDeserialization::deserialize(frame, result);
- ProtocolDeserialization::deserialize(frame, additionalInfo);
+ ProtocolDeserialization::deserialize(m_frameHeader, result);
+ ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo);
const PolicyResult policyResult(result, additionalInfo);
LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>",
policyResult.policyType(), policyResult.metadata().c_str());
- return std::make_shared(policyResult, frame.sequenceNumber());
+ return std::make_shared(policyResult, m_frameHeader.sequenceNumber());
}
ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
@@ -128,9 +128,9 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue)
LOGD("Deserialized opCode [%" PRIu8 "]", opCode);
switch (opCode) {
case OpCheckPolicyResponse:
- return deserializeCheckResponse(m_frameHeader);
+ return deserializeCheckResponse();
case OpCancelResponse:
- return deserializeCancelResponse(m_frameHeader);
+ return deserializeCancelResponse();
default:
throw InvalidProtocolException(InvalidProtocolException::WrongOpCode);
break;
diff --git a/src/common/protocol/ProtocolClient.h b/src/common/protocol/ProtocolClient.h
index 1bb1b6a..dc72e7a 100644
--- a/src/common/protocol/ProtocolClient.h
+++ b/src/common/protocol/ProtocolClient.h
@@ -48,11 +48,11 @@ public:
virtual void execute(RequestContextPtr context, CheckResponsePtr response);
private:
- RequestPtr deserializeCancelRequest(ProtocolFrameHeader &frame);
- RequestPtr deserializeCheckRequest(ProtocolFrameHeader &frame);
+ RequestPtr deserializeCancelRequest(void);
+ RequestPtr deserializeCheckRequest(void);
- ResponsePtr deserializeCancelResponse(ProtocolFrameHeader &frame);
- ResponsePtr deserializeCheckResponse(ProtocolFrameHeader &frame);
+ ResponsePtr deserializeCancelResponse(void);
+ ResponsePtr deserializeCheckResponse(void);
};
} // namespace Cynara
--
2.7.4
From cb00a4e9ea320a3f74cb28b06e30bb7b5e43d613 Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Wed, 12 Nov 2014 16:36:52 +0100
Subject: [PATCH 06/16] Remove dangerous reference
RequestContext contained reference to an external BinaryQueue. One
problem was, BBQ was held inside vector (so practically any operation
on vector made this object out-of-date), second problem was,
RequestContext was passed to other classes inside shared_ptr, so owner
of this bbq looses control other its reference.
Moreover, soon RequestContext will be held pending (e.g. when waiting
for external Agent to return answer) inside cynara logic, so BBQ stored
inside RequestContext needs to be alive as long as corresponding
connection is opened. Not more, not less.
Change-Id: I79c9eb9b5e74927bd7bb159da01fae23612ca83e
---
src/client-async/sockets/SocketClientAsync.cpp | 8 +--
src/client-async/sockets/SocketClientAsync.h | 4 +-
src/common/containers/BinaryQueue.h | 67 ++++++++++++-------------
src/common/exceptions/ContextErrorException.h | 42 ++++++++++++++++
src/common/protocol/Protocol.h | 4 +-
src/common/protocol/ProtocolAdmin.cpp | 16 +++---
src/common/protocol/ProtocolAdmin.h | 4 +-
src/common/protocol/ProtocolClient.cpp | 12 ++---
src/common/protocol/ProtocolClient.h | 4 +-
src/common/protocol/ProtocolFrameSerializer.cpp | 8 +--
src/common/protocol/ProtocolFrameSerializer.h | 2 +-
src/common/protocol/ProtocolSignal.cpp | 8 +--
src/common/protocol/ProtocolSignal.h | 4 +-
src/common/request/RequestContext.h | 12 +++--
src/common/sockets/SocketClient.cpp | 6 ++-
src/common/sockets/SocketClient.h | 4 +-
src/service/sockets/Descriptor.cpp | 24 ++++++---
src/service/sockets/Descriptor.h | 26 +++++-----
18 files changed, 158 insertions(+), 97 deletions(-)
create mode 100644 src/common/exceptions/ContextErrorException.h
diff --git a/src/client-async/sockets/SocketClientAsync.cpp b/src/client-async/sockets/SocketClientAsync.cpp
index e3ffbd4..148b13a 100644
--- a/src/client-async/sockets/SocketClientAsync.cpp
+++ b/src/client-async/sockets/SocketClientAsync.cpp
@@ -30,6 +30,8 @@ namespace Cynara {
SocketClientAsync::SocketClientAsync(const std::string &socketPath, ProtocolPtr protocol)
: m_socket(socketPath, 0), m_protocol(protocol) {
+ m_readQueue = std::make_shared();
+ m_writeQueue = std::make_shared();
}
Socket::ConnectionStatus SocketClientAsync::connect(void) {
@@ -54,15 +56,15 @@ void SocketClientAsync::appendRequest(RequestPtr request) {
}
bool SocketClientAsync::isDataToSend(void) {
- return m_socket.isDataToSend() || !m_writeQueue.empty();
+ return m_socket.isDataToSend() || !m_writeQueue->empty();
}
Socket::SendStatus SocketClientAsync::sendToCynara(void) {
- return m_socket.sendToServer(m_writeQueue);
+ return m_socket.sendToServer(*m_writeQueue);
}
bool SocketClientAsync::receiveFromCynara(void) {
- return m_socket.receiveFromServer(m_readQueue);
+ return m_socket.receiveFromServer(*m_readQueue);
}
ResponsePtr SocketClientAsync::getResponse(void) {
diff --git a/src/client-async/sockets/SocketClientAsync.h b/src/client-async/sockets/SocketClientAsync.h
index 5fb0543..eaacf84 100644
--- a/src/client-async/sockets/SocketClientAsync.h
+++ b/src/client-async/sockets/SocketClientAsync.h
@@ -56,8 +56,8 @@ public:
private:
Socket m_socket;
ProtocolPtr m_protocol;
- BinaryQueue m_readQueue;
- BinaryQueue m_writeQueue;
+ BinaryQueuePtr m_readQueue;
+ BinaryQueuePtr m_writeQueue;
};
} // namespace Cynara
diff --git a/src/common/containers/BinaryQueue.h b/src/common/containers/BinaryQueue.h
index f69f786..12b2e8a 100644
--- a/src/common/containers/BinaryQueue.h
+++ b/src/common/containers/BinaryQueue.h
@@ -33,52 +33,20 @@ namespace Cynara {
*/
class BinaryQueue;
typedef std::shared_ptr BinaryQueuePtr;
+typedef std::weak_ptr BinaryQueueWeakPtr;
/**
* Binary stream implemented as constant size bucket list
*
* @todo Add optimized implementation for FlattenConsume
*/
-class BinaryQueue
-{
- public:
+class BinaryQueue {
+public:
typedef void (*BufferDeleter)(const void *buffer, size_t bufferSize,
void *userParam);
static void bufferDeleterFree(const void *buffer,
size_t bufferSize,
void *userParam);
-
- private:
- struct Bucket
- {
- const void *buffer;
- const void *ptr;
- size_t size;
- size_t left;
-
- BufferDeleter deleter;
- void *param;
-
- Bucket(const void *buffer,
- size_t bufferSize,
- BufferDeleter deleter,
- void *userParam);
- ~Bucket();
- // make it noncopyable
- Bucket(const Bucket &) = delete;
- const Bucket &operator=(const Bucket &) = delete;
- // make it nonmoveable
- Bucket(Bucket &&) = delete;
- Bucket &operator=(Bucket &&) = delete;
- };
-
- typedef std::list BucketList;
- BucketList m_buckets;
- size_t m_size;
-
- static void deleteBucket(Bucket *bucket);
-
- public:
/**
* Construct empty binary queue
*/
@@ -239,6 +207,35 @@ class BinaryQueue
* is larger than available bytes in binary queue
*/
void flattenConsume(void *buffer, size_t bufferSize);
+
+private:
+ struct Bucket {
+ const void *buffer;
+ const void *ptr;
+ size_t size;
+ size_t left;
+
+ BufferDeleter deleter;
+ void *param;
+
+ Bucket(const void *buffer,
+ size_t bufferSize,
+ BufferDeleter deleter,
+ void *userParam);
+ ~Bucket();
+ // make it noncopyable
+ Bucket(const Bucket &) = delete;
+ const Bucket &operator=(const Bucket &) = delete;
+ // make it nonmoveable
+ Bucket(Bucket &&) = delete;
+ Bucket &operator=(Bucket &&) = delete;
+ };
+
+ typedef std::list BucketList;
+ BucketList m_buckets;
+ size_t m_size;
+
+ static void deleteBucket(Bucket *bucket);
};
} // namespace Cynara
diff --git a/src/common/exceptions/ContextErrorException.h b/src/common/exceptions/ContextErrorException.h
new file mode 100644
index 0000000..771065a
--- /dev/null
+++ b/src/common/exceptions/ContextErrorException.h
@@ -0,0 +1,42 @@
+/*
+ * 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 src/common/exceptions/ContextErrorException.h
+ * @author Zofia Abramowska
+ * @version 1.0
+ * @brief Implementation of ContextErrorException.h
+ */
+
+#ifndef SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_
+#define SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_
+
+#include "Exception.h"
+
+namespace Cynara {
+
+class ContextErrorException : public Exception {
+public:
+ ContextErrorException() = default;
+ virtual ~ContextErrorException() {};
+
+ virtual const std::string message(void) const {
+ return "ContextErrorException";
+ }
+};
+
+} /* namespace Cynara */
+
+#endif /* SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_ */
diff --git a/src/common/protocol/Protocol.h b/src/common/protocol/Protocol.h
index b98f145..63ee24d 100644
--- a/src/common/protocol/Protocol.h
+++ b/src/common/protocol/Protocol.h
@@ -44,8 +44,8 @@ public:
virtual ProtocolPtr clone(void) = 0;
- virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue) = 0;
- virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue) = 0;
+ virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue) = 0;
+ virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue) = 0;
ProtocolFrameHeader &frameHeader(void) {
return m_frameHeader;
diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp
index 2d4c879..8d792f9 100644
--- a/src/common/protocol/ProtocolAdmin.cpp
+++ b/src/common/protocol/ProtocolAdmin.cpp
@@ -149,7 +149,7 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(void) {
m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
+RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) {
ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue);
if (m_frameHeader.isFrameComplete()) {
@@ -201,7 +201,7 @@ ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) {
m_frameHeader.sequenceNumber());
}
-ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
+ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) {
ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue);
if (m_frameHeader.isFrameComplete()) {
@@ -239,7 +239,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckRequestPtr requ
ProtocolSerialization::serialize(frame, request->startBucket());
ProtocolSerialization::serialize(frame, request->recursive());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) {
@@ -255,7 +255,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketReque
ProtocolSerialization::serialize(frame, request->result().policyType());
ProtocolSerialization::serialize(frame, request->result().metadata());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr request) {
@@ -267,7 +267,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr re
ProtocolSerialization::serialize(frame, OpRemoveBucket);
ProtocolSerialization::serialize(frame, request->bucketId());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr request) {
@@ -311,7 +311,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req
}
}
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) {
@@ -327,7 +327,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response
ProtocolSerialization::serialize(frame, response->m_resultRef.policyType());
ProtocolSerialization::serialize(frame, response->m_resultRef.metadata());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) {
@@ -340,7 +340,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response)
ProtocolSerialization::serialize(frame, OpCodeResponse);
ProtocolSerialization::serialize(frame, static_cast(response->m_code));
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
} // namespace Cynara
diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h
index 3f7fcc9..9d2c6ac 100644
--- a/src/common/protocol/ProtocolAdmin.h
+++ b/src/common/protocol/ProtocolAdmin.h
@@ -35,8 +35,8 @@ public:
virtual ProtocolPtr clone(void);
- virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue);
- virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue);
+ virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue);
+ virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue);
virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request);
virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request);
diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp
index c130809..3f13653 100644
--- a/src/common/protocol/ProtocolClient.cpp
+++ b/src/common/protocol/ProtocolClient.cpp
@@ -73,7 +73,7 @@ RequestPtr ProtocolClient::deserializeCheckRequest(void) {
m_frameHeader.sequenceNumber());
}
-RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
+RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) {
ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue);
if (m_frameHeader.isFrameComplete()) {
@@ -117,7 +117,7 @@ ResponsePtr ProtocolClient::deserializeCheckResponse(void) {
return std::make_shared(policyResult, m_frameHeader.sequenceNumber());
}
-ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
+ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) {
ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue);
if (m_frameHeader.isFrameComplete()) {
@@ -147,7 +147,7 @@ void ProtocolClient::execute(RequestContextPtr context, CancelRequestPtr request
ProtocolSerialization::serialize(frame, OpCancelRequest);
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) {
@@ -162,7 +162,7 @@ void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request)
ProtocolSerialization::serialize(frame, request->key().user().value());
ProtocolSerialization::serialize(frame, request->key().privilege().value());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr response) {
@@ -173,7 +173,7 @@ void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr respon
ProtocolSerialization::serialize(frame, OpCancelResponse);
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) {
@@ -188,7 +188,7 @@ void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr respons
ProtocolSerialization::serialize(frame, response->m_resultRef.policyType());
ProtocolSerialization::serialize(frame, response->m_resultRef.metadata());
- ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue());
+ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue()));
}
} // namespace Cynara
diff --git a/src/common/protocol/ProtocolClient.h b/src/common/protocol/ProtocolClient.h
index dc72e7a..a1c5110 100644
--- a/src/common/protocol/ProtocolClient.h
+++ b/src/common/protocol/ProtocolClient.h
@@ -38,8 +38,8 @@ public:
virtual ProtocolPtr clone(void);
- virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue);
- virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue);
+ virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue);
+ virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue);
virtual void execute(RequestContextPtr context, CancelRequestPtr request);
virtual void execute(RequestContextPtr context, CheckRequestPtr request);
diff --git a/src/common/protocol/ProtocolFrameSerializer.cpp b/src/common/protocol/ProtocolFrameSerializer.cpp
index 0599f02..68c497c 100644
--- a/src/common/protocol/ProtocolFrameSerializer.cpp
+++ b/src/common/protocol/ProtocolFrameSerializer.cpp
@@ -31,15 +31,15 @@
namespace Cynara {
void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader,
- BinaryQueue &data) {
+ BinaryQueuePtr data) {
if (!frameHeader.isHeaderComplete()) {
- if ((data.size() < ProtocolFrameHeader::frameHeaderLength())) {
+ if ((data->size() < ProtocolFrameHeader::frameHeaderLength())) {
return;
}
LOGD("Deserializing frameHeader");
- frameHeader.setHeaderContent(BinaryQueuePtr(&data, [=] (BinaryQueue *) {}));
+ frameHeader.setHeaderContent(data);
ProtocolFrameSignature signature;
ProtocolDeserialization::deserialize(frameHeader, frameHeader.m_signature.length(),
@@ -60,7 +60,7 @@ void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader
frameHeader.setHeaderComplete();
}
- if (data.size() >= (frameHeader.frameLength() - ProtocolFrameHeader::frameHeaderLength())) {
+ if (data->size() >= (frameHeader.frameLength() - ProtocolFrameHeader::frameHeaderLength())) {
frameHeader.setBodyComplete();
}
}
diff --git a/src/common/protocol/ProtocolFrameSerializer.h b/src/common/protocol/ProtocolFrameSerializer.h
index f2e201e..d7d6c15 100644
--- a/src/common/protocol/ProtocolFrameSerializer.h
+++ b/src/common/protocol/ProtocolFrameSerializer.h
@@ -33,7 +33,7 @@ namespace Cynara {
class ProtocolFrameSerializer {
public:
- static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueue &data);
+ static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueuePtr data);
static ProtocolFrame startSerialization(ProtocolFrameSequenceNumber sequenceNumber);
static void finishSerialization(ProtocolFrame &frame, BinaryQueue &data);
};
diff --git a/src/common/protocol/ProtocolSignal.cpp b/src/common/protocol/ProtocolSignal.cpp
index 963ee9a..d04dbbe 100644
--- a/src/common/protocol/ProtocolSignal.cpp
+++ b/src/common/protocol/ProtocolSignal.cpp
@@ -46,17 +46,17 @@ ProtocolPtr ProtocolSignal::clone(void) {
return std::make_shared();
}
-RequestPtr ProtocolSignal::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
- if (bufferQueue.size() >= sizeof(struct signalfd_siginfo)) {
+RequestPtr ProtocolSignal::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) {
+ if (bufferQueue->size() >= sizeof(struct signalfd_siginfo)) {
struct signalfd_siginfo sigInfo;
- bufferQueue.flattenConsume(&sigInfo, sizeof(sigInfo));
+ bufferQueue->flattenConsume(&sigInfo, sizeof(sigInfo));
return std::make_shared(sigInfo);
}
return nullptr;
}
-ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueue &bufferQueue UNUSED) {
+ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueuePtr bufferQueue UNUSED) {
throw NotImplementedException();
}
diff --git a/src/common/protocol/ProtocolSignal.h b/src/common/protocol/ProtocolSignal.h
index e2142da..6c544c4 100644
--- a/src/common/protocol/ProtocolSignal.h
+++ b/src/common/protocol/ProtocolSignal.h
@@ -36,8 +36,8 @@ public:
virtual ProtocolPtr clone(void);
- virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue);
- virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue);
+ virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue);
+ virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue);
virtual void execute(RequestContextPtr context, SignalRequestPtr request);
};
diff --git a/src/common/request/RequestContext.h b/src/common/request/RequestContext.h
index 33b6ef4..9c98bef 100644
--- a/src/common/request/RequestContext.h
+++ b/src/common/request/RequestContext.h
@@ -26,6 +26,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,10 +37,10 @@ namespace Cynara {
class RequestContext {
private:
ResponseTakerWeakPtr m_responseTaker;
- BinaryQueue &m_responseQueue;
+ BinaryQueueWeakPtr m_responseQueue;
public:
- RequestContext(ResponseTakerPtr responseTaker, BinaryQueue &responseQueue)
+ RequestContext(ResponseTakerPtr responseTaker, BinaryQueuePtr responseQueue)
: m_responseTaker(responseTaker), m_responseQueue(responseQueue) {
}
@@ -49,8 +50,11 @@ public:
response->execute(response, taker, self);
}
- BinaryQueue &responseQueue(void) const {
- return m_responseQueue;
+ BinaryQueuePtr responseQueue(void) const {
+ auto bbqPtr = m_responseQueue.lock();
+ if (bbqPtr)
+ return bbqPtr;
+ throw ContextErrorException();
}
};
diff --git a/src/common/sockets/SocketClient.cpp b/src/common/sockets/SocketClient.cpp
index 6db91d6..b3ce8ad 100644
--- a/src/common/sockets/SocketClient.cpp
+++ b/src/common/sockets/SocketClient.cpp
@@ -37,6 +37,8 @@ namespace Cynara {
SocketClient::SocketClient(const std::string &socketPath, ProtocolPtr protocol)
: m_socket(socketPath), m_protocol(protocol) {
+ m_writeQueue = std::make_shared();
+ m_readQueue = std::make_shared();
}
bool SocketClient::connect(void) {
@@ -64,14 +66,14 @@ ResponsePtr SocketClient::askCynaraServer(RequestPtr request) {
request->execute(request, m_protocol, context);
//send request to cynara
- if (m_socket.sendToServer(m_writeQueue) == Socket::SendStatus::CONNECTION_LOST) {
+ if (m_socket.sendToServer(*m_writeQueue) == Socket::SendStatus::CONNECTION_LOST) {
LOGW("Disconnected while sending request to Cynara.");
return nullptr;
}
// receive response from cynara
while (true) {
- if (!m_socket.receiveFromServer(m_readQueue)) {
+ if (!m_socket.receiveFromServer(*m_readQueue)) {
LOGW("Disconnected while receiving response from Cynara.");
return nullptr;
}
diff --git a/src/common/sockets/SocketClient.h b/src/common/sockets/SocketClient.h
index 9f9737f..c313b13 100644
--- a/src/common/sockets/SocketClient.h
+++ b/src/common/sockets/SocketClient.h
@@ -41,8 +41,8 @@ class SocketClient {
private:
Socket m_socket;
ProtocolPtr m_protocol;
- BinaryQueue m_readQueue;
- BinaryQueue m_writeQueue;
+ BinaryQueuePtr m_readQueue;
+ BinaryQueuePtr m_writeQueue;
public:
SocketClient(const std::string &socketPath, ProtocolPtr protocol);
diff --git a/src/service/sockets/Descriptor.cpp b/src/service/sockets/Descriptor.cpp
index 0e55e4b..b2e9459 100644
--- a/src/service/sockets/Descriptor.cpp
+++ b/src/service/sockets/Descriptor.cpp
@@ -27,8 +27,17 @@ namespace Cynara {
Descriptor::Descriptor() : m_listen(false), m_used(false), m_client(false), m_protocol(nullptr) {
}
+void Descriptor::checkQueues(void) {
+ if (!m_writeQueue)
+ m_writeQueue = std::make_shared();
+ if (!m_readQueue)
+ m_readQueue = std::make_shared();
+}
+
bool Descriptor::hasDataToWrite(void) const {
- return !(m_writeQueue.empty() && m_writeBuffer.empty());
+ if (m_writeQueue)
+ return !(m_writeQueue->empty() && m_writeBuffer.empty());
+ return false;
}
ResponseTakerPtr Descriptor::responseTaker(void) const {
@@ -36,19 +45,22 @@ ResponseTakerPtr Descriptor::responseTaker(void) const {
}
void Descriptor::pushReadBuffer(const RawBuffer &readbuffer) {
- m_readQueue.appendCopy(readbuffer.data(), readbuffer.size());
+ checkQueues();
+ m_readQueue->appendCopy(readbuffer.data(), readbuffer.size());
}
RequestPtr Descriptor::extractRequest(void) {
+ checkQueues();
return m_protocol->extractRequestFromBuffer(m_readQueue);
}
RawBuffer &Descriptor::prepareWriteBuffer(void) {
- size_t queuedDataSize = m_writeQueue.size();
+ checkQueues();
+ size_t queuedDataSize = m_writeQueue->size();
size_t bufferDataSize = m_writeBuffer.size();
m_writeBuffer.resize(queuedDataSize + bufferDataSize);
- m_writeQueue.flattenConsume(m_writeBuffer.data() + bufferDataSize, queuedDataSize);
+ m_writeQueue->flattenConsume(m_writeBuffer.data() + bufferDataSize, queuedDataSize);
return m_writeBuffer;
}
@@ -57,8 +69,8 @@ void Descriptor::clear(void) {
m_listen = false;
m_used = false;
m_client = false;
- m_readQueue.clear();
- m_writeQueue.clear();
+ m_readQueue.reset();
+ m_writeQueue.reset();
m_writeBuffer.clear();
m_protocol.reset();
}
diff --git a/src/service/sockets/Descriptor.h b/src/service/sockets/Descriptor.h
index 0f42a36..5d77028 100644
--- a/src/service/sockets/Descriptor.h
+++ b/src/service/sockets/Descriptor.h
@@ -34,17 +34,6 @@
namespace Cynara {
class Descriptor {
-private:
- bool m_listen;
- bool m_used;
- bool m_client;
-
- BinaryQueue m_readQueue;
- BinaryQueue m_writeQueue;
- RawBuffer m_writeBuffer;
-
- ProtocolPtr m_protocol;
-
public:
Descriptor();
@@ -68,7 +57,7 @@ public:
ResponseTakerPtr responseTaker(void) const;
- BinaryQueue &writeQueue(void) {
+ BinaryQueuePtr writeQueue(void) {
return m_writeQueue;
}
@@ -94,6 +83,19 @@ public:
RawBuffer &prepareWriteBuffer(void);
void clear(void);
+
+private:
+ bool m_listen;
+ bool m_used;
+ bool m_client;
+
+ BinaryQueuePtr m_readQueue;
+ BinaryQueuePtr m_writeQueue;
+ RawBuffer m_writeBuffer;
+
+ ProtocolPtr m_protocol;
+
+ void checkQueues(void);
};
} // namespace Cynara
--
2.7.4
From 86891d2550fcec655be8a7d4d53037a626c42b2d Mon Sep 17 00:00:00 2001
From: Pawel Wieczorek
Date: Fri, 14 Nov 2014 13:04:19 +0100
Subject: [PATCH 07/16] Disallow adding valid and invalid policies at once
Storage::insertPolicies() now cares, if all buckets exist before it
makes any change in database (in memory as well as in storage).
No changes are made if any part of request contains invalid parameters.
Change-Id: Ia8d180c7af88bd945dca22f2a4a41b049fdb4c33
---
src/storage/Storage.cpp | 6 ++++++
test/storage/storage/policies.cpp | 32 ++++++++++++++++++++++++++------
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/src/storage/Storage.cpp b/src/storage/Storage.cpp
index 39793e2..aa9bc93 100644
--- a/src/storage/Storage.cpp
+++ b/src/storage/Storage.cpp
@@ -101,7 +101,13 @@ void Storage::insertPolicies(const std::map>
// TODO: Rewrite, when transactions are supported
// Check if all of buckets exist
for (const auto &group : policiesByBucketId) {
+ const auto &bucketId = group.first;
const auto &policies = group.second;
+
+ if (m_backend.hasBucket(bucketId) == false) {
+ throw BucketNotExistsException(bucketId);
+ }
+
std::for_each(policies.cbegin(), policies.cend(), pointedBucketExists);
}
diff --git a/test/storage/storage/policies.cpp b/test/storage/storage/policies.cpp
index 0166ff5..8d72dde 100644
--- a/test/storage/storage/policies.cpp
+++ b/test/storage/storage/policies.cpp
@@ -86,8 +86,12 @@ TEST(storage, insertPolicies) {
FakeStorageBackend backend;
Storage storage(backend);
- PolicyBucketId testBucket1 = "test-bucket-1";
- PolicyBucketId testBucket2 = "test-bucket-2";
+ std::vector testBuckets = {
+ PolicyBucketId("test-bucket-1"),
+ PolicyBucketId("test-bucket-2"),
+ };
+
+ PolicyResult defaultPolicy(PredefinedPolicyType::DENY);
typedef std::pair> BucketPolicyPair;
@@ -96,18 +100,26 @@ TEST(storage, insertPolicies) {
};
std::map> policiesToInsert = {
- BucketPolicyPair(testBucket1, {
+ BucketPolicyPair(testBuckets[0], {
createPolicy("1", ALLOW),
createPolicy("2", DENY),
createPolicy("3", DENY)
}),
- BucketPolicyPair(testBucket2, {
- createPolicy("4", { BUCKET, testBucket1 }),
+ BucketPolicyPair(testBuckets[1], {
+ createPolicy("4", { BUCKET, testBuckets[0] }),
createPolicy("5", PredefinedPolicyType::ALLOW)
})
};
- EXPECT_CALL(backend, hasBucket(testBucket1)).WillOnce(Return(true));
+ for (const auto &bucket: testBuckets) {
+ EXPECT_CALL(backend, hasBucket(bucket)).WillOnce(Return(false));
+ EXPECT_CALL(backend, createBucket(bucket, defaultPolicy)).WillOnce(Return());
+
+ storage.addOrUpdateBucket(bucket, defaultPolicy);
+ }
+
+ EXPECT_CALL(backend, hasBucket(testBuckets[0])).WillRepeatedly(Return(true));
+ EXPECT_CALL(backend, hasBucket(testBuckets[1])).WillOnce(Return(true));
for (const auto &group : policiesToInsert) {
const auto &bucketId = group.first;
@@ -130,6 +142,8 @@ TEST(storage, insertPointingToNonexistentBucket) {
PolicyBucketId testBucketId = "test-bucket-1";
PolicyBucketId nonexistentBucketId = "nonexistent";
+ PolicyResult defaultPolicy(PredefinedPolicyType::DENY);
+
typedef std::pair> BucketPolicyPair;
auto createPolicy = [] (const std::string &keySuffix, const PolicyResult &result) -> Policy {
@@ -143,6 +157,12 @@ TEST(storage, insertPointingToNonexistentBucket) {
}),
};
+ EXPECT_CALL(backend, hasBucket(testBucketId)).WillOnce(Return(false));
+ EXPECT_CALL(backend, createBucket(testBucketId, defaultPolicy)).WillOnce(Return());
+
+ storage.addOrUpdateBucket(testBucketId, defaultPolicy);
+
+ EXPECT_CALL(backend, hasBucket(testBucketId)).WillOnce(Return(true));
EXPECT_CALL(backend, hasBucket(nonexistentBucketId)).WillOnce(Return(false));
ASSERT_THROW(storage.insertPolicies(policiesToInsert), BucketNotExistsException);
--
2.7.4
From 6013044e77d40a59b49043e82e47332cd69b6d3d Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Fri, 14 Nov 2014 14:29:31 +0100
Subject: [PATCH 08/16] Add context invalidation mechanism
RequestTaker gets RequestContext, which might be processed in
another event loop. During this loop socket associated with this
context might get closed, so class holding this context needs
notification.
Change-Id: I77dee05b84a987e444f4ec71e87bcb867682768b
---
src/common/request/RequestTaker.cpp | 4 ++++
src/common/request/RequestTaker.h | 2 ++
src/service/logic/Logic.cpp | 4 ++++
src/service/logic/Logic.h | 2 ++
src/service/sockets/SocketManager.cpp | 5 ++++-
5 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp
index c87a9a4..a4d7c2d 100644
--- a/src/common/request/RequestTaker.cpp
+++ b/src/common/request/RequestTaker.cpp
@@ -59,4 +59,8 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, SignalRequestPtr re
throw NotImplementedException();
}
+void RequestTaker::contextClosed(RequestContextPtr context UNUSED) {
+ throw NotImplementedException();
+}
+
} // namespace Cynara
diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h
index b1d3466..522d8bb 100644
--- a/src/common/request/RequestTaker.h
+++ b/src/common/request/RequestTaker.h
@@ -39,6 +39,8 @@ public:
virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request);
virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request);
virtual void execute(RequestContextPtr context, SignalRequestPtr request);
+
+ virtual void contextClosed(RequestContextPtr context);
};
} // namespace Cynara
diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp
index f76ce98..ca56d64 100644
--- a/src/service/logic/Logic.cpp
+++ b/src/service/logic/Logic.cpp
@@ -174,6 +174,10 @@ void Logic::execute(RequestContextPtr context, SetPoliciesRequestPtr request) {
request->sequenceNumber()));
}
+void Logic::contextClosed(RequestContextPtr context UNUSED) {
+ //We don't care now, but we will
+}
+
void Logic::onPoliciesChanged(void) {
m_storage->save();
m_socketManager->disconnectAllClients();
diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h
index 3c434a5..e74cffe 100644
--- a/src/service/logic/Logic.h
+++ b/src/service/logic/Logic.h
@@ -64,6 +64,8 @@ public:
virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request);
virtual void execute(RequestContextPtr context, SignalRequestPtr request);
+ virtual void contextClosed(RequestContextPtr context);
+
private:
PluginManagerPtr m_pluginManager;
StoragePtr m_storage;
diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp
index cb3c9b4..c9e1692 100644
--- a/src/service/sockets/SocketManager.cpp
+++ b/src/service/sockets/SocketManager.cpp
@@ -210,9 +210,12 @@ void SocketManager::readyForAccept(int fd) {
void SocketManager::closeSocket(int fd) {
LOGD("SocketManger closeSocket fd [%d] start", fd);
+ Descriptor &desc = m_fds[fd];
+ requestTaker()->contextClosed(std::make_shared(nullptr,
+ desc.writeQueue()));
removeReadSocket(fd);
removeWriteSocket(fd);
- m_fds[fd].clear();
+ desc.clear();
close(fd);
LOGD("SocketManger closeSocket fd [%d] done", fd);
}
--
2.7.4
From 06da6ae48965239adbb1b104707f1dd893f8c316 Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Fri, 17 Oct 2014 14:48:46 +0200
Subject: [PATCH 09/16] Add PathConfig
Put all default paths into globally visible namespaces.
Change-Id: I4f234c5558e828cbcacf86de8d266e89a0ad687c
---
src/admin/logic/Logic.cpp | 4 +--
src/client-async/logic/Logic.cpp | 4 +--
src/client/logic/Logic.cpp | 5 +--
src/common/CMakeLists.txt | 2 +-
src/common/config/PathConfig.cpp | 65 +++++++++++++++++++++++++++++++++++
src/common/config/PathConfig.h | 52 ++++++++++++++++++++++++++++
src/common/sockets/SocketPath.cpp | 32 -----------------
src/common/sockets/SocketPath.h | 37 --------------------
src/service/main/Cynara.cpp | 32 ++---------------
src/service/main/Cynara.h | 17 ++++-----
src/service/sockets/SocketManager.cpp | 10 +++---
11 files changed, 140 insertions(+), 120 deletions(-)
create mode 100644 src/common/config/PathConfig.cpp
create mode 100644 src/common/config/PathConfig.h
delete mode 100644 src/common/sockets/SocketPath.cpp
delete mode 100644 src/common/sockets/SocketPath.h
diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp
index 0deccb9..506ecbf 100644
--- a/src/admin/logic/Logic.cpp
+++ b/src/admin/logic/Logic.cpp
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
#include
@@ -39,7 +40,6 @@
#include
#include
#include
-#include
#include
#include "Logic.h"
@@ -47,7 +47,7 @@
namespace Cynara {
Logic::Logic() {
- m_socketClient = std::make_shared(SocketPath::admin,
+ m_socketClient = std::make_shared(PathConfig::SocketPath::admin,
std::make_shared());
}
diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp
index 8babbed..921c2d6 100644
--- a/src/client-async/logic/Logic.cpp
+++ b/src/client-async/logic/Logic.cpp
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,7 +37,6 @@
#include
#include
#include
-#include
#include "Logic.h"
@@ -45,7 +45,7 @@ namespace Cynara {
Logic::Logic(cynara_status_callback callback, void *userStatusData)
: m_statusCallback(callback, userStatusData) {
m_socketClient = std::make_shared(
- SocketPath::client, std::make_shared());
+ PathConfig::SocketPath::client, std::make_shared());
m_cache = std::make_shared();
auto naiveInterpreter = std::make_shared();
diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp
index 4886b78..e05a168 100644
--- a/src/client/logic/Logic.cpp
+++ b/src/client/logic/Logic.cpp
@@ -24,6 +24,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,7 +37,6 @@
#include
#include
#include
-#include
#include
@@ -48,7 +48,8 @@ static ProtocolFrameSequenceNumber generateSequenceNumber(void) {
}
Logic::Logic() {
- m_socket = std::make_shared(SocketPath::client, std::make_shared());
+ m_socket = std::make_shared(PathConfig::SocketPath::client,
+ std::make_shared());
m_cache = std::make_shared();
auto naiveInterpreter = std::make_shared();
m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter);
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 6cd0005..61debfd 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -26,6 +26,7 @@ INCLUDE_DIRECTORIES(
)
SET(COMMON_SOURCES
+ ${COMMON_PATH}/config/PathConfig.cpp
${COMMON_PATH}/containers/BinaryQueue.cpp
${COMMON_PATH}/log/log.cpp
${COMMON_PATH}/protocol/ProtocolAdmin.cpp
@@ -49,7 +50,6 @@ SET(COMMON_SOURCES
${COMMON_PATH}/response/ResponseTaker.cpp
${COMMON_PATH}/sockets/Socket.cpp
${COMMON_PATH}/sockets/SocketClient.cpp
- ${COMMON_PATH}/sockets/SocketPath.cpp
${COMMON_PATH}/types/PolicyBucket.cpp
${COMMON_PATH}/types/PolicyKey.cpp
${COMMON_PATH}/types/PolicyKeyHelpers.cpp
diff --git a/src/common/config/PathConfig.cpp b/src/common/config/PathConfig.cpp
new file mode 100644
index 0000000..a5a603b
--- /dev/null
+++ b/src/common/config/PathConfig.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 src/common/config/PathConfig.cpp
+ * @author Zofia Abramowska
+ * @version 1.0
+ * @brief This file specifies PathConfig namespace containing values of default cynara paths
+ */
+
+#include "PathConfig.h"
+
+namespace Cynara {
+namespace PathConfig {
+
+//main paths
+const std::string statePath(
+#ifdef CYNARA_STATE_PATH
+ CYNARA_STATE_PATH
+#else
+ "/var/lib/cynara/"
+#endif
+ );
+
+const std::string libraryPath(
+#ifdef CYNARA_LIB_PATH
+ CYNARA_LIB_PATH
+#else
+ "/usr/lib/cynara/"
+#endif
+ );
+
+const std::string clientPath("/run/cynara/");
+
+namespace SocketPath {
+const std::string client(clientPath + "cynara.socket");
+const std::string admin(clientPath + "cynara-admin.socket");
+} // namespace SocketPath
+
+namespace StoragePath {
+const std::string dbDir(statePath + "db/");
+} // namespace StoragePath
+
+namespace PluginPath {
+const std::string clientDir(libraryPath + "plugin/client/");
+const std::string serviceDir(libraryPath + "plugin/service/");
+} // namespace PluginPath
+
+} // namespace PathConfig
+} // namespace Cynara
+
+
+
diff --git a/src/common/config/PathConfig.h b/src/common/config/PathConfig.h
new file mode 100644
index 0000000..27b10c2
--- /dev/null
+++ b/src/common/config/PathConfig.h
@@ -0,0 +1,52 @@
+/*
+ * 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 src/common/config/PathConfig.h
+ * @author Zofia Abramowska
+ * @version 1.0
+ * @brief This file specifies PathConfig namespace containing default cynara paths
+ */
+
+#ifndef SRC_COMMON_CONFIG_PATHCONFIG_H_
+#define SRC_COMMON_CONFIG_PATHCONFIG_H_
+
+#include
+
+namespace Cynara {
+namespace PathConfig {
+
+extern const std::string statePath;
+extern const std::string libraryPath;
+extern const std::string clientPath;
+
+namespace SocketPath {
+extern const std::string client;
+extern const std::string admin;
+} // namespace SocketPath
+
+namespace StoragePath {
+extern const std::string dbDir;
+} // namespace StoragePath
+
+namespace PluginPath {
+extern const std::string clientDir;
+extern const std::string serviceDir;
+} // namespace PluginPath
+
+} // namespace PathConfig
+} // namespace Cynara
+
+#endif /* SRC_COMMON_CONFIG_PATHCONFIG_H_ */
diff --git a/src/common/sockets/SocketPath.cpp b/src/common/sockets/SocketPath.cpp
deleted file mode 100644
index c64e2ff..0000000
--- a/src/common/sockets/SocketPath.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 src/common/sockets/SocketPath.cpp
- * @author Marcin Niesluchowski
- * @version 1.0
- * @brief Source file for common socket paths
- */
-
-#include "SocketPath.h"
-
-namespace Cynara {
-namespace SocketPath {
-
-const std::string client("/run/cynara/cynara.socket");
-const std::string admin("/run/cynara/cynara-admin.socket");
-
-} // namespace SocketPath
-} // namespace Cynara
diff --git a/src/common/sockets/SocketPath.h b/src/common/sockets/SocketPath.h
deleted file mode 100644
index cca867d..0000000
--- a/src/common/sockets/SocketPath.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 src/common/sockets/SocketPath.h
- * @author Marcin Niesluchowski
- * @version 1.0
- * @brief Header for common socket paths
- */
-
-#ifndef SRC_COMMON_SOCKETS_SOCKETPATH_H_
-#define SRC_COMMON_SOCKETS_SOCKETPATH_H_
-
-#include
-
-namespace Cynara {
-namespace SocketPath {
-
-extern const std::string client;
-extern const std::string admin;
-
-} // namespace SocketPath
-} // namespace Cynara
-
-#endif // SRC_COMMON_SOCKETS_SOCKETPATH_H_
diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp
index 1a0d45e..c0f77ef 100644
--- a/src/service/main/Cynara.cpp
+++ b/src/service/main/Cynara.cpp
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
@@ -45,38 +46,11 @@ Cynara::~Cynara() {
finalize();
}
-const std::string Cynara::storageDir(void) {
- std::string dir("/var/lib/cynara/");
-
-#ifdef CYNARA_STATE_PATH
- dir = CYNARA_STATE_PATH;
-#else
- LOGW("Cynara compiled without CYNARA_STATE_PATH flag. Using default database directory.");
-#endif
-
- dir += "db/";
- LOGI("Cynara database path <%s>", dir.c_str());
- return dir;
-}
-
-const std::string Cynara::pluginDir(void) {
- std::string dir("/usr/lib/cynara/");
-
-#ifdef CYNARA_LIB_PATH
- dir = CYNARA_LIB_PATH;
-#else
- LOGW("Cynara compiled without CYNARA_LIB_PATH flag. Using default plugin directory.");
-#endif
- dir += "plugin/";
- LOGI("Cynara plugin path <%s>", dir.c_str());
- return dir;
-}
-
void Cynara::init(void) {
m_logic = std::make_shared();
- m_pluginManager = std::make_shared(pluginDir());
+ m_pluginManager = std::make_shared(PathConfig::PluginPath::serviceDir);
m_socketManager = std::make_shared();
- m_storageBackend = std::make_shared(storageDir());
+ m_storageBackend = std::make_shared(PathConfig::StoragePath::dbDir);
m_storage = std::make_shared(*m_storageBackend);
m_logic->bindPluginManager(m_pluginManager);
diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h
index e89eda3..2eb94dc 100644
--- a/src/service/main/Cynara.h
+++ b/src/service/main/Cynara.h
@@ -28,16 +28,6 @@
namespace Cynara {
class Cynara {
-private:
- LogicPtr m_logic;
- PluginManagerPtr m_pluginManager;
- SocketManagerPtr m_socketManager;
- StoragePtr m_storage;
- StorageBackendPtr m_storageBackend;
-
- static const std::string pluginDir(void);
- static const std::string storageDir(void);
-
public:
Cynara();
~Cynara();
@@ -45,6 +35,13 @@ public:
void init(void);
void run(void);
void finalize(void);
+
+private:
+ LogicPtr m_logic;
+ PluginManagerPtr m_pluginManager;
+ SocketManagerPtr m_socketManager;
+ StoragePtr m_storage;
+ StorageBackendPtr m_storageBackend;
};
} // namespace Cynara
diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp
index c9e1692..3161dc7 100644
--- a/src/service/sockets/SocketManager.cpp
+++ b/src/service/sockets/SocketManager.cpp
@@ -37,10 +37,10 @@
#include
#include
+#include
#include
#include
#include
-#include
#include
#include
@@ -73,10 +73,10 @@ void SocketManager::init(void) {
const mode_t clientSocketUMask(0);
const mode_t adminSocketUMask(0077);
- createDomainSocket(std::make_shared(), SocketPath::client, clientSocketUMask,
- true);
- createDomainSocket(std::make_shared(), SocketPath::admin, adminSocketUMask,
- false);
+ createDomainSocket(std::make_shared(), PathConfig::SocketPath::client,
+ clientSocketUMask, true);
+ createDomainSocket(std::make_shared(), PathConfig::SocketPath::admin,
+ adminSocketUMask, false);
createSignalSocket(std::make_shared());
LOGI("SocketManger init done");
}
--
2.7.4
From aae388640a4fa6b772db232e28d6e4fc5a65278c Mon Sep 17 00:00:00 2001
From: Zofia Abramowska
Date: Thu, 16 Oct 2014 18:35:48 +0200
Subject: [PATCH 10/16] Fix dlopened objects management
* Add destroy function type, so deletion is compatible with allocation
* Remove extern "C" from plugin creation/destruction typedefs
* Add proper comments, so expected names of creation/destruction
function symbol are known to API user
Change-Id: I019f5bf83afc94945c8efc62e99dd324c419cc33
---
src/include/cynara-plugin.h | 17 +++++++++++++----
src/service/plugin/PluginManager.cpp | 18 ++++++++++++++++--
src/service/plugin/PluginManager.h | 3 ++-
3 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h
index 83956fe..a9d6da7 100644
--- a/src/include/cynara-plugin.h
+++ b/src/include/cynara-plugin.h
@@ -34,11 +34,20 @@ namespace Cynara {
class ExternalPluginInterface;
-extern "C" {
-typedef ExternalPluginInterface *(*createPlugin)(void);
-}
+/**
+ * Type of function used for creating objects implementing ExternalPluginInterface.
+ * Inside plugin library function with create_t signature should have symbol
+ * named "create".
+ */
+typedef ExternalPluginInterface *(*create_t)(void);
+/**
+ * Type of function used for destroying objects created with "create".
+ * Inside plugin library function with destroy_t signature should have symbol
+ * named "destroy".
+ */
+typedef void (*destroy_t)(ExternalPluginInterface *);
-//These typedefs will be defined in external headers
+// These typedefs will be defined in external headers
typedef std::string PluginData;
typedef std::string AgentType;
typedef std::vector PolicyTypes;
diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp
index 3d21b49..c591805 100644
--- a/src/service/plugin/PluginManager.cpp
+++ b/src/service/plugin/PluginManager.cpp
@@ -53,6 +53,14 @@ PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) {
loadPlugins();
}
+PluginManager::~PluginManager(void) {
+ // We have to be sure, that external objects will be destroyed
+ // before handles to libraries are closed.
+ for (auto &plugin : m_plugins) {
+ plugin.second.reset();
+ }
+}
+
ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) {
return m_plugins[pType];
}
@@ -90,7 +98,7 @@ void PluginManager::openPlugin(const std::string &path) {
//Flush any previous errors
dlerror();
- createPlugin func = reinterpret_cast(dlsym(handle, "create"));
+ create_t creator = reinterpret_cast(dlsym(handle, "create"));
char *error;
if ((error = dlerror()) != NULL) {
@@ -98,7 +106,13 @@ void PluginManager::openPlugin(const std::string &path) {
return;
}
- ExternalPluginPtr pluginPtr(func());
+ destroy_t destroyer = reinterpret_cast(dlsym(handle, "destroy"));
+ if ((error = dlerror()) != NULL) {
+ LOGE("Couldn't resolve symbol from lib <%s> : <%s>", path.c_str(), error);
+ return;
+ }
+
+ ExternalPluginPtr pluginPtr(creator(), destroyer);
if (!pluginPtr) {
LOGE("Couldn't create plugin for <%s>", path.c_str());
diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h
index 6338cad..1abc6e6 100644
--- a/src/service/plugin/PluginManager.h
+++ b/src/service/plugin/PluginManager.h
@@ -23,6 +23,7 @@
#ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_
#define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_
+#include
#include
#include