#include <fstream>
#include <functional>
#include <memory>
+#include <new>
#include <stdexcept>
#include <string>
#include <string.h>
namespace Cynara {
+const std::string InMemoryStorageBackend::m_chsFilename(PathConfig::StoragePath::checksumFilename);
const std::string InMemoryStorageBackend::m_indexFilename(PathConfig::StoragePath::indexFilename);
const std::string InMemoryStorageBackend::m_backupFilenameSuffix(
PathConfig::StoragePath::backupFilenameSuffix);
PathConfig::StoragePath::bucketFilenamePrefix);
InMemoryStorageBackend::InMemoryStorageBackend(const std::string &path) : m_dbPath(path),
- m_integrity(path) {
+ m_checksum(path), m_integrity(path) {
}
void InMemoryStorageBackend::load(void) {
bool isBackupValid = m_integrity.backupGuardExists();
std::string bucketSuffix = "";
std::string indexFilename = m_dbPath + m_indexFilename;
+ std::string chsFilename = m_dbPath + m_chsFilename;
if (isBackupValid) {
bucketSuffix += m_backupFilenameSuffix;
indexFilename += m_backupFilenameSuffix;
+ chsFilename += m_backupFilenameSuffix;
}
try {
+ auto chsStream = std::make_shared<std::ifstream>();
+ openFileStream(chsStream, chsFilename, isBackupValid);
+ m_checksum.load(*chsStream);
+
auto indexStream = std::make_shared<std::ifstream>();
- openFileStream(indexStream, indexFilename);
+ openFileStream(indexStream, indexFilename, isBackupValid);
StorageDeserializer storageDeserializer(indexStream,
std::bind(&InMemoryStorageBackend::bucketStreamOpener, this,
- std::placeholders::_1, bucketSuffix));
+ std::placeholders::_1, bucketSuffix, isBackupValid));
storageDeserializer.initBuckets(buckets());
storageDeserializer.loadBuckets(buckets());
buckets().clear();
// TODO: Implement emergency mode toggle
}
+ m_checksum.clear();
if (!hasBucket(defaultPolicyBucketId)) {
LOGN("Creating defaultBucket.");
}
void InMemoryStorageBackend::openFileStream(std::shared_ptr<std::ifstream> stream,
- const std::string &filename) {
+ const std::string &filename, bool isBackupValid) {
// TODO: Consider adding exceptions to streams and handling them:
// stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
stream->open(filename);
if (!stream->is_open()) {
throw FileNotFoundException(filename);
}
+
+ m_checksum.compare(*stream, filename, isBackupValid);
}
void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr<std::ofstream> stream,
}
std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
- const PolicyBucketId &bucketId, const std::string &filenameSuffix) {
+ const PolicyBucketId &bucketId, const std::string &filenameSuffix, bool isBackupValid) {
std::string bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId + filenameSuffix;
auto bucketStream = std::make_shared<std::ifstream>();
try {
- openFileStream(bucketStream, bucketFilename);
+ openFileStream(bucketStream, bucketFilename, isBackupValid);
return std::make_shared<BucketDeserializer>(bucketStream);
} catch (const FileNotFoundException &) {
return nullptr;
+ } catch (const std::bad_alloc &) {
+ return nullptr;
}
}
}
//in case there were unnecessary files in db directory
m_integrity.deleteNonIndexedFiles(std::bind(&InMemoryStorageBackend::hasBucket, this,
- std::placeholders::_1));
+ std::placeholders::_1));
}
} /* namespace Cynara */
#include <storage/BucketDeserializer.h>
#include <storage/Buckets.h>
+#include <storage/ChecksumValidator.h>
#include <storage/Integrity.h>
#include <storage/StorageBackend.h>
#include <storage/StorageSerializer.h>
const PolicyKey &filter);
protected:
- void openFileStream(std::shared_ptr<std::ifstream> stream, const std::string &filename);
+ void openFileStream(std::shared_ptr<std::ifstream> stream, const std::string &filename,
+ bool isBackupValid);
std::shared_ptr<BucketDeserializer> bucketStreamOpener(const PolicyBucketId &bucketId,
- const std::string &fileNameSuffix);
+ const std::string &fileNameSuffix,
+ bool isBackupValid);
virtual void openDumpFileStream(std::shared_ptr<std::ofstream> stream,
const std::string &filename);
private:
std::string m_dbPath;
Buckets m_buckets;
+ ChecksumValidator m_checksum;
Integrity m_integrity;
+ static const std::string m_chsFilename;
static const std::string m_indexFilename;
static const std::string m_backupFilenameSuffix;
static const std::string m_bucketFilenamePrefix;
}
syncElement(m_dbPath + m_indexFilename + suffix);
+ syncElement(m_dbPath + PathConfig::StoragePath::checksumFilename + suffix);
syncDirectory(m_dbPath);
}
if (fileFd < 0) {
int err = errno;
if (err != EEXIST) {
- LOGE("'open' function error [%d] : <%s>", err, strerror(err));
+ LOGE("File <%s> : 'open' function error [%d] : <%s>", filename.c_str(), err,
+ strerror(err));
throw UnexpectedErrorException(err, strerror(err));
} else {
throw CannotCreateFileException(filename);
}
const auto &indexFilename = m_dbPath + m_indexFilename;
+ const auto &checksumFilename = m_dbPath + PathConfig::StoragePath::checksumFilename;
deleteHardLink(indexFilename);
createHardLink(indexFilename + m_backupFilenameSuffix, indexFilename);
+ deleteHardLink(checksumFilename);
+ createHardLink(checksumFilename + m_backupFilenameSuffix, checksumFilename);
}
void Integrity::deleteBackupHardLinks(const Buckets &buckets) {
}
deleteHardLink(m_dbPath + m_indexFilename + m_backupFilenameSuffix);
+ deleteHardLink(m_dbPath + PathConfig::StoragePath::checksumFilename + m_backupFilenameSuffix);
}
void Integrity::createHardLink(const std::string &oldName, const std::string &newName) {