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(); if (reply()->hasRawHeader("OC-ErrorString")) { _item->_errorString = reply()->rawHeader("OC-ErrorString"); } if (_item->_status == SyncFileItem::FatalError || _item->_httpErrorCode >= 400) { if (_item->_status != SyncFileItem::FatalError && _item->_httpErrorCode != 503) { SyncJournalDb::PollInfo info; info._file = _item->_file; // no info._url removes it from the database _journal->setPollInfo(info); _journal->commit("remove poll info"); } emit finishedSignal(); return true; } start(); return false; } bool ok = false; QByteArray jsonData = reply()->readAll().trimmed(); 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; emit finishedSignal(); return true; } if (status["unfinished"].isValid()) { start(); 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(); SyncJournalDb::PollInfo info; info._file = _item->_file; // no info._url removes it from the database _journal->setPollInfo(info); _journal->commit("remove poll info"); emit finishedSignal(); return true; }
void FileTask::startFileOp() { bool error = false; QString errMessage; QFile src(m_srcFileName); switch (m_currentOp) { case CopyOp: if (!src.copy(m_filesDir + m_destFileName)) { error = true; errMessage = tr("Failed to copy %1 to %2: %3") .arg(m_srcFileName).arg(m_filesDir + m_destFileName) .arg(src.errorString()); } break; case RemoveOp: if (!QFile::remove(m_filesDir + m_srcFileName)) { error = true; errMessage = tr("Failed to remove %1: %2") .arg(m_filesDir + m_srcFileName).arg(src.errorString()); } break; default: break; } if (error) { emit errorSignal(errMessage); return; } emit finishedSignal(m_srcFileName, m_destFileName, m_currentOp); }
bool MoveJob::finished() { qCInfo(lcMoveJob) << "MOVE of" << reply()->request().url() << "FINISHED WITH STATUS" << replyStatusString(); emit finishedSignal(); return true; }
void PropagateRemoteDelete::start() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; qDebug() << Q_FUNC_INFO << _item->_file; _job = new DeleteJob(_propagator->account(), _propagator->_remoteFolder + _item->_file, this); connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotDeleteJobFinished())); _propagator->_activeJobs ++; _job->start(); }
void PropagateRemoteMkdir::start() { if (propagator()->_abortRequested.fetchAndAddRelaxed(0)) return; qCDebug(lcPropagateRemoteMkdir) << _item->_file; propagator()->_activeJobList.append(this); if (!_deleteExisting) { return slotStartMkcolJob(); } _job = new DeleteJob(propagator()->account(), propagator()->_remoteFolder + _item->_file, this); connect(_job, SIGNAL(finishedSignal()), SLOT(slotStartMkcolJob())); _job->start(); }
void PropagateRemoteMove::start() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; qDebug() << Q_FUNC_INFO << _item->_file << _item->_renameTarget; QString targetFile(_propagator->getFilePath(_item->_renameTarget)); if (_item->_file == _item->_renameTarget) { // The parent has been renamed already so there is nothing more to do. finalize(); return; } 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 happened QString versionString = _propagator->account()->serverVersion(); if (versionString.contains('.') && versionString.split('.')[0].toInt() < 7) { QString originalFile(_propagator->getFilePath(QLatin1String("Shared"))); emit _propagator->touchedFile(originalFile); emit _propagator->touchedFile(targetFile); QString renameError; if( FileSystem::rename(targetFile, originalFile, &renameError) ) { done(SyncFileItem::NormalError, tr("This folder must not be renamed. It is renamed back to its original name.")); } else { done(SyncFileItem::NormalError, tr("This folder must not be renamed. Please name it back to Shared.")); } return; } } QString destination = QDir::cleanPath(_propagator->account()->url().path() + QLatin1Char('/') + _propagator->account()->davPath() + _propagator->_remoteFolder + _item->_renameTarget); _job = new MoveJob(_propagator->account(), _propagator->_remoteFolder + _item->_file, destination, this); connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotMoveJobFinished())); _propagator->_activeJobList.append(this); _job->start(); }
void PropagateUploadFileQNAM::start() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) { return; } _propagator->_activeJobList.append(this); if (!_deleteExisting) { return slotComputeContentChecksum(); } auto job = new DeleteJob(_propagator->account(), _propagator->_remoteFolder + _item->_file, this); _jobs.append(job); connect(job, SIGNAL(finishedSignal()), SLOT(slotComputeContentChecksum())); connect(job, SIGNAL(destroyed(QObject*)), SLOT(slotJobDestroyed(QObject*))); job->start(); }
void BackupTask::startBackupTask() { bool error = false; QString errMessage; switch (m_currentOp) { case ExportOp: error = !fullExport(m_path, errMessage); break; case ImportOp: error = !fullImport(m_path, errMessage); break; default: break; } if (error) { emit errorSignal(errMessage); return; } emit finishedSignal(m_currentOp); }
void PropagateUploadFileQNAM::startNextChunk() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; if (! _jobs.isEmpty() && _currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 // We return now and when the _jobs are finished we will proceed with the last chunk // NOTE: Some other parts of the code such as slotUploadProgress also assume that the last chunk // is sent last. return; } quint64 fileSize = _item->_size; QMap<QByteArray, QByteArray> 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->_file.contains(".sys.admin#recall#")) { // This is a file recall triggered by the admin. Note: the // recall list file created by the admin and downloaded by the // client (.sys.admin#recall#) also falls into this category // (albeit users are not supposed to mess up with it) // We use a special tag header so that the server may decide to store this file away in some admin stage area // And not directly in the user's area (which would trigger redownloads etc). headers["OC-Tag"] = ".sys.admin#recall#"; } if (!_item->_etag.isEmpty() && _item->_etag != "empty_etag" && _item->_instruction != CSYNC_INSTRUCTION_NEW // On new files never send a If-Match && _item->_instruction != CSYNC_INSTRUCTION_TYPE_CHANGE && !_deleteExisting ) { // We add quotes because the owncloud server always adds quotes around the etag, and // csync_owncloud.c's owncloud_file_id always strips the quotes. headers["If-Match"] = '"' + _item->_etag + '"'; } QString path = _item->_file; UploadDevice *device = new UploadDevice(&_propagator->_bandwidthManager); qint64 chunkStart = 0; qint64 currentChunkSize = fileSize; bool isFinalChunk = false; if (_chunkCount > 1) { int sendingChunk = (_currentChunk + _startChunk) % _chunkCount; // XOR with chunk size to make sure everything goes well if chunk size changes between runs uint transid = _transferId ^ chunkSize(); qDebug() << "Upload chunk" << sendingChunk << "of" << _chunkCount << "transferid(remote)=" << transid; path += QString("-chunking-%1-%2-%3").arg(transid).arg(_chunkCount).arg(sendingChunk); headers["OC-Chunked"] = "1"; chunkStart = chunkSize() * quint64(sendingChunk); currentChunkSize = chunkSize(); if (sendingChunk == _chunkCount - 1) { // last chunk currentChunkSize = (fileSize % chunkSize()); if( currentChunkSize == 0 ) { // if the last chunk pretends to be 0, its actually the full chunk size. currentChunkSize = chunkSize(); } isFinalChunk = true; } } else { // if there's only one chunk, it's the final one isFinalChunk = true; } if (isFinalChunk && !_transmissionChecksumType.isEmpty()) { headers[checkSumHeaderC] = makeChecksumHeader( _transmissionChecksumType, _transmissionChecksum); } const QString fileName = _propagator->getFilePath(_item->_file); if (! device->prepareAndOpen(fileName, chunkStart, currentChunkSize)) { qDebug() << "ERR: Could not prepare upload device: " << device->errorString(); // If the file is currently locked, we want to retry the sync // when it becomes available again. if (FileSystem::isFileLocked(fileName)) { emit _propagator->seenLockedFile(fileName); } // Soft error because this is likely caused by the user modifying his files while syncing abortWithError( SyncFileItem::SoftError, device->errorString() ); delete device; return; } // job takes ownership of device via a QScopedPointer. Job deletes itself when finishing PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk); _jobs.append(job); connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished())); connect(job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64))); connect(job, SIGNAL(uploadProgress(qint64,qint64)), device, SLOT(slotJobUploadProgress(qint64,qint64))); connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotJobDestroyed(QObject*))); job->start(); _propagator->_activeJobList.append(this); _currentChunk++; bool parallelChunkUpload = true; QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK"); if (!env.isEmpty()) { parallelChunkUpload = env != "false" && env != "0"; } else { int versionNum = _propagator->account()->serverVersionInt(); if (versionNum < 0x080003) { // Disable parallel chunk upload severs older than 8.0.3 to avoid too many // internal sever errors (#2743, #2938) parallelChunkUpload = false; } } if (_currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 parallelChunkUpload = false; } if (parallelChunkUpload && (_propagator->_activeJobList.count() < _propagator->maximumActiveJob()) && _currentChunk < _chunkCount ) { startNextChunk(); } if (!parallelChunkUpload || _chunkCount - _currentChunk <= 0) { emit ready(); } }
bool MoveJob::finished() { emit finishedSignal(); return true; }
bool SimpleNetworkJob::finished() { emit finishedSignal(reply()); return true; }
void PropagateUploadFileQNAM::startNextChunk() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; if (! _jobs.isEmpty() && _currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 // We return now and when the _jobs will be finished we will proceed the last chunk return; } quint64 fileSize = _item._size; QMap<QByteArray, QByteArray> headers; headers["OC-Total-Length"] = QByteArray::number(fileSize); headers["OC-Async"] = "1"; 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 ) { // 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 + '"'; } QString path = _item._file; UploadDevice *device = 0; if (_chunkCount > 1) { int sendingChunk = (_currentChunk + _startChunk) % _chunkCount; // XOR with chunk size to make sure everything goes well if chunk size change between runs uint transid = _transferId ^ chunkSize(); path += QString("-chunking-%1-%2-%3").arg(transid).arg(_chunkCount).arg(sendingChunk); headers["OC-Chunked"] = "1"; int currentChunkSize = chunkSize(); if (sendingChunk == _chunkCount - 1) { // last chunk currentChunkSize = (fileSize % chunkSize()); if( currentChunkSize == 0 ) { // if the last chunk pretents to be 0, its actually the full chunk size. currentChunkSize = chunkSize(); } } device = new UploadDevice(_file, chunkSize() * quint64(sendingChunk), currentChunkSize, &_propagator->_bandwidthManager); } else { device = new UploadDevice(_file, 0, fileSize, &_propagator->_bandwidthManager); } bool isOpen = true; if (!device->isOpen()) { isOpen = device->open(QIODevice::ReadOnly); } if( isOpen ) { PUTFileJob* job = new PUTFileJob(AccountManager::instance()->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk); _jobs.append(job); job->setTimeout(_propagator->httpTimeout() * 1000); connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished())); connect(job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64))); connect(job, SIGNAL(uploadProgress(qint64,qint64)), device, SLOT(slotJobUploadProgress(qint64,qint64))); connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotJobDestroyed(QObject*))); job->start(); _propagator->_activeJobs++; _currentChunk++; QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK"); bool parallelChunkUpload = env=="true" || env =="1";; if (_currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 parallelChunkUpload = false; } if (parallelChunkUpload && (_propagator->_activeJobs < _propagator->maximumActiveJob()) && _currentChunk < _chunkCount ) { startNextChunk(); } if (!parallelChunkUpload || _chunkCount - _currentChunk <= 0) { emitReady(); } } else {
void PropagateUploadFileQNAM::startNextChunk() { if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) return; if (! _jobs.isEmpty() && _currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 // We return now and when the _jobs will be finished we will proceed the last chunk // NOTE: Some other part of the code such as slotUploadProgress assume also that the last chunk // is sent last. return; } quint64 fileSize = _item._size; QMap<QByteArray, QByteArray> 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 ) { // 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 + '"'; } QString path = _item._file; UploadDevice *device = new UploadDevice(&_propagator->_bandwidthManager); qint64 chunkStart = 0; qint64 currentChunkSize = fileSize; if (_chunkCount > 1) { int sendingChunk = (_currentChunk + _startChunk) % _chunkCount; // XOR with chunk size to make sure everything goes well if chunk size change between runs uint transid = _transferId ^ chunkSize(); path += QString("-chunking-%1-%2-%3").arg(transid).arg(_chunkCount).arg(sendingChunk); headers["OC-Chunked"] = "1"; chunkStart = chunkSize() * quint64(sendingChunk); currentChunkSize = chunkSize(); if (sendingChunk == _chunkCount - 1) { // last chunk currentChunkSize = (fileSize % chunkSize()); if( currentChunkSize == 0 ) { // if the last chunk pretents to be 0, its actually the full chunk size. currentChunkSize = chunkSize(); } } } 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() ); delete device; return; } // job takes ownership of device via a QScopedPointer. Job deletes itself when finishing PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk); _jobs.append(job); connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished())); connect(job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64))); connect(job, SIGNAL(uploadProgress(qint64,qint64)), device, SLOT(slotJobUploadProgress(qint64,qint64))); connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotJobDestroyed(QObject*))); job->start(); _propagator->_activeJobs++; _currentChunk++; bool parallelChunkUpload = true; QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK"); if (!env.isEmpty()) { parallelChunkUpload = env != "false" && env != "0"; } else { auto version = _propagator->account()->serverVersion(); auto components = version.split('.'); int versionNum = (components.value(0).toInt() << 16) + (components.value(1).toInt() << 8) + components.value(2).toInt(); if (versionNum < 0x080003) { // Disable parallel chunk upload severs older than 8.0.3 to avoid too many // internal sever errors (#2743, #2938) parallelChunkUpload = false; } } if (_currentChunk + _startChunk >= _chunkCount - 1) { // Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that // https://github.com/owncloud/core/issues/11106 parallelChunkUpload = false; } if (parallelChunkUpload && (_propagator->_activeJobs < _propagator->maximumActiveJob()) && _currentChunk < _chunkCount ) { startNextChunk(); } if (!parallelChunkUpload || _chunkCount - _currentChunk <= 0) { emit ready(); } }
bool DeleteJob::finished() { emit finishedSignal(); return true; }