serverJob = new DiscoverySingleDirectoryJob(_discoveryData->_account,
_discoveryData->_remoteFolder + _currentFolder._server, this);
connect(serverJob, &DiscoverySingleDirectoryJob::etag, this, &ProcessDirectoryJob::etag);
+ _discoveryData->_currentlyActiveJobs++;
+ _pendingAsyncJobs++;
connect(serverJob, &DiscoverySingleDirectoryJob::finished, this, [this, serverJob](const auto &results) {
+ _discoveryData->_currentlyActiveJobs--;
+ _pendingAsyncJobs--;
if (results) {
_serverEntries = *results;
_hasServerEntries = true;
}
processFile(std::move(path), localEntry, serverEntry, record);
}
-
- progress();
+ QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
}
bool ProcessDirectoryJob::handleExcluded(const QString &path, bool isDirectory, bool isHidden, bool isSymlink)
if (!result) {
processFileAnalyzeLocalInfo(item, path, localEntry, serverEntry, dbEntry, _queryServer);
}
- progress();
+ QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
});
return;
}
auto job = new RequestEtagJob(_discoveryData->_account, originalPath, this);
connect(job, &RequestEtagJob::finishedWithResult, this, [=](const Result<QString> &etag) mutable {
_pendingAsyncJobs--;
+ QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
if (etag.errorCode() != 404 ||
// Somehow another item claimed this original path, consider as if it existed
_discoveryData->_renamedItems.contains(originalPath)) {
// If the file exist or if there is another error, consider it is a new file.
postProcessServerNew();
- progress();
return;
}
postProcessRename(path);
processFileFinalize(item, path, item->isDirectory(), item->_instruction == CSYNC_INSTRUCTION_RENAME ? NormalQuery : ParentDontExist, _queryServer);
- progress();
});
job->start();
done = true; // Ideally, if the origin still exist on the server, we should continue searching... but that'd be difficult
}
processFileFinalize(item, path, item->isDirectory(), NormalQuery, recurseQueryServer);
_pendingAsyncJobs--;
- progress();
+ QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
});
job->start();
return;
int count = _runningJobs.removeAll(job);
ASSERT(count == 1);
job->deleteLater();
- progress();
+ QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
}
-void ProcessDirectoryJob::progress()
+int ProcessDirectoryJob::progress(int nbJobs)
{
- int maxRunning = 3; // FIXME
- if (_pendingAsyncJobs + _runningJobs.size() > maxRunning)
- return;
-
- if (!_queuedJobs.empty()) {
- auto f = _queuedJobs.front();
- _queuedJobs.pop_front();
- _runningJobs.push_back(f);
- f->start();
- return;
- }
- if (_runningJobs.empty() && _pendingAsyncJobs == 0) {
+ if (_queuedJobs.empty() && _runningJobs.empty() && _pendingAsyncJobs == 0) {
+ _pendingAsyncJobs = -1; // We're finished, we don't want to emit finished again
if (_dirItem) {
if (_childModified && _dirItem->_instruction == CSYNC_INSTRUCTION_REMOVE) {
// re-create directory that has modified contents
}
emit finished();
}
+
+ int started = 0;
+ foreach (auto *rj, _runningJobs) {
+ started += rj->progress(nbJobs - started);
+ if (started >= nbJobs)
+ return started;
+ }
+
+ while (started < nbJobs && !_queuedJobs.empty()) {
+ auto f = _queuedJobs.front();
+ _queuedJobs.pop_front();
+ _runningJobs.push_back(f);
+ f->start();
+ started++;
+ }
+ return started;
}
void ProcessDirectoryJob::dbError()
class DiscoveryPhase : public QObject
{
Q_OBJECT
+
+ ProcessDirectoryJob *_currentRootJob = nullptr;
+
public:
QString _localDir; // absolute path to the local directory. ends with '/'
QString _remoteFolder; // remote folder, ends with '/'
QStringList _selectiveSyncWhiteList;
ExcludedFiles *_excludes;
QString _invalidFilenamePattern; // FIXME: maybe move in ExcludedFiles
+ int _currentlyActiveJobs = 0;
bool _ignoreHiddenFiles = false;
std::function<bool(const QString &)> _shouldDiscoverLocaly;
QByteArray _dataFingerprint;
+ void scheduleMoreJobs();
signals:
void fatalError(const QString &errorString);
void itemDiscovered(const SyncFileItemPtr &item);