Skip to content

Commit

Permalink
Merge pull request #17 from nemomobile/lock-repo
Browse files Browse the repository at this point in the history
Lock repository when working with it
  • Loading branch information
Denis Zalevskiy committed Oct 30, 2014
2 parents 03a379c + 14305ea commit 9cbc986
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 4 deletions.
13 changes: 11 additions & 2 deletions include/vault/vault.hpp
Expand Up @@ -8,6 +8,7 @@
* @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*/

#include <qtaround/os.hpp>
#include <functional>

#include <QString>
Expand All @@ -18,7 +19,8 @@

namespace vault {

enum class File { Message, VersionTree, VersionRepo, State };
enum class File { Message, VersionTree, VersionRepo, State, Lock
, Last_ = Lock };

QString fileName(File);

Expand All @@ -36,6 +38,10 @@ class Snapshot
Gittin::Tag m_tag;
};

typedef std::shared_ptr<qtaround::os::FileLock> Lock;
typedef std::weak_ptr<qtaround::os::FileLock> Barrier;


class Vault
{
public:
Expand Down Expand Up @@ -85,6 +91,8 @@ class Vault
bool ensureValid();
void reset(const QByteArray &treeish = QByteArray());

Lock lock() const;

private:
bool setState(const QString &state);
bool backupUnit(const QString &home, const QString &unit, const ProgressCallback &callback);
Expand All @@ -93,7 +101,7 @@ class Vault
void resetMaster();

void setup(const QVariantMap *config);
QString absolutePath(QString const &);
QString absolutePath(QString const &) const;
QString readFile(const QString &relPath);

void setVersion(File, int);
Expand All @@ -103,6 +111,7 @@ class Vault
const QString m_blobStorage;
Gittin::Repo m_vcs;
config::Vault m_config;
mutable Barrier m_barrier;
};

}
Expand Down
1 change: 1 addition & 0 deletions rpm/vault.spec
Expand Up @@ -14,6 +14,7 @@ BuildRequires: pkgconfig(gittin)
BuildRequires: pkgconfig(tut) >= 0.0.3
BuildRequires: pkgconfig(Qt5Core) >= 5.2.0
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(qtaround) >= 0.2.3
%{?_with_usersession:Requires: systemd-user-session-targets}
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
Expand Down
2 changes: 2 additions & 0 deletions src/transfer.cpp
Expand Up @@ -210,6 +210,8 @@ void CardTransfer::validateDump(QString const &archive, QVariantMap const &err)

void CardTransfer::exportStorage(CardTransfer::progressCallback onProgress)
{
auto v = getVault();
auto l = v ? v->lock() : nullptr;
auto tag_fname = vault::fileName(File::State);
QStringList options = {"-cf", dst_, "-C", src_, ".git", tag_fname};
onProgress({{"type", "stage"}, {"stage", "Copy"}});
Expand Down
43 changes: 41 additions & 2 deletions src/vault.cpp
Expand Up @@ -37,6 +37,7 @@ static const QMap<File, QString> fileNames = {
, {File::VersionTree, ".vault"}
, {File::VersionRepo, os::path::join(".git", "vault.version")}
, {File::State, ".vault.state"}
, {File::Lock, ".vault.lock"}
};

QString fileName(File id)
Expand Down Expand Up @@ -144,6 +145,7 @@ int Vault::execute(const QVariantMap &options)
}

Vault vault(options.value("vault").toString());
auto l = vault.lock();
QStringList units{str(options.value("unit")).split(",", QString::SkipEmptyParts)};

auto unitsResult = [](Result &&res) {
Expand Down Expand Up @@ -232,19 +234,22 @@ int Vault::getVersion(File src)
return readFile(fileName(src)).toInt();
}

QString Vault::absolutePath(QString const &relativePath)
QString Vault::absolutePath(QString const &relativePath) const
{
return os::path::join(m_path, relativePath);
}

void Vault::setup(const QVariantMap *config)
{
auto createRepo = [this]() {
debug::debug("Setup vault", config ? *config : QVariantMap{});
auto l = lock();
auto createRepo = [this, &l]() {
debug::debug("Creating repo at", m_path);
if (!os::path::exists(m_path))
if (!os::mkdir(m_path))
error::raise({{"msg", "Can't create repo dir"}, {"path", m_path}});

l = lock();
if (!m_vcs.init())
error::raise({{"msg", "Can't init git repo"}, {"path", m_path}});
};
Expand Down Expand Up @@ -352,6 +357,7 @@ void Vault::setup(const QVariantMap *config)
bool Vault::init(const QVariantMap &config)
{
try {
auto l = lock();
setup(&config);
return true;
} catch (std::exception const &e) {
Expand All @@ -364,6 +370,7 @@ bool Vault::init(const QVariantMap &config)

bool Vault::ensureValid()
{
auto l = lock();
if (!os::path::exists(absolutePath(".git"))) {
debug::info("Can't find .git", m_path);
return false;
Expand All @@ -387,6 +394,7 @@ bool Vault::ensureValid()
Vault::Result Vault::backup(const QString &home, const QStringList &units, const QString &message, const ProgressCallback &callback)
{
debug::info("Backup units", units, ", home", home);
auto l = lock();
Result res;
res.failedUnits << units;

Expand Down Expand Up @@ -433,6 +441,7 @@ Vault::Result Vault::backup(const QString &home, const QStringList &units, const

bool Vault::clear(const QVariantMap &options)
{
auto l = lock();
if (!os::path::isDir(m_path)) {
debug::info("vault.clear:", "Path", m_path, "is not a dir");
return false;
Expand Down Expand Up @@ -465,6 +474,7 @@ bool Vault::clear(const QVariantMap &options)

void Vault::reset(const QByteArray &treeish)
{
auto l = lock();
m_vcs.clean(CleanOptions::Force | CleanOptions::RemoveDirectories);
if (!treeish.isEmpty()) {
m_vcs.reset(ResetOptions::Hard, treeish);
Expand All @@ -481,12 +491,14 @@ void Vault::resetMaster()

Vault::Result Vault::restore(const QString &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback)
{
auto l = lock();
Snapshot ss(Gittin::Tag(&m_vcs, QString(">") + snapshot));
return restore(ss, home, units, callback);
}

Vault::Result Vault::restore(const Snapshot &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback)
{
auto l = lock();
debug::info("Restore units", units, ", home", home);
Result res;
res.failedUnits << units;
Expand Down Expand Up @@ -523,6 +535,7 @@ Vault::Result Vault::restore(const Snapshot &snapshot, const QString &home, cons

QList<Snapshot> Vault::snapshots() const
{
auto l = lock();
auto tags = m_vcs.tags();
QList<Snapshot> list;
for (const Gittin::Tag &tag: tags) {
Expand All @@ -535,6 +548,7 @@ QList<Snapshot> Vault::snapshots() const

Snapshot Vault::snapshot(const QByteArray &tagName) const
{
auto l = lock();
auto tags = m_vcs.tags();
for (const Gittin::Tag &tag: tags) {
if (tag.name() == tagName) {
Expand All @@ -547,6 +561,7 @@ Snapshot Vault::snapshot(const QByteArray &tagName) const

QString Vault::notes(const QString &snapshot)
{
auto l = lock();
Gittin::Tag tag(&m_vcs, snapshot);
return tag.notes();
}
Expand Down Expand Up @@ -775,4 +790,28 @@ void Vault::tagSnapshot(const QString &msg)
m_vcs.tag(QLatin1String(">") + msg);
}

/**
* \note thread-unsafe
*/
Lock Vault::lock() const
{
if (!exists())
return Lock{};
auto handle = m_barrier.lock();
if (!handle) {
int timeout = 1 * 1000;
auto lock_fname = absolutePath(fileName(File::Lock));
auto gotLock = [&handle](os::FileLock l) { handle = box(std::move(l)); };
auto locker = os::tryLock(lock_fname, gotLock, timeout);
while (locker) {
// max 8s timeout
if (timeout <= 4 * 1000)
timeout *= 2;
locker = os::tryLock(std::move(locker), gotLock, timeout);
}
m_barrier = handle;
}
return handle;
}

}

0 comments on commit 9cbc986

Please sign in to comment.