From c3a1946675855b299a2b36550cdf2c2f69d153aa Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Mon, 17 Sep 2012 23:03:03 +0200 Subject: initial import --- distfoldd/distfolder.cc | 200 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 distfoldd/distfolder.cc (limited to 'distfoldd/distfolder.cc') diff --git a/distfoldd/distfolder.cc b/distfoldd/distfolder.cc new file mode 100644 index 0000000..211aafe --- /dev/null +++ b/distfoldd/distfolder.cc @@ -0,0 +1,200 @@ +#include + +#include "clientagent.h" +#include "serveragent.h" +#include "distfolder.h" + +DistFolder::DistFolder(const QUuid& uuid, const QString& localPath, QObject *parent) : + QObject(parent), _uuid(uuid), _localPath(localPath), + _mtime(), _mtimeChanged(false), + _watcher(new Watcher(localPath, this)), + _server(new Server(this)), + _discoverer(new Discoverer(uuid, _server->serverPort(), QString("Files on %1").arg(_localPath.canonicalPath()), this)), + _syncFlags(Agent::SYNC_NORMAL), + _numAgents(0) +{ + Q_ASSERT(_localPath.isReadable()); + connect(_watcher, SIGNAL(pathAdded(QString)), SLOT(handlePathAdded(QString))); + connect(_watcher, SIGNAL(pathChanged(QString)), SLOT(handlePathChanged(QString))); + connect(_watcher, SIGNAL(pathRemoved(QString)), SLOT(handlePathRemoved(QString))); + updateLastModTime(); + connect(_discoverer, SIGNAL(foundMoreRecentHost(QHostAddress,uint,QDateTime)), + SLOT(handleMoreRecentHost(QHostAddress,uint,QDateTime))); + connect(_server, SIGNAL(newConnection()), SLOT(handleNewConnection())); + qDebug() << "Ready Folder UUID:" << _uuid; +} + +bool DistFolder::readOnlySync() const +{ + return _syncFlags & Agent::SYNC_READ_ONLY; +} + +void DistFolder::setReadOnlySync(bool read_only) +{ + if (read_only) { + qDebug() << "Enabling read only sync"; + _syncFlags |= Agent::SYNC_READ_ONLY; + } else { + _syncFlags &= ~Agent::SYNC_READ_ONLY; + } +} + +bool DistFolder::pullMode() const +{ + return _syncFlags & Agent::SYNC_PULL; +} + +void DistFolder::setPullMode(bool pull_mode) +{ + if (pull_mode) { + qDebug() << "Enabling pull sync"; + _syncFlags |= Agent::SYNC_PULL; + } else { + _syncFlags &= ~Agent::SYNC_PULL; + } + updateLastModTime(); +} + +bool DistFolder::compress() const +{ + return _syncFlags & Agent::SYNC_COMPRESS; +} + +void DistFolder::setCompress(bool compress) +{ + if (compress) { + qDebug() << "Enabling compression"; + _syncFlags |= Agent::SYNC_COMPRESS; + } else { + _syncFlags &= ~Agent::SYNC_COMPRESS; + } +} + +QDateTime DistFolder::scanLastModTime() +{ + return scanLastModTime(_localPath); +} + +void DistFolder::updateLastModTime(const QDateTime& dt) +{ + QDateTime curMtime = _mtime; + if (pullMode()) { + _mtime = QDateTime::fromTime_t(0); // Force being the puller for the next sync + } else { + if (dt.isNull()) { + _mtime = scanLastModTime(); + } else if (dt > _mtime) { + _mtime = dt; + } + } + if (_mtime != curMtime) { + if (_numAgents > 0) { + _mtimeChanged = true; + } else { + _discoverer->setLastModifiedTime(_mtime); + _mtimeChanged = false; + } + } +} + +QDateTime DistFolder::scanLastModTime(const QDir& dir) +{ + QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + QDateTime max = QFileInfo(dir.absolutePath()).lastModified(); + + foreach (const QFileInfo &info, list) { + QDateTime mtime; + if (info.isDir()) { + mtime = scanLastModTime(QDir(info.absoluteFilePath())); + } else { + mtime = info.lastModified(); + } + if (mtime > max) { + max = mtime; + } + } + + return max; +} + +void DistFolder::handleNewConnection() +{ + qDebug() << "Incoming connection"; + ServerAgent *agent = + new ServerAgent(static_cast(_server->nextPendingConnection()), + _localPath, _syncFlags, this); + connect(agent, SIGNAL(destroyed()), SLOT(handleDestroyedAgent())); + _numAgents++; + qDebug() << "Num agents" << _numAgents; +} + +void DistFolder::handlePathAdded(const QString &path) +{ + QFileInfo info(path); + qDebug() << "added: " << path; + if (info.lastModified() > _mtime) { + updateLastModTime(info.lastModified()); + } +} + +void DistFolder::handlePathChanged(const QString &path) +{ + QFileInfo info(path); + qDebug() << "changed: " << path; + if (info.lastModified() > _mtime) { + updateLastModTime(info.lastModified()); + } +} + +void DistFolder::handlePathRemoved(const QString &path) +{ + QFileInfo info(path); + qDebug() << "removed: " << path; + // Find a parent that has not been removed + const QString base_path = _localPath.absolutePath(); + do { + info = QFileInfo(info.absolutePath()); + } while (!info.exists() && // Until it exists and as long as we are under the base dir. + info.absoluteFilePath().startsWith(base_path)); + if (info.lastModified() > _mtime) { + updateLastModTime(info.lastModified()); + } +} + +void DistFolder::handleMoreRecentHost(const QHostAddress &address, uint port, const QDateTime &dateTime) +{ + Q_UNUSED(dateTime); + if (_numAgents == 0) { + qDebug() << "Trying to connect to" << address.toString() << port; + ClientAgent *agent = new ClientAgent(address, port, _localPath, _syncFlags, this); + connect(agent, SIGNAL(destroyed()), SLOT(handleDestroyedAgent())); + connect(agent, SIGNAL(finished()), SLOT(handleClientFinished())); + _numAgents++; + qDebug() << "Num agents" << _numAgents; + } else { + qDebug() << "Busy but a more recent host was found"; + // TODO + } +} + +void DistFolder::handleClientFinished() +{ + if (pullMode()) { + // Stop pulling once a succesful sync is done + qDebug() << "Stopping pull mode"; + setPullMode(false); + } +} + +void DistFolder::handleDestroyedAgent() +{ + _numAgents--; + qDebug() << "Num agents" << _numAgents; + if (_numAgents == 0) { + // All sync agents have finished + if (_mtimeChanged) { + _discoverer->setLastModifiedTime(_mtime); + _mtimeChanged = false; + } + } +} -- cgit v1.2.3