From fb55ea21c891a75f2e7e06d336faa9b5b8b105a3 Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 14 Jun 2015 20:18:59 +0200 Subject: improve sync locking and status messages --- smartpensyncer.cc | 145 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 30 deletions(-) (limited to 'smartpensyncer.cc') diff --git a/smartpensyncer.cc b/smartpensyncer.cc index 551162e..cdf9bc6 100644 --- a/smartpensyncer.cc +++ b/smartpensyncer.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include "paperreplay.h" #include "notebookmodel.h" #include "smartpensyncer.h" @@ -28,33 +29,98 @@ #define BUFFER_SIZE 16 * 1024 namespace { -static QDateTime getTimestampFileDate(const QString &path) +class LockFile { - QFileInfo info(path); - qDebug() << "Checking timestamp" << info.filePath(); +public: + LockFile(const QString &path); + ~LockFile(); + + bool lock(); + +private: + QString _path; + FILE * _file; + bool _locked; +}; + +class TimestampFile +{ +public: + TimestampFile(const QString &path); + + QDateTime get(); + void set(); + +private: + QFileInfo _fi; +}; + +LockFile::LockFile(const QString &path) + : _path(path), _file(0), _locked(false) +{ + +} + +LockFile::~LockFile() +{ + if (_file) { + fclose(_file); + } + if (_locked) { + if (!QFile::remove(_path)) { + qWarning() << "Cannot remove lock file:" << _path; + } + } +} + +bool LockFile::lock() +{ + Q_ASSERT(!_locked); + + QFileInfo info(_path); if (info.exists()) { - return info.lastModified(); + if (info.created().secsTo(QDateTime::currentDateTime()) > 10 * 60) { + if (QFile::remove(info.filePath())) { + qDebug() << "Removing stale lock file:" << info.absoluteFilePath(); + } + } else { + return false; + } + } + + _file = ::fopen(info.absoluteFilePath().toLocal8Bit().data(), "wx"); + if (_file) { + _locked = true; + return true; } else { - return QDateTime(); + return false; } } -static void setTimestampFileDate(const QString &path) +TimestampFile::TimestampFile(const QString &path) + : _fi(path) { - QFile f(path); - if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qWarning() << "Could not set timestamp file:" << path; - return; +} + +QDateTime TimestampFile::get() +{ + qDebug() << "Checking timestamp" << _fi.filePath(); + if (_fi.exists()) { + return _fi.lastModified(); + } else { + return QDateTime(); } - f.close(); } -void removeTimestampFile(const QString &path) +void TimestampFile::set() { - QFile f(path); - if (!f.remove()) { - qWarning() << "Cannot remove timestamp file:" << path; + QFile f(_fi.filePath()); + if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qWarning() << "Could not set timestamp file:" << _fi.absoluteFilePath(); + return; } + f.close(); + _fi.refresh(); } } @@ -81,6 +147,11 @@ QString SmartpenSyncer::penName() const return _penName; } +bool SmartpenSyncer::hasErrors() const +{ + return _errored; +} + void SmartpenSyncer::abort() { _aborted = true; @@ -123,10 +194,14 @@ void SmartpenSyncer::run() bool SmartpenSyncer::syncPen() { - QDateTime lastSyncTime = getTimestampFileDate(_penDataDir.filePath(".lastsync")); - QList changes = _pen->getChangeList(lastSyncTime); + LockFile lock(_penDataDir.filePath(".sync.lck")); + if (!lock.lock()) { + qWarning() << "Pen is already being synchronized; delete this file if it is not:" << _penDataDir.absoluteFilePath(".sync.lck"); + return false; + } - setTimestampFileDate(_penDataDir.filePath(".sync.lck")); + TimestampFile lastSync(_penDataDir.filePath(".lastsync")); + QList changes = _pen->getChangeList(lastSync.get()); foreach(const Smartpen::ChangeReport &change, changes) { if (!change.guid.isEmpty()) { @@ -140,10 +215,14 @@ bool SmartpenSyncer::syncPen() return false; } } + + if (_aborted) { + qWarning() << "Aborting sync"; + return false; + } } - setTimestampFileDate(_penDataDir.filePath(".lastsync")); - removeTimestampFile(_penDataDir.filePath(".sync.lck")); + lastSync.set(); return true; } @@ -157,17 +236,20 @@ bool SmartpenSyncer::syncNotebook(const Smartpen::ChangeReport &change) } } - setTimestampFileDate(notebookDir.filePath(".sync.lck")); + LockFile lock(notebookDir.filePath(".sync.lck")); + if (!lock.lock()) { + qWarning() << "Notebook is already being synchronized; delete this file if it is not:" << notebookDir.absoluteFilePath(".sync.lck"); + return false; + } - QDateTime lastSyncTime = getTimestampFileDate(notebookDir.filePath(".lastsync")); - QByteArray lspData = _pen->getLspData(change.guid, lastSyncTime); + TimestampFile lastSync(notebookDir.filePath(".lastsync")); + QByteArray lspData = _pen->getLspData(change.guid, lastSync.get()); if (!extractZip(lspData, notebookDir)) { return false; } - setTimestampFileDate(notebookDir.filePath(".lastsync")); - removeTimestampFile(notebookDir.filePath(".sync.lck")); + lastSync.set(); return true; } @@ -181,17 +263,20 @@ bool SmartpenSyncer::syncPaperReplay() } } - setTimestampFileDate(replayDir.filePath(".sync.lck")); + LockFile lock(replayDir.filePath(".sync.lck")); + if (!lock.lock()) { + qWarning() << "Paper replay is already being synchronized; delete this file if it is not:" << replayDir.absoluteFilePath(".sync.lck"); + return false; + } - QDateTime lastSyncTime = getTimestampFileDate(replayDir.filePath(".lastsync")); - QByteArray replayData = _pen->getPaperReplay(lastSyncTime); + TimestampFile lastSync(replayDir.filePath(".lastsync")); + QByteArray replayData = _pen->getPaperReplay(lastSync.get()); if (!extractZip(replayData, replayDir)) { return false; } - setTimestampFileDate(replayDir.filePath(".lastsync")); - removeTimestampFile(replayDir.filePath(".sync.lck")); + lastSync.set(); return true; } -- cgit v1.2.3