From dff37e11eb3addc4c746bee8c5f8b0fefc5bc3f0 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 14 Oct 2015 15:45:44 +0200 Subject: [PATCH] Propagate: Store computed checksums in db during upload #3735 --- src/libsync/propagateupload.cpp | 35 +++++++++++++++++++++++++-------- src/libsync/syncjournaldb.cpp | 32 ++++++++++++++++++++++++++++++ src/libsync/syncjournaldb.h | 2 ++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index edcfc880e..c2b073082 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -209,19 +209,32 @@ void PropagateUploadFileQNAM::start() _stopWatch.start(); - // do whatever is needed to add a checksum to the http upload request. - // in any case, the validator will emit signal startUpload to let the flow - // continue in slotStartUpload here. + auto supportedChecksumTypes = _propagator->account()->capabilities().supportedChecksumTypes(); + + // If we already have a checksum header and the checksum type is supported + // by the server, we keep that - otherwise recompute. + if (!_item->_checksumHeader.isEmpty()) { + QByteArray checksumType; + QByteArray checksum; + if (parseChecksumHeader(_item->_checksumHeader, &checksumType, &checksum) + && supportedChecksumTypes.contains(checksumType)) { + // TODO: We could validate the old checksum and thereby determine whether + // an upload is necessary or not. + slotStartUpload(checksumType, checksum); + return; + } + } + + // Compute a new checksum. auto computeChecksum = new ComputeChecksum(this); // If the config file does not specify a checksum type but the - // server supports it choose a type based on that. + // server supports it, choose a type based on that. if (computeChecksum->checksumType().isEmpty()) { - auto checksumTypes = _propagator->account()->capabilities().supportedChecksumTypes(); - if (!checksumTypes.isEmpty()) { + if (!supportedChecksumTypes.isEmpty()) { // TODO: We might want to prefer some types over others instead // of choosing the first. - computeChecksum->setChecksumType(checksumTypes.first()); + computeChecksum->setChecksumType(supportedChecksumTypes.first()); } } @@ -232,8 +245,14 @@ void PropagateUploadFileQNAM::start() void PropagateUploadFileQNAM::slotStartUpload(const QByteArray& checksumType, const QByteArray& checksum) { + // Store the computed checksum in the database, if different + auto newChecksumHeader = makeChecksumHeader(checksumType, checksum); + if (newChecksumHeader != _item->_checksumHeader) { + _item->_checksumHeader = newChecksumHeader; + _propagator->_journal->updateFileRecordChecksumHeader(_item->_file, _item->_checksumHeader); + } + const QString fullFilePath = _propagator->getFilePath(_item->_file); - _item->_checksumHeader = makeChecksumHeader(checksumType, checksum); if (!FileSystem::fileExists(fullFilePath)) { done(SyncFileItem::SoftError, tr("File Removed")); diff --git a/src/libsync/syncjournaldb.cpp b/src/libsync/syncjournaldb.cpp index 0b099ee60..db1814eb9 100644 --- a/src/libsync/syncjournaldb.cpp +++ b/src/libsync/syncjournaldb.cpp @@ -355,6 +355,9 @@ bool SyncJournalDb::checkConnect() "(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, checksumHeader) " "VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15);" ); + _setFileRecordChecksumHeaderQuery.reset(new SqlQuery(_db) ); + _setFileRecordChecksumHeaderQuery->prepare("UPDATE metadata SET checksumHeader = ?2 WHERE phash == ?1;"); + _getDownloadInfoQuery.reset(new SqlQuery(_db) ); _getDownloadInfoQuery->prepare( "SELECT tmpfile, etag, errorcount FROM " "downloadinfo WHERE path=?1" ); @@ -835,6 +838,35 @@ int SyncJournalDb::getFileRecordCount() return 0; } +bool SyncJournalDb::updateFileRecordChecksumHeader(const QString &filename, const QByteArray &checksumHeader) +{ + QMutexLocker locker(&_mutex); + + qlonglong phash = getPHash(filename); + if( !checkConnect() ) { + qDebug() << "Failed to connect database."; + return false; + } + + auto & query = _setFileRecordChecksumHeaderQuery; + + query->reset(); + query->bindValue(1, QString::number(phash)); + query->bindValue(2, checksumHeader); + + if( !query->exec() ) { + qWarning() << "Error SQL statement setFileRecordChecksumHeaderQuery: " + << query->lastQuery() << " :" + << query->error(); + return false; + } + + qDebug() << query->lastQuery() << phash << checksumHeader; + + query->reset(); + return true; +} + static void toDownloadInfo(SqlQuery &query, SyncJournalDb::DownloadInfo * res) { bool ok = true; diff --git a/src/libsync/syncjournaldb.h b/src/libsync/syncjournaldb.h index c0a51efe8..226fa3167 100644 --- a/src/libsync/syncjournaldb.h +++ b/src/libsync/syncjournaldb.h @@ -42,6 +42,7 @@ public: bool setFileRecord( const SyncJournalFileRecord& record ); bool deleteFileRecord( const QString& filename, bool recursively = false ); int getFileRecordCount(); + bool updateFileRecordChecksumHeader(const QString& filename, const QByteArray& checksumHeader); bool exists(); void walCheckpoint(); @@ -159,6 +160,7 @@ private: int _transaction; QScopedPointer _getFileRecordQuery; QScopedPointer _setFileRecordQuery; + QScopedPointer _setFileRecordChecksumHeaderQuery; QScopedPointer _getDownloadInfoQuery; QScopedPointer _setDownloadInfoQuery; QScopedPointer _deleteDownloadInfoQuery; -- 2.30.2