Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Check an advisory lock in SQLStorage
Browse files Browse the repository at this point in the history
To guide users about the dangers of running several aktualizr instances
based on the same storage location.

Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
  • Loading branch information
lbonn committed May 23, 2019
1 parent 4d8e0fe commit 4cdc56a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 18 deletions.
30 changes: 30 additions & 0 deletions src/libaktualizr/storage/sqlstorage_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@

boost::filesystem::path SQLStorageBase::dbPath() const { return sqldb_path_; }

StorageLock::StorageLock(boost::filesystem::path path) : lock_path(std::move(path)) {
{
std::fstream fs;
fs.open(lock_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
}
fl_ = lock_path.c_str();
if (!fl_.try_lock()) {
throw StorageLock::locked_exception();
}
}

StorageLock::~StorageLock() {
try {
if (!lock_path.empty()) {
fl_.unlock();
std::remove(lock_path.c_str());
}
} catch (std::exception& e) {
}
}

SQLStorageBase::SQLStorageBase(boost::filesystem::path sqldb_path, bool readonly,
std::vector<std::string> schema_migrations,
std::vector<std::string> schema_rollback_migrations, std::string current_schema,
Expand Down Expand Up @@ -34,6 +55,15 @@ SQLStorageBase::SQLStorageBase(boost::filesystem::path sqldb_path, bool readonly
}
}

try {
lock = StorageLock(db_parent_path / "storage.lock");
} catch (StorageLock::locked_exception& e) {
LOG_WARNING << "\033[31m"
<< "Storage in " << db_parent_path
<< " is already in use, running several instances concurrently may result in data corruption!"
<< "\033[0m";
}

if (!dbMigrate()) {
throw StorageException("SQLite database migration failed");
}
Expand Down
32 changes: 29 additions & 3 deletions src/libaktualizr/storage/sqlstorage_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,61 @@
#define SQLSTORAGE_BASE_H_

#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

#include "sql_utils.h"
#include "storage_config.h"

enum class DbVersion : int32_t { kEmpty = -1, kInvalid = -2 };

class StorageLock {
public:
StorageLock() = default;
StorageLock(boost::filesystem::path path);
StorageLock(StorageLock &other) = delete;
StorageLock &operator=(StorageLock &other) = delete;
StorageLock(StorageLock &&other) = default;
StorageLock &operator=(StorageLock &&other) = default;
virtual ~StorageLock();

class locked_exception : std::runtime_error {
public:
locked_exception() : std::runtime_error("locked") {}
};

private:
boost::filesystem::path lock_path;
boost::interprocess::file_lock fl_;
};

class SQLStorageBase {
public:
explicit SQLStorageBase(boost::filesystem::path sqldb_path, bool readonly, std::vector<std::string> schema_migrations,
std::vector<std::string> schema_rollback_migrations, std::string current_schema,
int current_schema_version);
~SQLStorageBase() = default;
std::string getTableSchemaFromDb(const std::string& tablename);
std::string getTableSchemaFromDb(const std::string &tablename);
bool dbMigrateForward(int version_from, int version_to = 0);
bool dbMigrateBackward(int version_from, int version_to = 0);
bool dbMigrate();
DbVersion getVersion(); // non-negative integer on success or -1 on error
boost::filesystem::path dbPath() const;

protected:
SQLite3Guard dbConnection() const;
boost::filesystem::path sqldb_path_;
boost::filesystem::path images_path_{sqldb_path_.parent_path() / "images"};
bool readonly_{false};

StorageLock lock;

const std::vector<std::string> schema_migrations_;
std::vector<std::string> schema_rollback_migrations_;
const std::string current_schema_;
const int current_schema_version_;
bool dbInsertBackMigrations(SQLite3Guard& db, int version_latest);

SQLite3Guard dbConnection() const;
bool dbInsertBackMigrations(SQLite3Guard &db, int version_latest);
};

#endif // SQLSTORAGE_BASE_H_
33 changes: 18 additions & 15 deletions src/libaktualizr/storage/sqlstorage_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -396,26 +396,29 @@ TEST(sqlstorage, migrate_from_fs) {
// (anonymized data)
Utils::copyDir(test_data_dir / "fs_snapshot", config.path);
ASSERT_GE(chmod(config.path.c_str(), S_IRWXU), 0);
auto storage = INvStorage::newStorage(config);

EXPECT_TRUE(storage->loadPrimaryKeys(nullptr, nullptr));
EXPECT_TRUE(storage->loadTlsCreds(nullptr, nullptr, nullptr));
EXPECT_TRUE(storage->loadLatestRoot(nullptr, Uptane::RepositoryType::Director()));
EXPECT_TRUE(storage->loadDeviceId(nullptr));
{
auto storage = INvStorage::newStorage(config);

EXPECT_TRUE(storage->loadPrimaryKeys(nullptr, nullptr));
EXPECT_TRUE(storage->loadTlsCreds(nullptr, nullptr, nullptr));
EXPECT_TRUE(storage->loadLatestRoot(nullptr, Uptane::RepositoryType::Director()));
EXPECT_TRUE(storage->loadDeviceId(nullptr));

EcuSerials serials;
EXPECT_TRUE(storage->loadEcuSerials(&serials));
EXPECT_EQ(serials.size(), 3);
EcuSerials serials;
EXPECT_TRUE(storage->loadEcuSerials(&serials));
EXPECT_EQ(serials.size(), 3);

std::vector<MisconfiguredEcu> misconfigured;
EXPECT_TRUE(storage->loadMisconfiguredEcus(&misconfigured));
EXPECT_EQ(misconfigured.size(), 1);
std::vector<MisconfiguredEcu> misconfigured;
EXPECT_TRUE(storage->loadMisconfiguredEcus(&misconfigured));
EXPECT_EQ(misconfigured.size(), 1);

EXPECT_TRUE(storage->loadEcuRegistered());
EXPECT_TRUE(storage->loadEcuRegistered());

std::vector<Uptane::Target> installed;
storage->loadPrimaryInstalledVersions(&installed, nullptr, nullptr);
EXPECT_NE(installed.size(), 0);
std::vector<Uptane::Target> installed;
storage->loadPrimaryInstalledVersions(&installed, nullptr, nullptr);
EXPECT_NE(installed.size(), 0);
}

// note: installation result is not migrated anymore

Expand Down

0 comments on commit 4cdc56a

Please sign in to comment.