From: Jocelyn Turcotte Date: Wed, 15 Apr 2015 13:19:11 +0000 (+0200) Subject: Pass SyncFileItems by pointer instead of by value X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~1673^2~25 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=12d7484b85c92a0c897daf37fa992a330fb91d9f;p=nextcloud-desktop.git Pass SyncFileItems by pointer instead of by value Use a QSharedPointer to keep the same ownership and continue passing the SyncFileItems as a const& when ownership isn't taken. This allows sharing the same allocations between the jobs and the result vectors. This saves about 20MB of memory (off 120MB) once all jobs are created. --- diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 0b37518ee..96713d0cd 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -337,11 +337,11 @@ void Folder::bubbleUpSyncResult() int renamedItems = 0; int errorItems = 0; - SyncFileItem firstItemNew; - SyncFileItem firstItemDeleted; - SyncFileItem firstItemUpdated; - SyncFileItem firstItemRenamed; - SyncFileItem firstItemError; + SyncFileItemPtr firstItemNew; + SyncFileItemPtr firstItemDeleted; + SyncFileItemPtr firstItemUpdated; + SyncFileItemPtr firstItemRenamed; + SyncFileItemPtr firstItemError; SyncRunFileLog syncFileLog; @@ -350,52 +350,52 @@ void Folder::bubbleUpSyncResult() QElapsedTimer timer; timer.start(); - foreach (const SyncFileItem &item, _syncResult.syncFileItemVector() ) { + foreach (const SyncFileItemPtr &item, _syncResult.syncFileItemVector() ) { // Log the item - syncFileLog.logItem( item ); + syncFileLog.logItem( *item ); // and process the item to the gui - if( item._status == SyncFileItem::FatalError || item._status == SyncFileItem::NormalError ) { - slotSyncError( tr("%1: %2").arg(item._file, item._errorString) ); + if( item->_status == SyncFileItem::FatalError || item->_status == SyncFileItem::NormalError ) { + slotSyncError( tr("%1: %2").arg(item->_file, item->_errorString) ); errorItems++; - if (firstItemError.isEmpty()) { + if (!firstItemError) { firstItemError = item; } - } else if( item._status == SyncFileItem::FileIgnored ) { + } else if( item->_status == SyncFileItem::FileIgnored ) { // ignored files don't show up in notifications continue; } else { // add new directories or remove gone away dirs to the watcher - if (item._isDirectory && item._instruction == CSYNC_INSTRUCTION_NEW ) { - FolderMan::instance()->addMonitorPath( alias(), path()+item._file ); + if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_NEW ) { + FolderMan::instance()->addMonitorPath( alias(), path()+item->_file ); } - if (item._isDirectory && item._instruction == CSYNC_INSTRUCTION_REMOVE ) { - FolderMan::instance()->removeMonitorPath( alias(), path()+item._file ); + if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_REMOVE ) { + FolderMan::instance()->removeMonitorPath( alias(), path()+item->_file ); } - if (!item.hasErrorStatus() && item._direction == SyncFileItem::Down) { - switch (item._instruction) { + if (!item->hasErrorStatus() && item->_direction == SyncFileItem::Down) { + switch (item->_instruction) { case CSYNC_INSTRUCTION_NEW: newItems++; - if (firstItemNew.isEmpty()) + if (!firstItemNew) firstItemNew = item; break; case CSYNC_INSTRUCTION_REMOVE: removedItems++; - if (firstItemDeleted.isEmpty()) + if (!firstItemDeleted) firstItemDeleted = item; break; case CSYNC_INSTRUCTION_CONFLICT: case CSYNC_INSTRUCTION_SYNC: updatedItems++; - if (firstItemUpdated.isEmpty()) + if (!firstItemUpdated) firstItemUpdated = item; break; case CSYNC_INSTRUCTION_ERROR: qDebug() << "Got Instruction ERROR. " << _syncResult.errorString(); break; case CSYNC_INSTRUCTION_RENAME: - if (firstItemRenamed.isEmpty()) { + if (!firstItemRenamed) { firstItemRenamed = item; } renamedItems++; @@ -404,8 +404,8 @@ void Folder::bubbleUpSyncResult() // nothing. break; } - } else if( item._direction == SyncFileItem::None ) { // ignored files counting. - if( item._instruction == CSYNC_INSTRUCTION_IGNORE ) { + } else if( item->_direction == SyncFileItem::None ) { // ignored files counting. + if( item->_instruction == CSYNC_INSTRUCTION_IGNORE ) { ignoredItems++; } } @@ -416,28 +416,28 @@ void Folder::bubbleUpSyncResult() qDebug() << "Processing result list and logging took " << timer.elapsed() << " Milliseconds."; _syncResult.setWarnCount(ignoredItems); - if( !firstItemNew.isEmpty() ) { - createGuiLog( firstItemNew._file, SyncFileStatus::STATUS_NEW, newItems ); + if( firstItemNew ) { + createGuiLog( firstItemNew->_file, SyncFileStatus::STATUS_NEW, newItems ); } - if( !firstItemDeleted.isEmpty() ) { - createGuiLog( firstItemDeleted._file, SyncFileStatus::STATUS_REMOVE, removedItems ); + if( firstItemDeleted ) { + createGuiLog( firstItemDeleted->_file, SyncFileStatus::STATUS_REMOVE, removedItems ); } - if( ! firstItemUpdated.isEmpty() ) { - createGuiLog( firstItemUpdated._file, SyncFileStatus::STATUS_UPDATED, updatedItems ); + if( firstItemUpdated ) { + createGuiLog( firstItemUpdated->_file, SyncFileStatus::STATUS_UPDATED, updatedItems ); } - if( !firstItemRenamed.isEmpty() ) { + if( firstItemRenamed ) { SyncFileStatus status(SyncFileStatus::STATUS_RENAME); // if the path changes it's rather a move - QDir renTarget = QFileInfo(firstItemRenamed._renameTarget).dir(); - QDir renSource = QFileInfo(firstItemRenamed._file).dir(); + QDir renTarget = QFileInfo(firstItemRenamed->_renameTarget).dir(); + QDir renSource = QFileInfo(firstItemRenamed->_file).dir(); if(renTarget != renSource) { status.set(SyncFileStatus::STATUS_MOVE); } - createGuiLog( firstItemRenamed._file, status, renamedItems, firstItemRenamed._renameTarget ); + createGuiLog( firstItemRenamed->_file, status, renamedItems, firstItemRenamed->_renameTarget ); } - createGuiLog( firstItemError._file, SyncFileStatus::STATUS_ERROR, errorItems ); + createGuiLog( firstItemError->_file, SyncFileStatus::STATUS_ERROR, errorItems ); qDebug() << "OO folder slotSyncFinished: result: " << int(_syncResult.status()); } @@ -578,9 +578,9 @@ QString Folder::configFile() } static void addErroredSyncItemPathsToList(const SyncFileItemVector& items, QSet* set) { - Q_FOREACH(const SyncFileItem &item, items) { - if (item.hasErrorStatus()) { - set->insert(item._file); + Q_FOREACH(const SyncFileItemPtr &item, items) { + if (item->hasErrorStatus()) { + set->insert(item->_file); } } } @@ -805,8 +805,8 @@ void Folder::startSync(const QStringList &pathList) SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*))); connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString))); connect(_engine.data(), SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info))); - connect(_engine.data(), SIGNAL(jobCompleted(SyncFileItem)), this, SLOT(slotJobCompleted(SyncFileItem))); - connect(_engine.data(), SIGNAL(syncItemDiscovered(SyncFileItem)), this, SLOT(slotSyncItemDiscovered(SyncFileItem))); + connect(_engine.data(), SIGNAL(jobCompleted(const SyncFileItem &)), this, SLOT(slotJobCompleted(const SyncFileItem &))); + connect(_engine.data(), SIGNAL(syncItemDiscovered(const SyncFileItem &)), this, SLOT(slotSyncItemDiscovered(const SyncFileItem &))); setDirtyNetworkLimits(); _engine->setSelectiveSyncBlackList(selectiveSyncBlackList()); diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index 0f42154a8..af6edbac3 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -128,10 +128,10 @@ SocketApi::SocketApi(QObject* parent) // folder watcher connect(FolderMan::instance(), SIGNAL(folderSyncStateChange(QString)), this, SLOT(slotUpdateFolderView(QString))); - connect(ProgressDispatcher::instance(), SIGNAL(jobCompleted(QString,SyncFileItem)), - SLOT(slotJobCompleted(QString,SyncFileItem))); - connect(ProgressDispatcher::instance(), SIGNAL(syncItemDiscovered(QString,SyncFileItem)), - this, SLOT(slotSyncItemDiscovered(QString,SyncFileItem))); + connect(ProgressDispatcher::instance(), SIGNAL(jobCompleted(QString, const SyncFileItem &)), + SLOT(slotJobCompleted(QString, const SyncFileItem &))); + connect(ProgressDispatcher::instance(), SIGNAL(syncItemDiscovered(QString, const SyncFileItem &)), + this, SLOT(slotSyncItemDiscovered(QString, const SyncFileItem &))); } SocketApi::~SocketApi() diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index 1ccefaf59..49b3d0be7 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -79,15 +79,15 @@ static bool blacklist(SyncJournalDb* journal, const SyncFileItem& item) void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorString) { _state = Finished; - if (_item._isRestoration) { + if (_item->_isRestoration) { if( status == SyncFileItem::Success || status == SyncFileItem::Conflict) { status = SyncFileItem::Restoration; } else { - _item._errorString += tr("; Restoration Failed: %1").arg(errorString); + _item->_errorString += tr("; Restoration Failed: %1").arg(errorString); } } else { - if( _item._errorString.isEmpty() ) { - _item._errorString = errorString; + if( _item->_errorString.isEmpty() ) { + _item->_errorString = errorString; } } @@ -103,20 +103,20 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr // do not blacklist in case of soft error or fatal error. break; case SyncFileItem::NormalError: - if (blacklist(_propagator->_journal, _item) && _item._hasBlacklistEntry) { + if (blacklist(_propagator->_journal, *_item) && _item->_hasBlacklistEntry) { // do not error if the item was, and continues to be, blacklisted status = SyncFileItem::FileIgnored; - _item._errorString.prepend(tr("Continue blacklisting:") + " "); + _item->_errorString.prepend(tr("Continue blacklisting:") + " "); } break; case SyncFileItem::Success: case SyncFileItem::Restoration: - if( _item._hasBlacklistEntry ) { + if( _item->_hasBlacklistEntry ) { // wipe blacklist entry. - _propagator->_journal->wipeErrorBlacklistEntry(_item._file); + _propagator->_journal->wipeErrorBlacklistEntry(_item->_file); // remove a blacklist entry in case the file was moved. - if( _item._originalFile != _item._file ) { - _propagator->_journal->wipeErrorBlacklistEntry(_item._originalFile); + if( _item->_originalFile != _item->_file ) { + _propagator->_journal->wipeErrorBlacklistEntry(_item->_originalFile); } } break; @@ -127,9 +127,9 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr break; } - _item._status = status; + _item->_status = status; - emit completed(_item); + emit completed(*_item); emit finished(status); } @@ -143,24 +143,24 @@ bool PropagateItemJob::checkForProblemsWithShared(int httpStatusCode, const QStr { PropagateItemJob *newJob = NULL; - if( httpStatusCode == 403 && _propagator->isInSharedDirectory(_item._file )) { - if( !_item._isDirectory ) { - SyncFileItem downloadItem(_item); - if (downloadItem._instruction == CSYNC_INSTRUCTION_NEW) { + if( httpStatusCode == 403 && _propagator->isInSharedDirectory(_item->_file )) { + if( !_item->_isDirectory ) { + SyncFileItemPtr downloadItem(new SyncFileItem(*_item)); + if (downloadItem->_instruction == CSYNC_INSTRUCTION_NEW) { // don't try to recover pushing new files return false; - } else if (downloadItem._instruction == CSYNC_INSTRUCTION_SYNC) { + } else if (downloadItem->_instruction == CSYNC_INSTRUCTION_SYNC) { // we modified the file locally, jsut create a conflict then - downloadItem._instruction = CSYNC_INSTRUCTION_CONFLICT; + downloadItem->_instruction = CSYNC_INSTRUCTION_CONFLICT; // HACK to avoid continuation: See task #1448: We do not know the _modtime from the // server, at this point, so just set the current one. (rather than the one locally) - downloadItem._modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTime()); + downloadItem->_modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTime()); } else { // the file was removed or renamed, just recover the old one - downloadItem._instruction = CSYNC_INSTRUCTION_SYNC; + downloadItem->_instruction = CSYNC_INSTRUCTION_SYNC; } - downloadItem._direction = SyncFileItem::Down; + downloadItem->_direction = SyncFileItem::Down; #ifdef USE_NEON newJob = new PropagateDownloadFileLegacy(_propagator, downloadItem); #else @@ -169,20 +169,20 @@ bool PropagateItemJob::checkForProblemsWithShared(int httpStatusCode, const QStr } else { // Directories are harder to recover. // But just re-create the directory, next sync will be able to recover the files - SyncFileItem mkdirItem(_item); - mkdirItem._instruction = CSYNC_INSTRUCTION_SYNC; - mkdirItem._direction = SyncFileItem::Down; + SyncFileItemPtr mkdirItem(new SyncFileItem(*_item)); + mkdirItem->_instruction = CSYNC_INSTRUCTION_SYNC; + mkdirItem->_direction = SyncFileItem::Down; newJob = new PropagateLocalMkdir(_propagator, mkdirItem); // Also remove the inodes and fileid from the db so no further renames are tried for // this item. - _propagator->_journal->avoidRenamesOnNextSync(_item._file); + _propagator->_journal->avoidRenamesOnNextSync(_item->_file); _propagator->_anotherSyncNeeded = true; } if( newJob ) { newJob->setRestoreJobMsg(msg); _restoreJob.reset(newJob); - connect(_restoreJob.data(), SIGNAL(completed(SyncFileItem)), - this, SLOT(slotRestoreJobCompleted(SyncFileItem))); + connect(_restoreJob.data(), SIGNAL(completed(const SyncFileItemPtr &)), + this, SLOT(slotRestoreJobCompleted(const SyncFileItemPtr &))); QMetaObject::invokeMethod(newJob, "start"); } return true; @@ -208,25 +208,25 @@ void PropagateItemJob::slotRestoreJobCompleted(const SyncFileItem& item ) // ================================================================================ -PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItem& item) { - switch(item._instruction) { +PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItemPtr &item) { + switch(item->_instruction) { case CSYNC_INSTRUCTION_REMOVE: - if (item._direction == SyncFileItem::Down) return new PropagateLocalRemove(this, item); + if (item->_direction == SyncFileItem::Down) return new PropagateLocalRemove(this, item); else return new PropagateRemoteDelete(this, item); case CSYNC_INSTRUCTION_NEW: - if (item._isDirectory) { - if (item._direction == SyncFileItem::Down) return new PropagateLocalMkdir(this, item); + if (item->_isDirectory) { + if (item->_direction == SyncFileItem::Down) return new PropagateLocalMkdir(this, item); else return new PropagateRemoteMkdir(this, item); } //fall trough case CSYNC_INSTRUCTION_SYNC: case CSYNC_INSTRUCTION_CONFLICT: - if (item._isDirectory) { + if (item->_isDirectory) { // Should we set the mtime? return 0; } #ifdef USE_NEON if (useLegacyJobs()) { - if (item._direction != SyncFileItem::Up) { + if (item->_direction != SyncFileItem::Up) { return new PropagateDownloadFileLegacy(this, item); } else { return new PropagateUploadFileLegacy(this, item); @@ -234,14 +234,14 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItem& item) { } else #endif { - if (item._direction != SyncFileItem::Up) { + if (item->_direction != SyncFileItem::Up) { return new PropagateDownloadFileQNAM(this, item); } else { return new PropagateUploadFileQNAM(this, item); } } case CSYNC_INSTRUCTION_RENAME: - if (item._direction == SyncFileItem::Up) { + if (item->_direction == SyncFileItem::Up) { return new PropagateRemoteMove(this, item); } else { return new PropagateLocalRename(this, item); @@ -269,13 +269,13 @@ void OwncloudPropagator::start(const SyncFileItemVector& items) directories.push(qMakePair(QString(), _rootJob.data())); QVector directoriesToRemove; QString removedDirectory; - foreach(const SyncFileItem &item, items) { + foreach(const SyncFileItemPtr &item, items) { - if (!removedDirectory.isEmpty() && item._file.startsWith(removedDirectory)) { + if (!removedDirectory.isEmpty() && item->_file.startsWith(removedDirectory)) { // this is an item in a directory which is going to be removed. PropagateDirectory *delDirJob = dynamic_cast(directoriesToRemove.last()); - if (item._instruction == CSYNC_INSTRUCTION_REMOVE) { + if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) { //already taken care of. (by the removal of the parent directory) // increase the number of subjobs that would be there. @@ -283,7 +283,7 @@ void OwncloudPropagator::start(const SyncFileItemVector& items) delDirJob->increaseAffectedCount(); } continue; - } else if (item._instruction == CSYNC_INSTRUCTION_NEW && item._isDirectory) { + } else if (item->_instruction == CSYNC_INSTRUCTION_NEW && item->_isDirectory) { // create a new directory within a deleted directory? That can happen if the directory // etag were not fetched properly on the previous sync because the sync was aborted // while uploading this directory (which is now removed). We can ignore it. @@ -291,39 +291,39 @@ void OwncloudPropagator::start(const SyncFileItemVector& items) delDirJob->increaseAffectedCount(); } continue; - } else if (item._instruction == CSYNC_INSTRUCTION_IGNORE) { + } else if (item->_instruction == CSYNC_INSTRUCTION_IGNORE) { continue; } qWarning() << "WARNING: Job within a removed directory? This should not happen!" - << item._file << item._instruction; + << item->_file << item->_instruction; } - while (!item.destination().startsWith(directories.top().first)) { + while (!item->destination().startsWith(directories.top().first)) { directories.pop(); } - if (item._isDirectory) { + if (item->_isDirectory) { PropagateDirectory *dir = new PropagateDirectory(this, item); dir->_firstJob.reset(createJob(item)); - if (item._instruction == CSYNC_INSTRUCTION_REMOVE) { + if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) { //We do the removal of directories at the end, because there might be moves from // this directories that will happen later. directoriesToRemove.append(dir); - removedDirectory = item._file + "/"; + removedDirectory = item->_file + "/"; // We should not update the etag of parent directories of the removed directory // since it would be done before the actual remove (issue #1845) // NOTE: Currently this means that we don't update those etag at all in this sync, // but it should not be a problem, they will be updated in the next sync. for (int i = 0; i < directories.size(); ++i) { - directories[i].second->_item._should_update_etag = false; + directories[i].second->_item->_should_update_etag = false; } } else { PropagateDirectory* currentDirJob = directories.top().second; currentDirJob->append(dir); } - directories.push(qMakePair(item.destination() + "/" , dir)); + directories.push(qMakePair(item->destination() + "/" , dir)); } else if (PropagateItemJob* current = createJob(item)) { directories.top().second->append(current); } @@ -333,8 +333,8 @@ void OwncloudPropagator::start(const SyncFileItemVector& items) _rootJob->append(it); } - connect(_rootJob.data(), SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem))); - connect(_rootJob.data(), SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64))); + connect(_rootJob.data(), SIGNAL(completed(const SyncFileItem &)), this, SIGNAL(completed(const SyncFileItem &))); + connect(_rootJob.data(), SIGNAL(progress(const SyncFileItem &,quint64)), this, SIGNAL(progress(const SyncFileItem &,quint64))); connect(_rootJob.data(), SIGNAL(finished(SyncFileItem::Status)), this, SLOT(emitFinished())); connect(_rootJob.data(), SIGNAL(ready()), this, SLOT(scheduleNextJob()), Qt::QueuedConnection); @@ -616,19 +616,19 @@ void PropagateDirectory::slotSubJobFinished(SyncFileItem::Status status) void PropagateDirectory::finalize() { - if (!_item.isEmpty() && _hasError == SyncFileItem::NoStatus) { - if( !_item._renameTarget.isEmpty() ) { - _item._file = _item._renameTarget; + if (!_item->isEmpty() && _hasError == SyncFileItem::NoStatus) { + if( !_item->_renameTarget.isEmpty() ) { + _item->_file = _item->_renameTarget; } - if (_item._should_update_etag && _item._instruction != CSYNC_INSTRUCTION_REMOVE) { + if (_item->_should_update_etag && _item->_instruction != CSYNC_INSTRUCTION_REMOVE) { if (PropagateRemoteMkdir* mkdir = qobject_cast(_firstJob.data())) { // special case from MKDIR, get the fileId from the job there - if (_item._fileId.isEmpty() && !mkdir->_item._fileId.isEmpty()) { - _item._fileId = mkdir->_item._fileId; + if (_item->_fileId.isEmpty() && !mkdir->_item->_fileId.isEmpty()) { + _item->_fileId = mkdir->_item->_fileId; } } - SyncJournalFileRecord record(_item, _propagator->_localDir + _item._file); + SyncJournalFileRecord record(*_item, _propagator->_localDir + _item->_file); _propagator->_journal->setFileRecord(record); } } @@ -649,9 +649,9 @@ void CleanupPollsJob::start() auto info = _pollInfos.first(); _pollInfos.pop_front(); - SyncFileItem item; - item._file = info._file; - item._modtime = info._modtime; + SyncFileItemPtr item(new SyncFileItem); + item->_file = info._file; + item->_modtime = info._modtime; PollJob *job = new PollJob(_account, info._url, item, _journal, _localPath, this); connect(job, SIGNAL(finishedSignal()), SLOT(slotPollFinished())); job->start(); @@ -661,13 +661,13 @@ void CleanupPollsJob::slotPollFinished() { PollJob *job = qobject_cast(sender()); Q_ASSERT(job); - if (job->_item._status == SyncFileItem::FatalError) { - emit aborted(job->_item._errorString); + if (job->_item->_status == SyncFileItem::FatalError) { + emit aborted(job->_item->_errorString); return; - } else if (job->_item._status != SyncFileItem::Success) { - qDebug() << "There was an error with file " << job->_item._file << job->_item._errorString; + } else if (job->_item->_status != SyncFileItem::Success) { + qDebug() << "There was an error with file " << job->_item->_file << job->_item->_errorString; } else { - _journal->setFileRecord(SyncJournalFileRecord(job->_item, _localPath + job->_item._file)); + _journal->setFileRecord(SyncJournalFileRecord(*job->_item, _localPath + job->_item->_file)); } // Continue with the next entry, or finish start(); diff --git a/src/libsync/owncloudpropagator.h b/src/libsync/owncloudpropagator.h index 860eed27b..add39bed1 100644 --- a/src/libsync/owncloudpropagator.h +++ b/src/libsync/owncloudpropagator.h @@ -125,11 +125,11 @@ protected: * It is displayed in the activity view. */ QString restoreJobMsg() const { - return _item._isRestoration ? _item._errorString : QString(); + return _item->_isRestoration ? _item->_errorString : QString(); } void setRestoreJobMsg( const QString& msg = QString() ) { - _item._isRestoration = true; - _item._errorString = msg; + _item->_isRestoration = true; + _item->_errorString = msg; } protected slots: @@ -139,7 +139,7 @@ private: QScopedPointer _restoreJob; public: - PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItem &item) + PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItemPtr &item) : PropagatorJob(propagator), _item(item) {} bool scheduleNextJob() Q_DECL_OVERRIDE { @@ -151,7 +151,7 @@ public: return true; } - SyncFileItem _item; + SyncFileItemPtr _item; public slots: virtual void start() = 0; @@ -170,13 +170,13 @@ public: // all the sub files or sub directories. QVector _subJobs; - SyncFileItem _item; + SyncFileItemPtr _item; int _current; // index of the current running job int _runningNow; // number of subJob running now SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error - explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItem &item = SyncFileItem()) + explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItemPtr &item = SyncFileItemPtr(new SyncFileItem)) : PropagatorJob(propagator) , _firstJob(0), _item(item), _current(-1), _runningNow(0), _hasError(SyncFileItem::NoStatus) { } @@ -199,7 +199,7 @@ public: } void increaseAffectedCount() { - _firstJob->_item._affectedItems++; + _firstJob->_item->_affectedItems++; } void finalize(); @@ -208,8 +208,8 @@ private slots: bool possiblyRunNextJob(PropagatorJob *next) { if (next->_state == NotYetStarted) { connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection); - connect(next, SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem))); - connect(next, SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64))); + connect(next, SIGNAL(completed(const SyncFileItem &)), this, SIGNAL(completed(const SyncFileItem &))); + connect(next, SIGNAL(progress(const SyncFileItem &,quint64)), this, SIGNAL(progress(const SyncFileItem &,quint64))); connect(next, SIGNAL(ready()), this, SIGNAL(ready())); _runningNow++; } @@ -224,18 +224,18 @@ private slots: class PropagateIgnoreJob : public PropagateItemJob { Q_OBJECT public: - PropagateIgnoreJob(OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateIgnoreJob(OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE { - SyncFileItem::Status status = _item._status; - done(status == SyncFileItem::NoStatus ? SyncFileItem::FileIgnored : status, _item._errorString); + SyncFileItem::Status status = _item->_status; + done(status == SyncFileItem::NoStatus ? SyncFileItem::FileIgnored : status, _item->_errorString); } }; class OwncloudPropagator : public QObject { Q_OBJECT - PropagateItemJob *createJob(const SyncFileItem& item); + PropagateItemJob *createJob(const SyncFileItemPtr& item); QScopedPointer _rootJob; bool useLegacyJobs(); diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index 98a78b45d..f251da39b 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -280,25 +280,25 @@ void PropagateDownloadFileQNAM::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - qDebug() << Q_FUNC_INFO << _item._file << _propagator->_activeJobs; + qDebug() << Q_FUNC_INFO << _item->_file << _propagator->_activeJobs; // do a klaas' case clash check. - if( _propagator->localFileNameClash(_item._file) ) { + if( _propagator->localFileNameClash(_item->_file) ) { done( SyncFileItem::NormalError, tr("File %1 can not be downloaded because of a local file name clash!") - .arg(QDir::toNativeSeparators(_item._file)) ); + .arg(QDir::toNativeSeparators(_item->_file)) ); return; } - emit progress(_item, 0); + emit progress(*_item, 0); QString tmpFileName; QByteArray expectedEtagForResume; - const SyncJournalDb::DownloadInfo progressInfo = _propagator->_journal->getDownloadInfo(_item._file); + const SyncJournalDb::DownloadInfo progressInfo = _propagator->_journal->getDownloadInfo(_item->_file); if (progressInfo._valid) { // if the etag has changed meanwhile, remove the already downloaded part. - if (progressInfo._etag != _item._etag) { + if (progressInfo._etag != _item->_etag) { QFile::remove(_propagator->getFilePath(progressInfo._tmpfile)); - _propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo()); + _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); } else { tmpFileName = progressInfo._tmpfile; expectedEtagForResume = progressInfo._etag; @@ -307,7 +307,7 @@ void PropagateDownloadFileQNAM::start() } if (tmpFileName.isEmpty()) { - tmpFileName = _item._file; + tmpFileName = _item->_file; //add a dot at the begining of the filename to hide the file. int slashPos = tmpFileName.lastIndexOf('/'); tmpFileName.insert(slashPos+1, '.'); @@ -325,10 +325,10 @@ void PropagateDownloadFileQNAM::start() { SyncJournalDb::DownloadInfo pi; - pi._etag = _item._etag; + pi._etag = _item->_etag; pi._tmpfile = tmpFileName; pi._valid = true; - _propagator->_journal->setDownloadInfo(_item._file, pi); + _propagator->_journal->setDownloadInfo(_item->_file, pi); _propagator->_journal->commit("download file start"); } @@ -337,27 +337,27 @@ void PropagateDownloadFileQNAM::start() quint64 startSize = _tmpFile.size(); if (startSize > 0) { - if (startSize == _item._size) { + if (startSize == _item->_size) { qDebug() << "File is already complete, no need to download"; downloadFinished(); return; } } - if (_item._directDownloadUrl.isEmpty()) { + if (_item->_directDownloadUrl.isEmpty()) { // Normal job, download from oC instance _job = new GETFileJob(_propagator->account(), - _propagator->_remoteFolder + _item._file, + _propagator->_remoteFolder + _item->_file, &_tmpFile, headers, expectedEtagForResume, startSize); } else { // We were provided a direct URL, use that one - qDebug() << Q_FUNC_INFO << "directDownloadUrl given for " << _item._file << _item._directDownloadUrl; + qDebug() << Q_FUNC_INFO << "directDownloadUrl given for " << _item->_file << _item->_directDownloadUrl; - if (!_item._directDownloadCookies.isEmpty()) { - headers["Cookie"] = _item._directDownloadCookies.toUtf8(); + if (!_item->_directDownloadCookies.isEmpty()) { + headers["Cookie"] = _item->_directDownloadCookies.toUtf8(); } - QUrl url = QUrl::fromUserInput(_item._directDownloadUrl); + QUrl url = QUrl::fromUserInput(_item->_directDownloadUrl); _job = new GETFileJob(_propagator->account(), url, &_tmpFile, headers, expectedEtagForResume, startSize); @@ -383,11 +383,11 @@ void PropagateDownloadFileQNAM::slotGetFinished() QNetworkReply::NetworkError err = job->reply()->error(); if (err != QNetworkReply::NoError) { - _item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + _item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // If we sent a 'Range' header and get 416 back, we want to retry // without the header. - bool badRangeHeader = job->resumeStart() > 0 && _item._httpErrorCode == 416; + bool badRangeHeader = job->resumeStart() > 0 && _item->_httpErrorCode == 416; if (badRangeHeader) { qDebug() << Q_FUNC_INFO << "server replied 416 to our range request, trying again without"; _propagator->_anotherSyncNeeded = true; @@ -398,13 +398,13 @@ void PropagateDownloadFileQNAM::slotGetFinished() if (_tmpFile.size() == 0 || badRangeHeader) { _tmpFile.close(); _tmpFile.remove(); - _propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo()); + _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); } - if(!_item._directDownloadUrl.isEmpty() && err != QNetworkReply::OperationCanceledError) { + if(!_item->_directDownloadUrl.isEmpty() && err != QNetworkReply::OperationCanceledError) { // If this was with a direct download, retry without direct download - qWarning() << "Direct download of" << _item._directDownloadUrl << "failed. Retrying through owncloud."; - _item._directDownloadUrl.clear(); + qWarning() << "Direct download of" << _item->_directDownloadUrl << "failed. Retrying through owncloud."; + _item->_directDownloadUrl.clear(); start(); return; } @@ -422,7 +422,7 @@ void PropagateDownloadFileQNAM::slotGetFinished() if (status == SyncFileItem::NoStatus) { - status = classifyError(err, _item._httpErrorCode); + status = classifyError(err, _item->_httpErrorCode); } if (badRangeHeader) { // Can't do this in classifyError() because 416 without a @@ -436,15 +436,15 @@ void PropagateDownloadFileQNAM::slotGetFinished() if (!job->etag().isEmpty()) { // The etag will be empty if we used a direct download URL. // (If it was really empty by the server, the GETFileJob will have errored - _item._etag = parseEtag(job->etag()); + _item->_etag = parseEtag(job->etag()); } if (job->lastModified()) { // It is possible that the file was modified on the server since we did the discovery phase // so make sure we have the up-to-date time - _item._modtime = job->lastModified(); + _item->_modtime = job->lastModified(); } - _item._requestDuration = job->duration(); - _item._responseTimeStamp = job->responseTimestamp(); + _item->_requestDuration = job->duration(); + _item->_responseTimeStamp = job->responseTimestamp(); _tmpFile.close(); _tmpFile.flush(); @@ -490,23 +490,23 @@ QString makeConflictFileName(const QString &fn, const QDateTime &dt) void PropagateDownloadFileQNAM::downloadFinished() { - QString fn = _propagator->getFilePath(_item._file); + QString fn = _propagator->getFilePath(_item->_file); // In case of file name clash, report an error // This can happen if another parallel download saved a clashing file. - if (_propagator->localFileNameClash(_item._file)) { + if (_propagator->localFileNameClash(_item->_file)) { done( SyncFileItem::NormalError, tr("File %1 cannot be saved because of a local file name clash!") - .arg(QDir::toNativeSeparators(_item._file)) ); + .arg(QDir::toNativeSeparators(_item->_file)) ); return; } // In case of conflict, make a backup of the old file // Ignore conflicts where both files are binary equal - bool isConflict = _item._instruction == CSYNC_INSTRUCTION_CONFLICT + bool isConflict = _item->_instruction == CSYNC_INSTRUCTION_CONFLICT && !FileSystem::fileEquals(fn, _tmpFile.fileName()); if (isConflict) { QString renameError; - QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime)); + QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item->_modtime)); if (!FileSystem::rename(fn, conflictFileName, &renameError)) { //If the rename fails, don't replace it. done(SyncFileItem::SoftError, renameError); @@ -519,10 +519,10 @@ void PropagateDownloadFileQNAM::downloadFinished() _tmpFile.setPermissions(existingFile.permissions()); } - FileSystem::setModTime(_tmpFile.fileName(), _item._modtime); + FileSystem::setModTime(_tmpFile.fileName(), _item->_modtime); // We need to fetch the time again because some file system such as FAT have a less than a second // Accuracy, and we really need the time from the file system. (#3103) - _item._modtime = FileSystem::getModTime(_tmpFile.fileName()); + _item->_modtime = FileSystem::getModTime(_tmpFile.fileName()); QString error; _propagator->addTouchedFile(fn); @@ -547,10 +547,10 @@ void PropagateDownloadFileQNAM::downloadFinished() // Maybe we downloaded a newer version of the file than we thought we would... // Get up to date information for the journal. - _item._size = FileSystem::getSize(fn); + _item->_size = FileSystem::getSize(fn); - _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, fn)); - _propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo()); + _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, fn)); + _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); _propagator->_journal->commit("download file start2"); done(isConflict ? SyncFileItem::Conflict : SyncFileItem::Success); } @@ -558,7 +558,7 @@ void PropagateDownloadFileQNAM::downloadFinished() void PropagateDownloadFileQNAM::slotDownloadProgress(qint64 received, qint64) { if (!_job) return; - emit progress(_item, received + _job->resumeStart()); + emit progress(*_item, received + _job->resumeStart()); } diff --git a/src/libsync/propagatedownload.h b/src/libsync/propagatedownload.h index 47c60702a..c63aa2ae8 100644 --- a/src/libsync/propagatedownload.h +++ b/src/libsync/propagatedownload.h @@ -106,7 +106,7 @@ class PropagateDownloadFileQNAM : public PropagateItemJob { // QFile *_file; QFile _tmpFile; public: - PropagateDownloadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateDownloadFileQNAM(OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; private slots: diff --git a/src/libsync/propagateremotedelete.cpp b/src/libsync/propagateremotedelete.cpp index 15f1c887b..5f7fc897f 100644 --- a/src/libsync/propagateremotedelete.cpp +++ b/src/libsync/propagateremotedelete.cpp @@ -58,10 +58,10 @@ void PropagateRemoteDelete::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - qDebug() << Q_FUNC_INFO << _item._file; + qDebug() << Q_FUNC_INFO << _item->_file; _job = new DeleteJob(_propagator->account(), - _propagator->_remoteFolder + _item._file, + _propagator->_remoteFolder + _item->_file, this); connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotDeleteJobFinished())); _propagator->_activeJobs ++; @@ -86,22 +86,22 @@ void PropagateRemoteDelete::slotDeleteJobFinished() QNetworkReply::NetworkError err = _job->reply()->error(); const int httpStatus = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - _item._httpErrorCode = httpStatus; + _item->_httpErrorCode = httpStatus; if (err != QNetworkReply::NoError && err != QNetworkReply::ContentNotFoundError) { - if( checkForProblemsWithShared(_item._httpErrorCode, + if( checkForProblemsWithShared(_item->_httpErrorCode, tr("The file has been removed from a read only share. It was restored.")) ) { return; } - SyncFileItem::Status status = classifyError(err, _item._httpErrorCode); + SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode); done(status, _job->errorString()); return; } - _item._requestDuration = _job->duration(); - _item._responseTimeStamp = _job->responseTimestamp(); + _item->_requestDuration = _job->duration(); + _item->_responseTimeStamp = _job->responseTimestamp(); // A 404 reply is also considered a success here: We want to make sure // a file is gone from the server. It not being there in the first place @@ -112,11 +112,11 @@ void PropagateRemoteDelete::slotDeleteJobFinished() // If it is not the case, it might be because of a proxy or gateway intercepting the request, so we must // throw an error. done(SyncFileItem::NormalError, tr("Wrong HTTP code returned by server. Expected 204, but received \"%1 %2\".") - .arg(_item._httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); + .arg(_item->_httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); return; } - _propagator->_journal->deleteFileRecord(_item._originalFile, _item._isDirectory); + _propagator->_journal->deleteFileRecord(_item->_originalFile, _item->_isDirectory); _propagator->_journal->commit("Remote Remove"); done(SyncFileItem::Success); } diff --git a/src/libsync/propagateremotedelete.h b/src/libsync/propagateremotedelete.h index 9a75c9a55..e40289d9a 100644 --- a/src/libsync/propagateremotedelete.h +++ b/src/libsync/propagateremotedelete.h @@ -37,7 +37,7 @@ class PropagateRemoteDelete : public PropagateItemJob { Q_OBJECT QPointer _job; public: - PropagateRemoteDelete (OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateRemoteDelete (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; void abort() Q_DECL_OVERRIDE; diff --git a/src/libsync/propagateremotemkdir.cpp b/src/libsync/propagateremotemkdir.cpp index 1b724dab3..6d97ec1e3 100644 --- a/src/libsync/propagateremotemkdir.cpp +++ b/src/libsync/propagateremotemkdir.cpp @@ -25,10 +25,10 @@ void PropagateRemoteMkdir::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - qDebug() << Q_FUNC_INFO << _item._file; + qDebug() << Q_FUNC_INFO << _item->_file; _job = new MkColJob(_propagator->account(), - _propagator->_remoteFolder + _item._file, + _propagator->_remoteFolder + _item->_file, this); connect(_job, SIGNAL(finished(QNetworkReply::NetworkError)), this, SLOT(slotMkcolJobFinished())); _propagator->_activeJobs++; @@ -52,32 +52,32 @@ void PropagateRemoteMkdir::slotMkcolJobFinished() << (_job->reply()->error() == QNetworkReply::NoError ? QLatin1String("") : _job->reply()->errorString()); QNetworkReply::NetworkError err = _job->reply()->error(); - _item._httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + _item->_httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (_item._httpErrorCode == 405) { + if (_item->_httpErrorCode == 405) { // This happens when the directory already exist. Nothing to do. } else if (err != QNetworkReply::NoError) { - SyncFileItem::Status status = classifyError(err, _item._httpErrorCode); + SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode); auto errorString = _job->reply()->errorString(); if (_job->reply()->hasRawHeader("OC-ErrorString")) { errorString = _job->reply()->rawHeader("OC-ErrorString"); } done(status, errorString); return; - } else if (_item._httpErrorCode != 201) { + } else if (_item->_httpErrorCode != 201) { // Normaly we expect "201 Created" // If it is not the case, it might be because of a proxy or gateway intercepting the request, so we must // throw an error. done(SyncFileItem::NormalError, tr("Wrong HTTP code returned by server. Expected 201, but received \"%1 %2\".") - .arg(_item._httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); + .arg(_item->_httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); return; } - _item._requestDuration = _job->duration(); - _item._responseTimeStamp = _job->responseTimestamp(); - _item._fileId = _job->reply()->rawHeader("OC-FileId"); + _item->_requestDuration = _job->duration(); + _item->_responseTimeStamp = _job->responseTimestamp(); + _item->_fileId = _job->reply()->rawHeader("OC-FileId"); - if (_item._fileId.isEmpty()) { + if (_item->_fileId.isEmpty()) { // Owncloud 7.0.0 and before did not have a header with the file id. // (https://github.com/owncloud/core/issues/9000) // So we must get the file id using a PROPFIND @@ -99,10 +99,10 @@ void PropagateRemoteMkdir::propfindResult(const QVariantMap &result) { _propagator->_activeJobs--; if (result.contains("getetag")) { - _item._etag = result["getetag"].toByteArray(); + _item->_etag = result["getetag"].toByteArray(); } if (result.contains("id")) { - _item._fileId = result["id"].toByteArray(); + _item->_fileId = result["id"].toByteArray(); } success(); } @@ -117,7 +117,7 @@ void PropagateRemoteMkdir::propfindError() void PropagateRemoteMkdir::success() { // save the file id already so we can detect rename or remove - SyncJournalFileRecord record(_item, _propagator->_localDir + _item.destination()); + SyncJournalFileRecord record(*_item, _propagator->_localDir + _item->destination()); _propagator->_journal->setFileRecord(record); done(SyncFileItem::Success); diff --git a/src/libsync/propagateremotemkdir.h b/src/libsync/propagateremotemkdir.h index 01f5623f8..de556b829 100644 --- a/src/libsync/propagateremotemkdir.h +++ b/src/libsync/propagateremotemkdir.h @@ -23,7 +23,7 @@ class PropagateRemoteMkdir : public PropagateItemJob { QPointer _job; friend class PropagateDirectory; // So it can access the _item; public: - PropagateRemoteMkdir (OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateRemoteMkdir (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; void abort() Q_DECL_OVERRIDE; diff --git a/src/libsync/propagateremotemove.cpp b/src/libsync/propagateremotemove.cpp index c6c45f8da..8b9af4eb1 100644 --- a/src/libsync/propagateremotemove.cpp +++ b/src/libsync/propagateremotemove.cpp @@ -64,16 +64,16 @@ void PropagateRemoteMove::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - qDebug() << Q_FUNC_INFO << _item._file << _item._renameTarget; + qDebug() << Q_FUNC_INFO << _item->_file << _item->_renameTarget; - QString targetFile(_propagator->getFilePath(_item._renameTarget)); + QString targetFile(_propagator->getFilePath(_item->_renameTarget)); - if (_item._file == _item._renameTarget) { + if (_item->_file == _item->_renameTarget) { // The parents has been renamed already so there is nothing more to do. finalize(); return; } - if (_item._file == QLatin1String("Shared") ) { + if (_item->_file == QLatin1String("Shared") ) { // Before owncloud 7, there was no permissions system. At the time all the shared files were // in a directory called "Shared" and were not supposed to be moved, otherwise bad things happens @@ -93,8 +93,8 @@ void PropagateRemoteMove::start() } _job = new MoveJob(_propagator->account(), - _propagator->_remoteFolder + _item._file, - _propagator->_remoteDir + _item._renameTarget, + _propagator->_remoteFolder + _item->_file, + _propagator->_remoteDir + _item->_renameTarget, this); connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotMoveJobFinished())); _propagator->_activeJobs++; @@ -119,29 +119,29 @@ void PropagateRemoteMove::slotMoveJobFinished() << (_job->reply()->error() == QNetworkReply::NoError ? QLatin1String("") : _job->reply()->errorString()); QNetworkReply::NetworkError err = _job->reply()->error(); - _item._httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + _item->_httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (err != QNetworkReply::NoError) { - if( checkForProblemsWithShared(_item._httpErrorCode, + if( checkForProblemsWithShared(_item->_httpErrorCode, tr("The file was renamed but is part of a read only share. The original file was restored."))) { return; } - SyncFileItem::Status status = classifyError(err, _item._httpErrorCode); + SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode); done(status, _job->errorString()); return; } - _item._requestDuration = _job->duration(); - _item._responseTimeStamp = _job->responseTimestamp(); + _item->_requestDuration = _job->duration(); + _item->_responseTimeStamp = _job->responseTimestamp(); - if (_item._httpErrorCode != 201 ) { + if (_item->_httpErrorCode != 201 ) { // Normaly we expect "201 Created" // If it is not the case, it might be because of a proxy or gateway intercepting the request, so we must // throw an error. done(SyncFileItem::NormalError, tr("Wrong HTTP code returned by server. Expected 201, but received \"%1 %2\".") - .arg(_item._httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); + .arg(_item->_httpErrorCode).arg(_job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())); return; } @@ -151,9 +151,9 @@ void PropagateRemoteMove::slotMoveJobFinished() void PropagateRemoteMove::finalize() { - _propagator->_journal->deleteFileRecord(_item._originalFile); - SyncJournalFileRecord record(_item, _propagator->getFilePath(_item._renameTarget)); - record._path = _item._renameTarget; + _propagator->_journal->deleteFileRecord(_item->_originalFile); + SyncJournalFileRecord record(*_item, _propagator->getFilePath(_item->_renameTarget)); + record._path = _item->_renameTarget; _propagator->_journal->setFileRecord(record); _propagator->_journal->commit("Remote Rename"); diff --git a/src/libsync/propagateremotemove.h b/src/libsync/propagateremotemove.h index dad7d75a6..741b9a457 100644 --- a/src/libsync/propagateremotemove.h +++ b/src/libsync/propagateremotemove.h @@ -39,7 +39,7 @@ class PropagateRemoteMove : public PropagateItemJob { Q_OBJECT QPointer _job; public: - PropagateRemoteMove (OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateRemoteMove (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; void abort() Q_DECL_OVERRIDE; diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index ce112c9b5..cfe57adf1 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -110,19 +110,19 @@ bool PollJob::finished() { QNetworkReply::NetworkError err = reply()->error(); if (err != QNetworkReply::NoError) { - _item._httpErrorCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - _item._status = classifyError(err, _item._httpErrorCode); - _item._errorString = reply()->errorString(); + _item->_httpErrorCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + _item->_status = classifyError(err, _item->_httpErrorCode); + _item->_errorString = reply()->errorString(); if (reply()->hasRawHeader("OC-ErrorString")) { - _item._errorString = reply()->rawHeader("OC-ErrorString"); + _item->_errorString = reply()->rawHeader("OC-ErrorString"); } - if (_item._status == SyncFileItem::FatalError || _item._httpErrorCode >= 400) { - if (_item._status != SyncFileItem::FatalError - && _item._httpErrorCode != 503) { + if (_item->_status == SyncFileItem::FatalError || _item->_httpErrorCode >= 400) { + if (_item->_status != SyncFileItem::FatalError + && _item->_httpErrorCode != 503) { SyncJournalDb::PollInfo info; - info._file = _item._file; + info._file = _item->_file; // no info._url removes it from the database _journal->setPollInfo(info); _journal->commit("remove poll info"); @@ -140,8 +140,8 @@ bool PollJob::finished() qDebug() << Q_FUNC_INFO << ">" << jsonData << "<" << reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QVariantMap status = QtJson::parse(QString::fromUtf8(jsonData), ok).toMap(); if (!ok || status.isEmpty()) { - _item._errorString = tr("Invalid JSON reply from the poll URL"); - _item._status = SyncFileItem::NormalError; + _item->_errorString = tr("Invalid JSON reply from the poll URL"); + _item->_status = SyncFileItem::NormalError; emit finishedSignal(); return true; } @@ -151,14 +151,14 @@ bool PollJob::finished() return false; } - _item._errorString = status["error"].toString(); - _item._status = _item._errorString.isEmpty() ? SyncFileItem::Success : SyncFileItem::NormalError; - _item._fileId = status["fileid"].toByteArray(); - _item._etag = status["etag"].toByteArray(); - _item._responseTimeStamp = responseTimestamp(); + _item->_errorString = status["error"].toString(); + _item->_status = _item->_errorString.isEmpty() ? SyncFileItem::Success : SyncFileItem::NormalError; + _item->_fileId = status["fileid"].toByteArray(); + _item->_etag = status["etag"].toByteArray(); + _item->_responseTimeStamp = responseTimestamp(); SyncJournalDb::PollInfo info; - info._file = _item._file; + info._file = _item->_file; // no info._url removes it from the database _journal->setPollInfo(info); _journal->commit("remove poll info"); @@ -174,7 +174,7 @@ void PropagateUploadFileQNAM::start() return; } - const QString fullFilePath(_propagator->getFilePath(_item._file)); + const QString fullFilePath(_propagator->getFilePath(_item->_file)); if (!FileSystem::fileExists(fullFilePath)) { done(SyncFileItem::SoftError, tr("File Removed")); @@ -182,14 +182,14 @@ void PropagateUploadFileQNAM::start() } // Update the mtime and size, it might have changed since discovery. - _item._modtime = FileSystem::getModTime(fullFilePath); + _item->_modtime = FileSystem::getModTime(fullFilePath); quint64 fileSize = FileSystem::getSize(fullFilePath); - _item._size = fileSize; + _item->_size = fileSize; // But skip the file if the mtime is too close to 'now'! // That usually indicates a file that is still being changed // or not yet fully copied to the destination. - if (fileIsStillChanging(_item)) { + if (fileIsStillChanging(*_item)) { _propagator->_anotherSyncNeeded = true; done(SyncFileItem::SoftError, tr("Local file changed during sync.")); return; @@ -197,20 +197,20 @@ void PropagateUploadFileQNAM::start() _chunkCount = std::ceil(fileSize/double(chunkSize())); _startChunk = 0; - _transferId = qrand() ^ _item._modtime ^ (_item._size << 16); + _transferId = qrand() ^ _item->_modtime ^ (_item->_size << 16); - const SyncJournalDb::UploadInfo progressInfo = _propagator->_journal->getUploadInfo(_item._file); + const SyncJournalDb::UploadInfo progressInfo = _propagator->_journal->getUploadInfo(_item->_file); - if (progressInfo._valid && Utility::qDateTimeToTime_t(progressInfo._modtime) == _item._modtime ) { + if (progressInfo._valid && Utility::qDateTimeToTime_t(progressInfo._modtime) == _item->_modtime ) { _startChunk = progressInfo._chunk; _transferId = progressInfo._transferid; - qDebug() << Q_FUNC_INFO << _item._file << ": Resuming from chunk " << _startChunk; + qDebug() << Q_FUNC_INFO << _item->_file << ": Resuming from chunk " << _startChunk; } _currentChunk = 0; _duration.start(); - emit progress(_item, 0); + emit progress(*_item, 0); this->startNextChunk(); } @@ -362,22 +362,22 @@ void PropagateUploadFileQNAM::startNextChunk() // is sent last. return; } - quint64 fileSize = _item._size; + quint64 fileSize = _item->_size; QMap headers; headers["OC-Total-Length"] = QByteArray::number(fileSize); headers["OC-Async"] = "1"; headers["OC-Chunk-Size"]= QByteArray::number(quint64(chunkSize())); headers["Content-Type"] = "application/octet-stream"; - headers["X-OC-Mtime"] = QByteArray::number(qint64(_item._modtime)); - if (!_item._etag.isEmpty() && _item._etag != "empty_etag" && - _item._instruction != CSYNC_INSTRUCTION_NEW // On new files never send a If-Match + headers["X-OC-Mtime"] = QByteArray::number(qint64(_item->_modtime)); + if (!_item->_etag.isEmpty() && _item->_etag != "empty_etag" && + _item->_instruction != CSYNC_INSTRUCTION_NEW // On new files never send a If-Match ) { // We add quotes because the owncloud server always add quotes around the etag, and // csync_owncloud.c's owncloud_file_id always strip the quotes. - headers["If-Match"] = '"' + _item._etag + '"'; + headers["If-Match"] = '"' + _item->_etag + '"'; } - QString path = _item._file; + QString path = _item->_file; UploadDevice *device = new UploadDevice(&_propagator->_bandwidthManager); qint64 chunkStart = 0; @@ -400,7 +400,7 @@ void PropagateUploadFileQNAM::startNextChunk() } } - if (! device->prepareAndOpen(_propagator->getFilePath(_item._file), chunkStart, currentChunkSize)) { + if (! device->prepareAndOpen(_propagator->getFilePath(_item->_file), chunkStart, currentChunkSize)) { qDebug() << "ERR: Could not prepare upload device: " << device->errorString(); // Soft error because this is likely caused by the user modifying his files while syncing abortWithError( SyncFileItem::SoftError, device->errorString() ); @@ -472,8 +472,8 @@ void PropagateUploadFileQNAM::slotPutFinished() QNetworkReply::NetworkError err = job->reply()->error(); if (err != QNetworkReply::NoError) { - _item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if(checkForProblemsWithShared(_item._httpErrorCode, + _item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if(checkForProblemsWithShared(_item->_httpErrorCode, tr("The file was edited locally but is part of a read only share. " "It is restored and your edit is in the conflict file."))) { return; @@ -491,20 +491,20 @@ void PropagateUploadFileQNAM::slotPutFinished() errorString = job->reply()->rawHeader("OC-ErrorString"); } - if (_item._httpErrorCode == 412) { + if (_item->_httpErrorCode == 412) { // Precondition Failed: Maybe the bad etag is in the database, we need to clear the // parent folder etag so we won't read from DB next sync. - _propagator->_journal->avoidReadFromDbOnNextSync(_item._file); + _propagator->_journal->avoidReadFromDbOnNextSync(_item->_file); _propagator->_anotherSyncNeeded = true; } - abortWithError(classifyError(err, _item._httpErrorCode), errorString); + abortWithError(classifyError(err, _item->_httpErrorCode), errorString); return; } - _item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + _item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // The server needs some time to process the request and provide with a poll URL - if (_item._httpErrorCode == 202) { + if (_item->_httpErrorCode == 202) { _finished = true; QString path = QString::fromUtf8(job->reply()->rawHeader("OC-Finish-Poll")); if (path.isEmpty()) { @@ -528,7 +528,7 @@ void PropagateUploadFileQNAM::slotPutFinished() bool finished = etag.length() > 0; // Check if the file still exists - const QString fullFilePath(_propagator->getFilePath(_item._file)); + const QString fullFilePath(_propagator->getFilePath(_item->_file)); if( !FileSystem::fileExists(fullFilePath) ) { if (!finished) { abortWithError(SyncFileItem::SoftError, tr("The local file was removed during sync.")); @@ -541,11 +541,11 @@ void PropagateUploadFileQNAM::slotPutFinished() // compare expected and real modification time of the file and size const time_t new_mtime = FileSystem::getModTime(fullFilePath); const quint64 new_size = static_cast(FileSystem::getSize(fullFilePath)); - QFileInfo fi(_propagator->getFilePath(_item._file)); - if (new_mtime != _item._modtime || new_size != _item._size) { + QFileInfo fi(_propagator->getFilePath(_item->_file)); + if (new_mtime != _item->_modtime || new_size != _item->_size) { qDebug() << "The local file has changed during upload:" - << "mtime: " << _item._modtime << "<->" << new_mtime - << ", size: " << _item._size << "<->" << new_size + << "mtime: " << _item->_modtime << "<->" << new_mtime + << ", size: " << _item->_size << "<->" << new_size << ", QFileInfo: " << Utility::qDateTimeToTime_t(fi.lastModified()) << fi.lastModified(); _propagator->_anotherSyncNeeded = true; if( !finished ) { @@ -577,8 +577,8 @@ void PropagateUploadFileQNAM::slotPutFinished() } pi._chunk = (currentChunk + _startChunk + 1) % _chunkCount ; // next chunk to start with pi._transferid = _transferId; - pi._modtime = Utility::qDateTimeFromTime_t(_item._modtime); - _propagator->_journal->setUploadInfo(_item._file, pi); + pi._modtime = Utility::qDateTimeFromTime_t(_item->_modtime); + _propagator->_journal->setUploadInfo(_item->_file, pi); _propagator->_journal->commit("Upload info"); startNextChunk(); return; @@ -589,15 +589,15 @@ void PropagateUploadFileQNAM::slotPutFinished() // the file id should only be empty for new files up- or downloaded QByteArray fid = job->reply()->rawHeader("OC-FileID"); if( !fid.isEmpty() ) { - if( !_item._fileId.isEmpty() && _item._fileId != fid ) { - qDebug() << "WARN: File ID changed!" << _item._fileId << fid; + if( !_item->_fileId.isEmpty() && _item->_fileId != fid ) { + qDebug() << "WARN: File ID changed!" << _item->_fileId << fid; } - _item._fileId = fid; + _item->_fileId = fid; } - _item._etag = etag; + _item->_etag = etag; - _item._responseTimeStamp = job->responseTimestamp(); + _item->_responseTimeStamp = job->responseTimestamp(); if (job->reply()->rawHeader("X-OC-MTime") != "accepted") { // X-OC-MTime is supported since owncloud 5.0. But not when chunking. @@ -612,21 +612,21 @@ void PropagateUploadFileQNAM::slotPutFinished() // Well, the mtime was not set #endif } - finalize(_item); + finalize(*_item); } void PropagateUploadFileQNAM::finalize(const SyncFileItem ©) { // Normally, copy == _item, but when it comes from the UpdateMTimeAndETagJob, we need to do // some updates - _item._etag = copy._etag; - _item._fileId = copy._fileId; + _item->_etag = copy._etag; + _item->_fileId = copy._fileId; - _item._requestDuration = _duration.elapsed(); + _item->_requestDuration = _duration.elapsed(); - _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, _propagator->getFilePath(_item._file))); + _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, _propagator->getFilePath(_item->_file))); // Remove from the progress database: - _propagator->_journal->setUploadInfo(_item._file, SyncJournalDb::UploadInfo()); + _propagator->_journal->setUploadInfo(_item->_file, SyncJournalDb::UploadInfo()); _propagator->_journal->commit("upload file start"); _finished = true; @@ -658,7 +658,7 @@ void PropagateUploadFileQNAM::slotUploadProgress(qint64 sent, qint64 total) // sender() is the only current job, no need to look at the byteWritten properties amount += sent; } - emit progress(_item, amount); + emit progress(*_item, amount); } void PropagateUploadFileQNAM::startPollJob(const QString& path) @@ -667,9 +667,9 @@ void PropagateUploadFileQNAM::startPollJob(const QString& path) _propagator->_journal, _propagator->_localDir, this); connect(job, SIGNAL(finishedSignal()), SLOT(slotPollFinished())); SyncJournalDb::PollInfo info; - info._file = _item._file; + info._file = _item->_file; info._url = path; - info._modtime = _item._modtime; + info._modtime = _item->_modtime; _propagator->_journal->setPollInfo(info); _propagator->_journal->commit("add poll info"); _propagator->_activeJobs++; @@ -683,13 +683,13 @@ void PropagateUploadFileQNAM::slotPollFinished() _propagator->_activeJobs--; - if (job->_item._status != SyncFileItem::Success) { + if (job->_item->_status != SyncFileItem::Success) { _finished = true; - done(job->_item._status, job->_item._errorString); + done(job->_item->_status, job->_item->_errorString); return; } - finalize(job->_item); + finalize(*job->_item); } void PropagateUploadFileQNAM::slotJobDestroyed(QObject* job) @@ -701,7 +701,7 @@ void PropagateUploadFileQNAM::abort() { foreach(auto *job, _jobs) { if (job->reply()) { - qDebug() << Q_FUNC_INFO << job << this->_item._file; + qDebug() << Q_FUNC_INFO << job << this->_item->_file; job->reply()->abort(); } } diff --git a/src/libsync/propagateupload.h b/src/libsync/propagateupload.h index 3e345fa23..99555958a 100644 --- a/src/libsync/propagateupload.h +++ b/src/libsync/propagateupload.h @@ -108,9 +108,9 @@ class PollJob : public AbstractNetworkJob { SyncJournalDb *_journal; QString _localPath; public: - SyncFileItem _item; + SyncFileItemPtr _item; // Takes ownership of the device - explicit PollJob(AccountPtr account, const QString &path, const SyncFileItem &item, + explicit PollJob(AccountPtr account, const QString &path, const SyncFileItemPtr &item, SyncJournalDb *journal, const QString &localPath, QObject *parent) : AbstractNetworkJob(account, path, parent), _journal(journal), _localPath(localPath), _item(item) {} @@ -149,7 +149,7 @@ class PropagateUploadFileQNAM : public PropagateItemJob { QVector _jobs; /// network jobs that are currently in transit bool _finished; // Tells that all the jobs have been finished public: - PropagateUploadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item) + PropagateUploadFileQNAM(OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item), _startChunk(0), _currentChunk(0), _chunkCount(0), _transferId(0), _finished(false) {} void start() Q_DECL_OVERRIDE; private slots: diff --git a/src/libsync/propagator_legacy.cpp b/src/libsync/propagator_legacy.cpp index b9dc7e8cd..613935b56 100644 --- a/src/libsync/propagator_legacy.cpp +++ b/src/libsync/propagator_legacy.cpp @@ -186,7 +186,7 @@ void PropagateUploadFileLegacy::start() _item._modtime = trans->oc_header_modtime; } - emit progress(_item, 0); + emit progress(*_item, 0); if (progressInfo._valid) { if (Utility::qDateTimeToTime_t(progressInfo._modtime) == _item._modtime) { @@ -267,7 +267,7 @@ void PropagateUploadFileLegacy::start() return; } - _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, _propagator->getFilePath(_item._file))); + _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, _propagator->getFilePath(_item._file))); // Remove from the progress database: _propagator->_journal->setUploadInfo(_item._file, SyncJournalDb::UploadInfo()); _propagator->_journal->commit("upload file start"); @@ -569,7 +569,7 @@ void PropagateDownloadFileLegacy::start() return; } - emit progress(_item, 0); + emit progress(*_item, 0); QString tmpFileName; const SyncJournalDb::DownloadInfo progressInfo = _propagator->_journal->getDownloadInfo(_item._file); @@ -721,7 +721,7 @@ void PropagateDownloadFileLegacy::start() FileSystem::setModTime(fn, _item._modtime); - _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, fn)); + _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, fn)); _propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo()); _propagator->_journal->commit("download file start2"); done(isConflict ? SyncFileItem::Conflict : SyncFileItem::Success); diff --git a/src/libsync/propagatorjobs.cpp b/src/libsync/propagatorjobs.cpp index 9f952576a..2b7318a2c 100644 --- a/src/libsync/propagatorjobs.cpp +++ b/src/libsync/propagatorjobs.cpp @@ -81,14 +81,14 @@ void PropagateLocalRemove::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - QString filename = _propagator->_localDir + _item._file; - if( _propagator->localFileNameClash(_item._file)) { + QString filename = _propagator->_localDir + _item->_file; + if( _propagator->localFileNameClash(_item->_file)) { done(SyncFileItem::NormalError, tr("Could not remove %1 because of a local file name clash") .arg(QDir::toNativeSeparators(filename))); return; } - if (_item._isDirectory) { + if (_item->_isDirectory) { QString error; if (QDir(filename).exists() && !removeRecursively(filename, error)) { done(SyncFileItem::NormalError, error); @@ -101,8 +101,8 @@ void PropagateLocalRemove::start() return; } } - emit progress(_item, 0); - _propagator->_journal->deleteFileRecord(_item._originalFile, _item._isDirectory); + emit progress(*_item, 0); + _propagator->_journal->deleteFileRecord(_item->_originalFile, _item->_isDirectory); _propagator->_journal->commit("Local remove"); done(SyncFileItem::Success); } @@ -112,15 +112,15 @@ void PropagateLocalMkdir::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - QDir newDir(_propagator->_localDir + _item._file); + QDir newDir(_propagator->_localDir + _item->_file); QString newDirStr = QDir::toNativeSeparators(newDir.path()); - if( Utility::fsCasePreserving() && _propagator->localFileNameClash(_item._file ) ) { + if( Utility::fsCasePreserving() && _propagator->localFileNameClash(_item->_file ) ) { qDebug() << "WARN: new directory to create locally already exists!"; done( SyncFileItem::NormalError, tr("Attention, possible case sensitivity clash with %1").arg(newDirStr) ); return; } QDir localDir(_propagator->_localDir); - if (!localDir.mkpath(_item._file)) { + if (!localDir.mkpath(_item->_file)) { done( SyncFileItem::NormalError, tr("could not create directory %1").arg(newDirStr) ); return; } @@ -132,24 +132,24 @@ void PropagateLocalRename::start() if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; - QString existingFile = _propagator->getFilePath(_item._file); - QString targetFile = _propagator->getFilePath(_item._renameTarget); + QString existingFile = _propagator->getFilePath(_item->_file); + QString targetFile = _propagator->getFilePath(_item->_renameTarget); - // if the file is a file underneath a moved dir, the _item.file is equal - // to _item.renameTarget and the file is not moved as a result. - if (_item._file != _item._renameTarget) { - emit progress(_item, 0); + // if the file is a file underneath a moved dir, the _item->file is equal + // to _item->renameTarget and the file is not moved as a result. + if (_item->_file != _item->_renameTarget) { + emit progress(*_item, 0); qDebug() << "MOVE " << existingFile << " => " << targetFile; - if (QString::compare(_item._file, _item._renameTarget, Qt::CaseInsensitive) != 0 - && _propagator->localFileNameClash(_item._renameTarget)) { + if (QString::compare(_item->_file, _item->_renameTarget, Qt::CaseInsensitive) != 0 + && _propagator->localFileNameClash(_item->_renameTarget)) { // Only use localFileNameClash for the destination if we know that the source was not // the one conflicting (renaming A.txt -> a.txt is OK) // Fixme: the file that is the reason for the clash could be named here, // it would have to come out the localFileNameClash function done(SyncFileItem::NormalError, tr( "File %1 can not be renamed to %2 because of a local file name clash") - .arg(QDir::toNativeSeparators(_item._file)).arg(QDir::toNativeSeparators(_item._renameTarget)) ); + .arg(QDir::toNativeSeparators(_item->_file)).arg(QDir::toNativeSeparators(_item->_renameTarget)) ); return; } @@ -162,15 +162,15 @@ void PropagateLocalRename::start() } } - _propagator->_journal->deleteFileRecord(_item._originalFile); + _propagator->_journal->deleteFileRecord(_item->_originalFile); // store the rename file name in the item. - _item._file = _item._renameTarget; + _item->_file = _item->_renameTarget; - SyncJournalFileRecord record(_item, targetFile); - record._path = _item._renameTarget; + SyncJournalFileRecord record(*_item, targetFile); + record._path = _item->_renameTarget; - if (!_item._isDirectory) { // Directory are saved at the end + if (!_item->_isDirectory) { // Directory are saved at the end _propagator->_journal->setFileRecord(record); } _propagator->_journal->commit("localRename"); diff --git a/src/libsync/propagatorjobs.h b/src/libsync/propagatorjobs.h index 99343fe9b..06b3c23be 100644 --- a/src/libsync/propagatorjobs.h +++ b/src/libsync/propagatorjobs.h @@ -24,20 +24,20 @@ namespace OCC { class PropagateLocalRemove : public PropagateItemJob { Q_OBJECT public: - PropagateLocalRemove (OwncloudPropagator* propagator,const SyncFileItem& item) : PropagateItemJob(propagator, item) {} + PropagateLocalRemove (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; }; class PropagateLocalMkdir : public PropagateItemJob { Q_OBJECT public: - PropagateLocalMkdir (OwncloudPropagator* propagator,const SyncFileItem& item) : PropagateItemJob(propagator, item) {} + PropagateLocalMkdir (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; }; class PropagateLocalRename : public PropagateItemJob { Q_OBJECT public: - PropagateLocalRename (OwncloudPropagator* propagator,const SyncFileItem& item) : PropagateItemJob(propagator, item) {} + PropagateLocalRename (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {} void start() Q_DECL_OVERRIDE; JobParallelism parallelism() Q_DECL_OVERRIDE { return WaitForFinishedInParentDirectory; } }; diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 81d087297..ea46e83ac 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -173,45 +173,45 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err) } -bool SyncEngine::checkErrorBlacklisting( SyncFileItem *item ) +bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item ) { if( !_journal ) { qWarning() << "Journal is undefined!"; return false; } - SyncJournalErrorBlacklistRecord entry = _journal->errorBlacklistEntry(item->_file); - item->_hasBlacklistEntry = false; + SyncJournalErrorBlacklistRecord entry = _journal->errorBlacklistEntry(item._file); + item._hasBlacklistEntry = false; if( !entry.isValid() ) { return false; } - item->_hasBlacklistEntry = true; + item._hasBlacklistEntry = true; // If duration has expired, it's not blacklisted anymore time_t now = Utility::qDateTimeToTime_t(QDateTime::currentDateTime()); if( now > entry._lastTryTime + entry._ignoreDuration ) { - qDebug() << "blacklist entry for " << item->_file << " has expired!"; + qDebug() << "blacklist entry for " << item._file << " has expired!"; return false; } // If the file has changed locally or on the server, the blacklist // entry no longer applies - if( item->_direction == SyncFileItem::Up ) { // check the modtime - if(item->_modtime == 0 || entry._lastTryModtime == 0) { + if( item._direction == SyncFileItem::Up ) { // check the modtime + if(item._modtime == 0 || entry._lastTryModtime == 0) { return false; - } else if( item->_modtime != entry._lastTryModtime ) { - qDebug() << item->_file << " is blacklisted, but has changed mtime!"; + } else if( item._modtime != entry._lastTryModtime ) { + qDebug() << item._file << " is blacklisted, but has changed mtime!"; return false; } - } else if( item->_direction == SyncFileItem::Down ) { + } else if( item._direction == SyncFileItem::Down ) { // download, check the etag. - if( item->_etag.isEmpty() || entry._lastTryEtag.isEmpty() ) { - qDebug() << item->_file << "one ETag is empty, no blacklisting"; + if( item._etag.isEmpty() || entry._lastTryEtag.isEmpty() ) { + qDebug() << item._file << "one ETag is empty, no blacklisting"; return false; - } else if( item->_etag != entry._lastTryEtag ) { - qDebug() << item->_file << " is blacklisted, but has changed etag!"; + } else if( item._etag != entry._lastTryEtag ) { + qDebug() << item._file << " is blacklisted, but has changed etag!"; return false; } } @@ -219,9 +219,9 @@ bool SyncEngine::checkErrorBlacklisting( SyncFileItem *item ) qDebug() << "Item is on blacklist: " << entry._file << "retries:" << entry._retryCount << "for another" << (entry._lastTryTime + entry._ignoreDuration - now) << "s"; - item->_instruction = CSYNC_INSTRUCTION_ERROR; - item->_status = SyncFileItem::FileIgnored; - item->_errorString = tr("The item is not synced because of previous errors: %1").arg(entry._errorString); + item._instruction = CSYNC_INSTRUCTION_ERROR; + item._status = SyncFileItem::FileIgnored; + item._errorString = tr("The item is not synced because of previous errors: %1").arg(entry._errorString); return true; } @@ -230,11 +230,11 @@ void SyncEngine::deleteStaleDownloadInfos() { // Find all downloadinfo paths that we want to preserve. QSet download_file_paths; - foreach(const SyncFileItem& it, _syncedItems) { - if (it._direction == SyncFileItem::Down - && it._type == SyncFileItem::File) + foreach(const SyncFileItemPtr &it, _syncedItems) { + if (it->_direction == SyncFileItem::Down + && it->_type == SyncFileItem::File) { - download_file_paths.insert(it._file); + download_file_paths.insert(it->_file); } } @@ -252,11 +252,11 @@ void SyncEngine::deleteStaleUploadInfos() { // Find all blacklisted paths that we want to preserve. QSet upload_file_paths; - foreach(const SyncFileItem& it, _syncedItems) { - if (it._direction == SyncFileItem::Up - && it._type == SyncFileItem::File) + foreach(const SyncFileItemPtr &it, _syncedItems) { + if (it->_direction == SyncFileItem::Up + && it->_type == SyncFileItem::File) { - upload_file_paths.insert(it._file); + upload_file_paths.insert(it->_file); } } @@ -268,9 +268,9 @@ void SyncEngine::deleteStaleErrorBlacklistEntries() { // Find all blacklisted paths that we want to preserve. QSet blacklist_file_paths; - foreach(const SyncFileItem& it, _syncedItems) { - if (it._hasBlacklistEntry) - blacklist_file_paths.insert(it._file); + foreach(const SyncFileItemPtr &it, _syncedItems) { + if (it->_hasBlacklistEntry) + blacklist_file_paths.insert(it->_file); } // Delete from journal. @@ -313,113 +313,116 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) } } - // Gets a default-contructed SyncFileItem or the one from the first walk (=local walk) - SyncFileItem item = _syncItemMap.value(key); - if (item._file.isEmpty() || instruction == CSYNC_INSTRUCTION_RENAME) { - item._file = fileUtf8; + // Gets a default-contructed SyncFileItemPtr or the one from the first walk (=local walk) + SyncFileItemPtr item = _syncItemMap.value(key); + if (!item) + item = SyncFileItemPtr(new SyncFileItem); + + if (item->_file.isEmpty() || instruction == CSYNC_INSTRUCTION_RENAME) { + item->_file = fileUtf8; } - item._originalFile = item._file; + item->_originalFile = item->_file; - if (item._instruction == CSYNC_INSTRUCTION_NONE - || (item._instruction == CSYNC_INSTRUCTION_IGNORE && instruction != CSYNC_INSTRUCTION_NONE)) { - item._instruction = instruction; - item._modtime = file->modtime; + if (item->_instruction == CSYNC_INSTRUCTION_NONE + || (item->_instruction == CSYNC_INSTRUCTION_IGNORE && instruction != CSYNC_INSTRUCTION_NONE)) { + item->_instruction = instruction; + item->_modtime = file->modtime; } else { if (instruction != CSYNC_INSTRUCTION_NONE) { - qDebug() << "ERROR: Instruction" << item._instruction << "vs" << instruction << "for" << fileUtf8; + qDebug() << "ERROR: Instruction" << item->_instruction << "vs" << instruction << "for" << fileUtf8; Q_ASSERT(!"Instructions are both unequal NONE"); return -1; } } if (file->file_id && strlen(file->file_id) > 0) { - item._fileId = file->file_id; + item->_fileId = file->file_id; } if (file->directDownloadUrl) { - item._directDownloadUrl = QString::fromUtf8( file->directDownloadUrl ); + item->_directDownloadUrl = QString::fromUtf8( file->directDownloadUrl ); } if (file->directDownloadCookies) { - item._directDownloadCookies = QString::fromUtf8( file->directDownloadCookies ); + item->_directDownloadCookies = QString::fromUtf8( file->directDownloadCookies ); } if (file->remotePerm && file->remotePerm[0]) { - item._remotePerm = QByteArray(file->remotePerm); + item->_remotePerm = QByteArray(file->remotePerm); } - item._should_update_etag = item._should_update_etag || file->should_update_etag; + item->_should_update_etag = item->_should_update_etag || file->should_update_etag; // record the seen files to be able to clean the journal later - _seenFiles.insert(item._file); + _seenFiles.insert(item->_file); if (!renameTarget.isEmpty()) { // Yes, this record both the rename renameTarget and the original so we keep both in case of a rename _seenFiles.insert(renameTarget); } if (remote && file->remotePerm && file->remotePerm[0]) { - _remotePerms[item._file] = file->remotePerm; + _remotePerms[item->_file] = file->remotePerm; } switch(file->error_status) { case CSYNC_STATUS_OK: break; case CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK: - item._errorString = tr("Symbolic links are not supported in syncing."); + item->_errorString = tr("Symbolic links are not supported in syncing."); break; case CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK: - item._errorString = tr("Hard links are not supported in syncing."); + item->_errorString = tr("Hard links are not supported in syncing."); break; case CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST: - item._errorString = tr("File is listed on the ignore list."); + item->_errorString = tr("File is listed on the ignore list."); break; case CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS: - item._errorString = tr("File contains invalid characters that can not be synced cross platform."); + item->_errorString = tr("File contains invalid characters that can not be synced cross platform."); break; case CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME: - item._errorString = tr("Filename is too long."); + item->_errorString = tr("Filename is too long."); break; case CYSNC_STATUS_FILE_LOCKED_OR_OPEN: - item._errorString = QLatin1String("File locked"); // don't translate, internal use! + item->_errorString = QLatin1String("File locked"); // don't translate, internal use! break; case CSYNC_STATUS_SERVICE_UNAVAILABLE: - item._errorString = QLatin1String("Server temporarily unavailable."); + item->_errorString = QLatin1String("Server temporarily unavailable."); break; case CSYNC_STATUS_STORAGE_UNAVAILABLE: - item._errorString = QLatin1String("Directory temporarily not available on server."); - item._status = SyncFileItem::SoftError; - _temporarilyUnavailablePaths.insert(item._file); + item->_errorString = QLatin1String("Directory temporarily not available on server."); + item->_status = SyncFileItem::SoftError; + _temporarilyUnavailablePaths.insert(item->_file); break; default: Q_ASSERT("Non handled error-status"); /* No error string */ } - if (item._instruction == CSYNC_INSTRUCTION_IGNORE && (utf8State.invalidChars > 0 || utf8State.remainingChars > 0)) { - item._status = SyncFileItem::NormalError; - //item._instruction = CSYNC_INSTRUCTION_ERROR; - item._errorString = tr("Filename encoding is not valid"); + if (item->_instruction == CSYNC_INSTRUCTION_IGNORE && (utf8State.invalidChars > 0 || utf8State.remainingChars > 0)) { + item->_status = SyncFileItem::NormalError; + //item->_instruction = CSYNC_INSTRUCTION_ERROR; + item->_errorString = tr("Filename encoding is not valid"); } - item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR; + item->_isDirectory = file->type == CSYNC_FTW_TYPE_DIR; // The etag is already set in the previous sync phases somewhere. Maybe we should remove it there // and do it here so we have a consistent state about which tree stores information from which source. - item._etag = file->etag; - item._size = file->size; + item->_etag = file->etag; + item->_size = file->size; if (!remote) { - item._inode = file->inode; + item->_inode = file->inode; } switch( file->type ) { case CSYNC_FTW_TYPE_DIR: - item._type = SyncFileItem::Directory; + item->_type = SyncFileItem::Directory; break; case CSYNC_FTW_TYPE_FILE: - item._type = SyncFileItem::File; + item->_type = SyncFileItem::File; break; case CSYNC_FTW_TYPE_SLINK: - item._type = SyncFileItem::SoftLink; + item->_type = SyncFileItem::SoftLink; break; default: - item._type = SyncFileItem::UnknownType; + item->_type = SyncFileItem::UnknownType; } SyncFileItem::Direction dir; @@ -427,7 +430,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) int re = 0; switch(file->instruction) { case CSYNC_INSTRUCTION_NONE: - if (remote && item._should_update_etag && !item._isDirectory && item._instruction == CSYNC_INSTRUCTION_NONE) { + if (remote && item->_should_update_etag && !item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_NONE) { // Update the database now already: New fileid or Etag or RemotePerm // Or for files that were detected as "resolved conflict". // They should have been a conflict because they both were new, or both @@ -437,12 +440,12 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) // Even if the mtime is different on the server, we always want to keep the mtime from // the file system in the DB, this is to avoid spurious upload on the next sync - item._modtime = file->other.modtime; + item->_modtime = file->other.modtime; - _journal->setFileRecord(SyncJournalFileRecord(item, _localPath + item._file)); - item._should_update_etag = false; + _journal->setFileRecord(SyncJournalFileRecord(*item, _localPath + item->_file)); + item->_should_update_etag = false; } - if (item._isDirectory && (remote || file->should_update_etag)) { + if (item->_isDirectory && (remote || file->should_update_etag)) { // Because we want still to update etags of directories dir = SyncFileItem::None; } else { @@ -451,15 +454,15 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) _hasNoneFiles = true; } - emit syncItemDiscovered(item); + emit syncItemDiscovered(*item); return re; } break; case CSYNC_INSTRUCTION_RENAME: dir = !remote ? SyncFileItem::Down : SyncFileItem::Up; - item._renameTarget = renameTarget; - if (item._isDirectory) - _renamedFolders.insert(item._file, item._renameTarget); + item->_renameTarget = renameTarget; + if (item->_isDirectory) + _renamedFolders.insert(item->_file, item->_renameTarget); break; case CSYNC_INSTRUCTION_REMOVE: _hasRemoveFile = true; @@ -484,14 +487,14 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) break; } - item._direction = dir; + item->_direction = dir; if (instruction != CSYNC_INSTRUCTION_NONE) { // check for blacklisting of this item. // if the item is on blacklist, the instruction was set to ERROR - checkErrorBlacklisting( &item ); + checkErrorBlacklisting( *item ); } - if (!item._isDirectory) { + if (!item->_isDirectory) { _progressInfo._totalFileCount++; if (Progress::isSizeDependent(file->instruction)) { _progressInfo._totalSize += file->size; @@ -502,21 +505,21 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) } _needsUpdate = true; - item.log._etag = file->etag; - item.log._fileId = file->file_id; - item.log._instruction = file->instruction; - item.log._modtime = file->modtime; - item.log._size = file->size; + item->log._etag = file->etag; + item->log._fileId = file->file_id; + item->log._instruction = file->instruction; + item->log._modtime = file->modtime; + item->log._size = file->size; - item.log._other_etag = file->other.etag; - item.log._other_fileId = file->other.file_id; - item.log._other_instruction = file->other.instruction; - item.log._other_modtime = file->other.modtime; - item.log._other_size = file->other.size; + item->log._other_etag = file->other.etag; + item->log._other_fileId = file->other.file_id; + item->log._other_instruction = file->other.instruction; + item->log._other_modtime = file->other.modtime; + item->log._other_size = file->other.size; _syncItemMap.insert(key, item); - emit syncItemDiscovered(item); + emit syncItemDiscovered(*item); return re; } @@ -730,7 +733,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) // Adjust the paths for the renames. for (SyncFileItemVector::iterator it = _syncedItems.begin(); it != _syncedItems.end(); ++it) { - it->_file = adjustRenamedPath(it->_file); + (*it)->_file = adjustRenamedPath((*it)->_file); } // Sort items per destination @@ -748,7 +751,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) if (!_hasNoneFiles && _hasRemoveFile) { qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user"; bool cancel = false; - emit aboutToRemoveAllFiles(_syncedItems.first()._direction, &cancel); + emit aboutToRemoveAllFiles(_syncedItems.first()->_direction, &cancel); if (cancel) { qDebug() << Q_FUNC_INFO << "Abort sync"; finalize(); @@ -779,10 +782,10 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) _propagator = QSharedPointer( new OwncloudPropagator (_account, session, _localPath, _remoteUrl, _remotePath, _journal, &_thread)); - connect(_propagator.data(), SIGNAL(completed(SyncFileItem)), - this, SLOT(slotJobCompleted(SyncFileItem))); - connect(_propagator.data(), SIGNAL(progress(SyncFileItem,quint64)), - this, SLOT(slotProgress(SyncFileItem,quint64))); + connect(_propagator.data(), SIGNAL(completed(const SyncFileItem &)), + this, SLOT(slotJobCompleted(const SyncFileItem &))); + connect(_propagator.data(), SIGNAL(progress(const SyncFileItem &,quint64)), + this, SLOT(slotProgress(const SyncFileItem &,quint64))); connect(_propagator.data(), SIGNAL(adjustTotalTransmissionSize(qint64)), this, SLOT(slotAdjustTotalTransmissionSize(qint64))); connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection); @@ -840,20 +843,6 @@ void SyncEngine::slotJobCompleted(const SyncFileItem &item) const char * instruction_str = csync_instruction_str(item._instruction); qDebug() << Q_FUNC_INFO << item._file << instruction_str << item._status << item._errorString; - /* Update the _syncedItems vector */ - int idx = _syncedItems.indexOf(item); - if (idx >= 0) { - _syncedItems[idx]._instruction = item._instruction; - _syncedItems[idx]._errorString = item._errorString; - _syncedItems[idx]._status = item._status; - - _syncedItems[idx]._requestDuration = item._requestDuration; - _syncedItems[idx]._responseTimeStamp = item._responseTimeStamp; - } else { - qWarning() << Q_FUNC_INFO << "Could not find index in synced items!"; - - } - _progressInfo.setProgressComplete(item); if (item._status == SyncFileItem::FatalError) { @@ -933,114 +922,113 @@ QString SyncEngine::adjustRenamedPath(const QString& original) void SyncEngine::checkForPermission() { for (SyncFileItemVector::iterator it = _syncedItems.begin(); it != _syncedItems.end(); ++it) { - - if (it->_direction != SyncFileItem::Up) { + if ((*it)->_direction != SyncFileItem::Up) { // Currently we only check server-side permissions continue; } // Do not propagate anything in the server if it is in the selective sync blacklist - const QString path = it->destination() + QLatin1Char('/'); + const QString path = (*it)->destination() + QLatin1Char('/'); if (std::binary_search(_selectiveSyncBlackList.constBegin(), _selectiveSyncBlackList.constEnd(), path)) { - it->_instruction = CSYNC_INSTRUCTION_IGNORE; - it->_status = SyncFileItem::FileIgnored; - it->_errorString = tr("Ignored because of the \"choose what to sync\" blacklist"); + (*it)->_instruction = CSYNC_INSTRUCTION_IGNORE; + (*it)->_status = SyncFileItem::FileIgnored; + (*it)->_errorString = tr("Ignored because of the \"choose what to sync\" blacklist"); - if (it->_isDirectory) { - for (SyncFileItemVector::iterator it_next = it + 1; it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) { + if ((*it)->_isDirectory) { + for (SyncFileItemVector::iterator it_next = it + 1; it_next != _syncedItems.end() && (*it_next)->_file.startsWith(path); ++it_next) { it = it_next; - it->_instruction = CSYNC_INSTRUCTION_IGNORE; - it->_status = SyncFileItem::FileIgnored; - it->_errorString = tr("Ignored because of the \"choose what to sync\" blacklist"); + (*it)->_instruction = CSYNC_INSTRUCTION_IGNORE; + (*it)->_status = SyncFileItem::FileIgnored; + (*it)->_errorString = tr("Ignored because of the \"choose what to sync\" blacklist"); } } continue; } - switch(it->_instruction) { + switch((*it)->_instruction) { case CSYNC_INSTRUCTION_NEW: { - int slashPos = it->_file.lastIndexOf('/'); - QString parentDir = slashPos <= 0 ? "" : it->_file.mid(0, slashPos); + int slashPos = (*it)->_file.lastIndexOf('/'); + QString parentDir = slashPos <= 0 ? "" : (*it)->_file.mid(0, slashPos); const QByteArray perms = getPermissions(parentDir); if (perms.isNull()) { // No permissions set break; - } else if (it->_isDirectory && !perms.contains("K")) { - qDebug() << "checkForPermission: ERROR" << it->_file; - it->_instruction = CSYNC_INSTRUCTION_ERROR; - it->_status = SyncFileItem::NormalError; - it->_errorString = tr("Not allowed because you don't have permission to add sub-directories in that directory"); + } else if ((*it)->_isDirectory && !perms.contains("K")) { + qDebug() << "checkForPermission: ERROR" << (*it)->_file; + (*it)->_instruction = CSYNC_INSTRUCTION_ERROR; + (*it)->_status = SyncFileItem::NormalError; + (*it)->_errorString = tr("Not allowed because you don't have permission to add sub-directories in that directory"); - for (SyncFileItemVector::iterator it_next = it + 1; it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) { + for (SyncFileItemVector::iterator it_next = it + 1; it_next != _syncedItems.end() && (*it_next)->_file.startsWith(path); ++it_next) { it = it_next; - it->_instruction = CSYNC_INSTRUCTION_ERROR; - it->_status = SyncFileItem::NormalError; - it->_errorString = tr("Not allowed because you don't have permission to add parent directory"); + (*it)->_instruction = CSYNC_INSTRUCTION_ERROR; + (*it)->_status = SyncFileItem::NormalError; + (*it)->_errorString = tr("Not allowed because you don't have permission to add parent directory"); } - } else if (!it->_isDirectory && !perms.contains("C")) { - qDebug() << "checkForPermission: ERROR" << it->_file; - it->_instruction = CSYNC_INSTRUCTION_ERROR; - it->_status = SyncFileItem::NormalError; - it->_errorString = tr("Not allowed because you don't have permission to add files in that directory"); + } else if (!(*it)->_isDirectory && !perms.contains("C")) { + qDebug() << "checkForPermission: ERROR" << (*it)->_file; + (*it)->_instruction = CSYNC_INSTRUCTION_ERROR; + (*it)->_status = SyncFileItem::NormalError; + (*it)->_errorString = tr("Not allowed because you don't have permission to add files in that directory"); } break; } case CSYNC_INSTRUCTION_SYNC: { - const QByteArray perms = getPermissions(it->_file); + const QByteArray perms = getPermissions((*it)->_file); if (perms.isNull()) { // No permissions set break; - } if (!it->_isDirectory && !perms.contains("W")) { - qDebug() << "checkForPermission: RESTORING" << it->_file; - it->_should_update_etag = true; - it->_instruction = CSYNC_INSTRUCTION_CONFLICT; - it->_direction = SyncFileItem::Down; - it->_isRestoration = true; + } if (!(*it)->_isDirectory && !perms.contains("W")) { + qDebug() << "checkForPermission: RESTORING" << (*it)->_file; + (*it)->_should_update_etag = true; + (*it)->_instruction = CSYNC_INSTRUCTION_CONFLICT; + (*it)->_direction = SyncFileItem::Down; + (*it)->_isRestoration = true; // take the things to write to the db from the "other" node (i.e: info from server) - it->_modtime = it->log._other_modtime; - it->_size = it->log._other_size; - it->_fileId = it->log._other_fileId; - it->_etag = it->log._other_etag; - it->_errorString = tr("Not allowed to upload this file because it is read-only on the server, restoring"); + (*it)->_modtime = (*it)->log._other_modtime; + (*it)->_size = (*it)->log._other_size; + (*it)->_fileId = (*it)->log._other_fileId; + (*it)->_etag = (*it)->log._other_etag; + (*it)->_errorString = tr("Not allowed to upload this file because it is read-only on the server, restoring"); continue; } break; } case CSYNC_INSTRUCTION_REMOVE: { - const QByteArray perms = getPermissions(it->_file); + const QByteArray perms = getPermissions((*it)->_file); if (perms.isNull()) { // No permissions set break; } if (!perms.contains("D")) { - qDebug() << "checkForPermission: RESTORING" << it->_file; - it->_should_update_etag = true; - it->_instruction = CSYNC_INSTRUCTION_NEW; - it->_direction = SyncFileItem::Down; - it->_isRestoration = true; - it->_errorString = tr("Not allowed to remove, restoring"); - - if (it->_isDirectory) { + qDebug() << "checkForPermission: RESTORING" << (*it)->_file; + (*it)->_should_update_etag = true; + (*it)->_instruction = CSYNC_INSTRUCTION_NEW; + (*it)->_direction = SyncFileItem::Down; + (*it)->_isRestoration = true; + (*it)->_errorString = tr("Not allowed to remove, restoring"); + + if ((*it)->_isDirectory) { // restore all sub items for (SyncFileItemVector::iterator it_next = it + 1; - it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) { + it_next != _syncedItems.end() && (*it_next)->_file.startsWith(path); ++it_next) { it = it_next; - if (it->_instruction != CSYNC_INSTRUCTION_REMOVE) { + if ((*it)->_instruction != CSYNC_INSTRUCTION_REMOVE) { qWarning() << "non-removed job within a removed directory" - << it->_file << it->_instruction; + << (*it)->_file << (*it)->_instruction; continue; } - qDebug() << "checkForPermission: RESTORING" << it->_file; - it->_should_update_etag = true; + qDebug() << "checkForPermission: RESTORING" << (*it)->_file; + (*it)->_should_update_etag = true; - it->_instruction = CSYNC_INSTRUCTION_NEW; - it->_direction = SyncFileItem::Down; - it->_isRestoration = true; - it->_errorString = tr("Not allowed to remove, restoring"); + (*it)->_instruction = CSYNC_INSTRUCTION_NEW; + (*it)->_direction = SyncFileItem::Down; + (*it)->_isRestoration = true; + (*it)->_errorString = tr("Not allowed to remove, restoring"); } } } else if(perms.contains("S") && perms.contains("D")) { @@ -1050,14 +1038,14 @@ void SyncEngine::checkForPermission() // not delete permission we fast forward the iterator and leave the // delete jobs intact. It is not physically tried to remove this files // underneath, propagator sees that. - if( it->_isDirectory ) { + if( (*it)->_isDirectory ) { // put a more descriptive message if really a top level share dir is removed. - if( it == _syncedItems.begin() || !(path.startsWith((it-1)->_file)) ) { - it->_errorString = tr("Local files and share folder removed."); + if( it == _syncedItems.begin() || !(path.startsWith((*(it-1))->_file)) ) { + (*it)->_errorString = tr("Local files and share folder removed."); } for (SyncFileItemVector::iterator it_next = it + 1; - it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) { + it_next != _syncedItems.end() && (*it_next)->_file.startsWith(path); ++it_next) { it = it_next; } } @@ -1067,13 +1055,13 @@ void SyncEngine::checkForPermission() case CSYNC_INSTRUCTION_RENAME: { - int slashPos = it->_renameTarget.lastIndexOf('/'); - const QString parentDir = slashPos <= 0 ? "" : it->_renameTarget.mid(0, slashPos); + int slashPos = (*it)->_renameTarget.lastIndexOf('/'); + const QString parentDir = slashPos <= 0 ? "" : (*it)->_renameTarget.mid(0, slashPos); const QByteArray destPerms = getPermissions(parentDir); - const QByteArray filePerms = getPermissions(it->_file); + const QByteArray filePerms = getPermissions((*it)->_file); //true when it is just a rename in the same directory. (not a move) - bool isRename = it->_file.startsWith(parentDir) && it->_file.lastIndexOf('/') == slashPos; + bool isRename = (*it)->_file.startsWith(parentDir) && (*it)->_file.lastIndexOf('/') == slashPos; // Check if we are allowed to move to the destination. @@ -1081,9 +1069,9 @@ void SyncEngine::checkForPermission() if (isRename || destPerms.isNull()) { // no need to check for the destination dir permission destinationOK = true; - } else if (it->_isDirectory && !destPerms.contains("K")) { + } else if ((*it)->_isDirectory && !destPerms.contains("K")) { destinationOK = false; - } else if (!it->_isDirectory && !destPerms.contains("C")) { + } else if (!(*it)->_isDirectory && !destPerms.contains("C")) { destinationOK = false; } @@ -1106,39 +1094,39 @@ void SyncEngine::checkForPermission() if (!sourceOK && !destinationOK) { // Both the source and the destination won't allow move. Move back to the original - std::swap(it->_file, it->_renameTarget); - it->_direction = SyncFileItem::Down; - it->_errorString = tr("Move not allowed, item restored"); - it->_isRestoration = true; - qDebug() << "checkForPermission: MOVING BACK" << it->_file; + std::swap((*it)->_file, (*it)->_renameTarget); + (*it)->_direction = SyncFileItem::Down; + (*it)->_errorString = tr("Move not allowed, item restored"); + (*it)->_isRestoration = true; + qDebug() << "checkForPermission: MOVING BACK" << (*it)->_file; } else #endif if (!sourceOK || !destinationOK) { // One of them is not possible, just throw an error - it->_instruction = CSYNC_INSTRUCTION_ERROR; - it->_status = SyncFileItem::NormalError; + (*it)->_instruction = CSYNC_INSTRUCTION_ERROR; + (*it)->_status = SyncFileItem::NormalError; const QString errorString = tr("Move not allowed because %1 is read-only").arg( sourceOK ? tr("the destination") : tr("the source")); - it->_errorString = errorString; + (*it)->_errorString = errorString; - qDebug() << "checkForPermission: ERROR MOVING" << it->_file << errorString; + qDebug() << "checkForPermission: ERROR MOVING" << (*it)->_file << errorString; // Avoid a rename on next sync: // TODO: do the resolution now already so we don't need two sync // At this point we would need to go back to the propagate phase on both remote to take // the decision. - _journal->avoidRenamesOnNextSync(it->_file); + _journal->avoidRenamesOnNextSync((*it)->_file); _anotherSyncNeeded = true; - if (it->_isDirectory) { + if ((*it)->_isDirectory) { for (SyncFileItemVector::iterator it_next = it + 1; - it_next != _syncedItems.end() && it_next->destination().startsWith(path); ++it_next) { + it_next != _syncedItems.end() && (*it_next)->destination().startsWith(path); ++it_next) { it = it_next; - it->_instruction = CSYNC_INSTRUCTION_ERROR; - it->_status = SyncFileItem::NormalError; - it->_errorString = errorString; - qDebug() << "checkForPermission: ERROR MOVING" << it->_file; + (*it)->_instruction = CSYNC_INSTRUCTION_ERROR; + (*it)->_status = SyncFileItem::NormalError; + (*it)->_errorString = errorString; + qDebug() << "checkForPermission: ERROR MOVING" << (*it)->_file; } } } @@ -1175,11 +1163,11 @@ bool SyncEngine::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s pat.append(QLatin1Char('/')); } - Q_FOREACH(const SyncFileItem &item, _syncedItems) { + Q_FOREACH(const SyncFileItemPtr &item, _syncedItems) { //qDebug() << Q_FUNC_INFO << fn << item._file << fn.startsWith(item._file) << item._file.startsWith(fn); - if (item._file.startsWith(pat) || - item._file == fn /* the same directory or file */) { + if (item->_file.startsWith(pat) || + item->_file == fn /* the same directory or file */) { qDebug() << Q_FUNC_INFO << "Setting" << fn << " to STATUS_EVAL"; s->set(SyncFileStatus::STATUS_EVAL); return true; diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index 61066771b..bd740663e 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -124,7 +124,7 @@ private: static int treewalkLocal( TREE_WALK_FILE*, void *); static int treewalkRemote( TREE_WALK_FILE*, void *); int treewalkFile( TREE_WALK_FILE*, bool ); - bool checkErrorBlacklisting( SyncFileItem *item ); + bool checkErrorBlacklisting( SyncFileItem &item ); // Cleans up unnecessary downloadinfo entries in the journal as well // as their temporary files. @@ -142,7 +142,7 @@ private: static bool _syncRunning; //true when one sync is running somewhere (for debugging) // Must only be acessed during update and reconcile - QMap _syncItemMap; + QMap _syncItemMap; // should be called _syncItems (present tense). It's the items from the _syncItemMap but // sorted and re-adjusted based on permissions. diff --git a/src/libsync/syncfileitem.h b/src/libsync/syncfileitem.h index dc2bf4aca..3a9ee81ed 100644 --- a/src/libsync/syncfileitem.h +++ b/src/libsync/syncfileitem.h @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -167,9 +168,12 @@ public: } log; }; +typedef QSharedPointer SyncFileItemPtr; +inline bool operator<(const SyncFileItemPtr& item1, const SyncFileItemPtr& item2) { + return *item1 < *item2; +} - -typedef QVector SyncFileItemVector; +typedef QVector SyncFileItemVector; }