return sqlFail("prepare _deleteUploadInfoQuery", _deleteUploadInfoQuery);
}
- QByteArray sql("SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget, errorCategory "
+ QByteArray sql("SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget, errorCategory, requestId "
"FROM blacklist WHERE path=?1");
if (Utility::fsCasePreserving()) {
// if the file system is case preserving we have to check the blacklist
commitInternal("update database structure: add errorCategory col");
}
+ if (columns.indexOf("requestId") == -1) {
+ SqlQuery query(_db);
+ query.prepare("ALTER TABLE blacklist ADD COLUMN requestId VARCHAR(36);");
+ if (!query.exec()) {
+ sqlFail("updateBlacklistTableStructure: Add requestId", query);
+ re = false;
+ }
+ commitInternal("update database structure: add errorCategory col");
+ }
+
SqlQuery query(_db);
query.prepare("CREATE INDEX IF NOT EXISTS blacklist_index ON blacklist(path collate nocase);");
if (!query.exec()) {
if (file.isEmpty())
return entry;
- // SELECT lastTryEtag, lastTryModtime, retrycount, errorstring
-
if (checkConnect()) {
_getErrorBlacklistQuery.reset_and_clear_bindings();
_getErrorBlacklistQuery.bindValue(1, file);
entry._renameTarget = _getErrorBlacklistQuery.stringValue(6);
entry._errorCategory = static_cast<SyncJournalErrorBlacklistRecord::Category>(
_getErrorBlacklistQuery.intValue(7));
+ entry._requestId = _getErrorBlacklistQuery.baValue(8);
entry._file = file;
}
}
if (!_setErrorBlacklistQuery.initOrReset(QByteArrayLiteral(
"INSERT OR REPLACE INTO blacklist "
- "(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget, errorCategory) "
- "VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"), _db)) {
+ "(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget, errorCategory, requestId) "
+ "VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)"), _db)) {
return;
}
_setErrorBlacklistQuery.bindValue(7, item._ignoreDuration);
_setErrorBlacklistQuery.bindValue(8, item._renameTarget);
_setErrorBlacklistQuery.bindValue(9, item._errorCategory);
+ _setErrorBlacklistQuery.bindValue(10, item._requestId);
_setErrorBlacklistQuery.exec();
}
QString _file;
QString _renameTarget;
+ /// The last X-Request-ID of the request that failled
+ QByteArray _requestId;
+
bool isValid() const;
};
return _responseTimestamp;
}
+QByteArray AbstractNetworkJob::requestId()
+{
+ return _reply ? _reply->request().rawHeader("X-Request-ID") : QByteArray();
+}
+
QString AbstractNetworkJob::errorString() const
{
if (_timedout) {
bool followRedirects() const { return _followRedirects; }
QByteArray responseTimestamp();
+ /* Content of the X-Request-ID header. (Only set after the request is sent) */
+ QByteArray requestId();
qint64 timeoutMsec() const { return _timer.interval(); }
bool timedOut() const { return _timedout; }
entry._lastTryTime = Utility::qDateTimeToTime_t(QDateTime::currentDateTimeUtc());
entry._renameTarget = item._renameTarget;
entry._retryCount = old._retryCount + 1;
+ entry._requestId = item._requestId;
static qint64 minBlacklistTime(getMinBlacklistTime());
static qint64 maxBlacklistTime(qMax(getMaxBlacklistTime(), minBlacklistTime));
GETFileJob *job = _job;
ASSERT(job);
+ _item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_responseTimeStamp = job->responseTimestamp();
+ _item->_requestId = job->requestId();
+
QNetworkReply::NetworkError err = job->reply()->error();
if (err != QNetworkReply::NoError) {
- _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.
// so make sure we have the up-to-date time
_item->_modtime = job->lastModified();
}
- _item->_responseTimeStamp = job->responseTimestamp();
_tmpFile.close();
_tmpFile.flush();
QNetworkReply::NetworkError err = _job->reply()->error();
const int httpStatus = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
_item->_httpErrorCode = httpStatus;
+ _item->_responseTimeStamp = _job->responseTimestamp();
+ _item->_requestId = _job->requestId();
if (err != QNetworkReply::NoError && err != QNetworkReply::ContentNotFoundError) {
SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode,
return;
}
- _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
// is ok. This will happen for files that are in the DB but not on
QNetworkReply::NetworkError err = _job->reply()->error();
_item->_httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_responseTimeStamp = _job->responseTimestamp();
+ _item->_requestId = _job->requestId();
if (_item->_httpErrorCode == 405) {
// This happens when the directory already exists. Nothing to do.
return;
}
- _item->_responseTimeStamp = _job->responseTimestamp();
_item->_fileId = _job->reply()->rawHeader("OC-FileId");
if (_item->_fileId.isEmpty()) {
QNetworkReply::NetworkError err = _job->reply()->error();
_item->_httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_responseTimeStamp = _job->responseTimestamp();
+ _item->_requestId = _job->requestId();
if (err != QNetworkReply::NoError) {
SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode,
return;
}
- _item->_responseTimeStamp = _job->responseTimestamp();
-
if (_item->_httpErrorCode != 201) {
// Normally 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
QNetworkReply::NetworkError err = reply()->error();
if (err != QNetworkReply::NoError) {
_item->_httpErrorCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_requestId = requestId();
_item->_status = classifyError(err, _item->_httpErrorCode);
_item->_errorString = errorString();
auto httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
auto status = classifyError(err, httpErrorCode, &propagator()->_anotherSyncNeeded);
if (status == SyncFileItem::FatalError) {
+ _item->_requestId = job->requestId();
propagator()->_activeJobList.removeOne(this);
abortWithError(status, job->errorStringParsingBody());
return;
const int httpStatus = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
SyncFileItem::Status status = classifyError(err, httpStatus);
if (status == SyncFileItem::FatalError) {
+ _item->_requestId = job->requestId();
abortWithError(status, job->errorString());
return;
} else {
_item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (err != QNetworkReply::NoError || _item->_httpErrorCode != 201) {
+ _item->_requestId = job->requestId();
SyncFileItem::Status status = classifyError(err, _item->_httpErrorCode,
&propagator()->_anotherSyncNeeded);
abortWithError(status, job->errorStringParsingBody());
if (err != QNetworkReply::NoError) {
_item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_requestId = job->requestId();
commonErrorHandling(job);
return;
}
slotJobDestroyed(job); // remove it from the _jobs list
QNetworkReply::NetworkError err = job->reply()->error();
_item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_responseTimeStamp = job->responseTimestamp();
+ _item->_requestId = job->requestId();
if (err != QNetworkReply::NoError) {
commonErrorHandling(job);
abortWithError(SyncFileItem::NormalError, tr("Missing ETag from server"));
return;
}
- _item->_responseTimeStamp = job->responseTimestamp();
finalize();
}
}
_item->_httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ _item->_responseTimeStamp = job->responseTimestamp();
+ _item->_requestId = job->requestId();
QNetworkReply::NetworkError err = job->reply()->error();
if (err != QNetworkReply::NoError) {
commonErrorHandling(job);
_item->_etag = etag;
- _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.
// Normally Owncloud 6 always puts X-OC-MTime
RemotePermissions _remotePerm;
QString _errorString; // Contains a string only in case of error
QByteArray _responseTimeStamp;
+ QByteArray _requestId; // X-Request-Id of the failed request
quint32 _affectedItems = 1; // the number of affected items by the operation on this item.
// usually this value is 1, but for removes on dirs, it might be much higher.
auto &modifier = remote ? fakeFolder.remoteModifier() : fakeFolder.localModifier();
int counter = 0;
- fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &, QIODevice *) -> QNetworkReply * {
+ QByteArray reqId;
+ fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *) -> QNetworkReply * {
+ reqId = req.rawHeader("X-Request-ID");
if (!remote && op == QNetworkAccessManager::PutOperation)
++counter;
if (remote && op == QNetworkAccessManager::GetOperation)
QCOMPARE(entry._retryCount, 1);
QCOMPARE(counter, 1);
QVERIFY(entry._ignoreDuration > 0);
+ QCOMPARE(entry._requestId, reqId);
if (remote)
QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
QCOMPARE(entry._retryCount, 1);
QCOMPARE(counter, 1);
QVERIFY(entry._ignoreDuration > 0);
+ QCOMPARE(entry._requestId, reqId);
if (remote)
QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
QCOMPARE(entry._retryCount, 2);
QCOMPARE(counter, 2);
QVERIFY(entry._ignoreDuration > 0);
+ QCOMPARE(entry._requestId, reqId);
if (remote)
QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
QCOMPARE(entry._retryCount, 3);
QCOMPARE(counter, 3);
QVERIFY(entry._ignoreDuration > 0);
+ QCOMPARE(entry._requestId, reqId);
if (remote)
QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);