[Pkg-owncloud-commits] [owncloud-client] 02/333: use QNAM for the PUT

Sandro Knauß hefee-guest at moszumanska.debian.org
Thu Apr 17 23:16:26 UTC 2014


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository owncloud-client.

commit 9a6275a5e3104e8e56ab54480b3e7301b225252c
Author: Olivier Goffart <ogoffart at woboq.com>
Date:   Thu Feb 6 11:50:16 2014 +0100

    use QNAM for the PUT
    
    Not yet supported:
     - chunking
     - if the file changes while uploading
     - aborting
     - owncloudcmd  (because of the dependency to the account and the credidentials)
---
 src/CMakeLists.txt                     |   2 +
 src/creds/dummycredentials.cpp         |   2 +-
 src/creds/dummycredentials.h           |   3 +
 src/mirall/owncloudpropagator.cpp      |  14 +--
 src/mirall/owncloudpropagator_p.h      |  12 +++
 src/mirall/owncloudpropagator_qnam.cpp | 191 +++++++++++++++++++++++++++++++++
 src/mirall/owncloudpropagator_qnam.h   |  51 +++++++++
 7 files changed, 262 insertions(+), 13 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f2f4ffa..3661274 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -70,6 +70,7 @@ set(libsync_SRCS
     mirall/mirallconfigfile.cpp
     mirall/csyncthread.cpp
     mirall/owncloudpropagator.cpp
+    mirall/owncloudpropagator_qnam.cpp
     mirall/syncjournalfilerecord.cpp
     mirall/syncjournaldb.cpp
     mirall/theme.cpp
@@ -104,6 +105,7 @@ set(libsync_HEADERS
     mirall/csyncthread.h
     mirall/owncloudpropagator.h
     mirall/owncloudpropagator_p.h
+    mirall/owncloudpropagator_qnam.h
     mirall/syncjournaldb.h
     mirall/theme.h
     mirall/owncloudtheme.h
diff --git a/src/creds/dummycredentials.cpp b/src/creds/dummycredentials.cpp
index 478020f..e50ddc3 100644
--- a/src/creds/dummycredentials.cpp
+++ b/src/creds/dummycredentials.cpp
@@ -37,7 +37,7 @@ QString DummyCredentials::authType() const
 
 QString DummyCredentials::user() const
 {
-    return QString();
+    return _user;
 }
 
 QNetworkAccessManager* DummyCredentials::getQNAM() const
diff --git a/src/creds/dummycredentials.h b/src/creds/dummycredentials.h
index 7c883ce..7a460eb 100644
--- a/src/creds/dummycredentials.h
+++ b/src/creds/dummycredentials.h
@@ -24,6 +24,9 @@ class DummyCredentials : public AbstractCredentials
     Q_OBJECT
 
 public:
+
+    QString _user;
+    QString _password;
     void syncContextPreInit(CSYNC* ctx);
     void syncContextPreStart(CSYNC* ctx);
     bool changed(AbstractCredentials* credentials) const;
diff --git a/src/mirall/owncloudpropagator.cpp b/src/mirall/owncloudpropagator.cpp
index f8f138f..e8bbba6 100644
--- a/src/mirall/owncloudpropagator.cpp
+++ b/src/mirall/owncloudpropagator.cpp
@@ -17,6 +17,7 @@
 #include "syncjournaldb.h"
 #include "syncjournalfilerecord.h"
 #include "utility.h"
+#include "owncloudpropagator_qnam.h"
 #include <httpbf.h>
 #include <qfile.h>
 #include <qdir.h>
@@ -254,17 +255,6 @@ void PropagateRemoteMkdir::start()
     done(SyncFileItem::Success);
 }
 
-static QByteArray parseEtag(const char *header) {
-    if (!header)
-        return QByteArray();
-    QByteArray arr = header;
-    arr.replace("-gzip", ""); // https://github.com/owncloud/mirall/issues/1195
-    if(arr.length() >= 2 && arr.startsWith('"') && arr.endsWith('"')) {
-        arr = arr.mid(1, arr.length() - 2);
-    }
-    return arr;
-}
-
 void PropagateUploadFile::start()
 {
 
@@ -1005,7 +995,7 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItem& item) {
                 return 0;
             }
             if (item._dir != SyncFileItem::Up) return new PropagateDownloadFile(this, item);
-            else return new PropagateUploadFile(this, item);
+            else return new PropagateUploadFileQNAM(this, item);
         case CSYNC_INSTRUCTION_RENAME:
             if (item._dir == SyncFileItem::Up) {
                 return new PropagateRemoteRename(this, item);
diff --git a/src/mirall/owncloudpropagator_p.h b/src/mirall/owncloudpropagator_p.h
index 1458fd9..380e3fe 100644
--- a/src/mirall/owncloudpropagator_p.h
+++ b/src/mirall/owncloudpropagator_p.h
@@ -174,4 +174,16 @@ private:
                                const ne_session_status_info* info);
 };
 
+inline QByteArray parseEtag(const char *header) {
+    if (!header)
+        return QByteArray();
+    QByteArray arr = header;
+    arr.replace("-gzip", ""); // https://github.com/owncloud/mirall/issues/1195
+    if(arr.length() >= 2 && arr.startsWith('"') && arr.endsWith('"')) {
+        arr = arr.mid(1, arr.length() - 2);
+    }
+    return arr;
+}
+
+
 }
diff --git a/src/mirall/owncloudpropagator_qnam.cpp b/src/mirall/owncloudpropagator_qnam.cpp
new file mode 100644
index 0000000..db765f3
--- /dev/null
+++ b/src/mirall/owncloudpropagator_qnam.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) by Olivier Goffart <ogoffart at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "owncloudpropagator_qnam.h"
+#include "networkjobs.h"
+#include "account.h"
+#include "syncjournaldb.h"
+#include "syncjournalfilerecord.h"
+#include <QNetworkAccessManager>
+
+namespace Mirall {
+
+void PUTFileJob::start() {
+    QNetworkRequest req;
+    qDebug() << _headers;
+    for(QMap<QByteArray, QByteArray>::const_iterator it = _headers.begin(); it != _headers.end(); ++it) {
+        req.setRawHeader(it.key(), it.value());
+        qDebug() << it.key() << it.value();
+    }
+
+    setReply(davRequest("PUT", path(), req, _device));
+    _device->setParent(reply());
+    setupConnections(reply());
+
+    if( reply()->error() != QNetworkReply::NoError ) {
+        qDebug() << "getting etag: request network error: " << reply()->errorString();
+    }
+    AbstractNetworkJob::start();
+
+}
+
+
+void PropagateUploadFileQNAM::start()
+{
+    QFile *file = new QFile(_propagator->_localDir + _item._file);
+    if (!file->open(QIODevice::ReadOnly)) {
+        done(SyncFileItem::NormalError, file->errorString());
+        delete file;
+        return;
+    }
+
+    //TODO
+    //const SyncJournalDb::UploadInfo progressInfo = _propagator->_journal->getUploadInfo(_item._file);
+    QMap<QByteArray, QByteArray> headers;
+    headers["OC-Total-Length"] = QByteArray::number(file->size());
+    headers["Content-Type"] = "application/octet-stream";
+    headers["X-OC-Mtime"] = QByteArray::number(qint64(_item._modtime));
+    if (!_item._etag.isEmpty() && _item._etag != "empty_etag") {
+        // 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 + '"';
+    }
+    PUTFileJob *job = new PUTFileJob(AccountManager::instance()->account(), _item._file, file, headers);
+    connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
+
+//     if( transfer->block_cnt > 1 ) {
+//         ne_add_request_header(req, "OC-Chunked", "1");
+//     }
+
+
+        /*
+        // If the source file has changed during upload, it is detected and the
+        // variable _previousFileSize is set accordingly. The propagator waits a
+        // couple of seconds and retries.
+        if(_previousFileSize > 0) {
+            qDebug() << "File size changed underway: " << trans->stat_size - _previousFileSize;
+            // Report the change of the overall transmission size to the propagator
+            _propagator->overallTransmissionSizeChanged(qint64(trans->stat_size - _previousFileSize));
+            // update the item's values to the current from trans. hbf_splitlist does a stat
+            _item._size = trans->stat_size;
+            _item._modtime = trans->modtime;
+
+        }
+        if (progressInfo._valid) {
+            if (Utility::qDateTimeToTime_t(progressInfo._modtime) == _item._modtime) {
+                trans->start_id = progressInfo._chunk;
+                trans->transfer_id = progressInfo._transferid;
+            }
+        }
+        */
+
+    emit progress(Progress::StartUpload, _item, 0, file->size());
+    job->start();
+}
+
+void PropagateUploadFileQNAM::slotPutFinished()
+{
+    PUTFileJob *job = qobject_cast<PUTFileJob *>(sender());
+    Q_ASSERT(job);
+
+    QNetworkReply::NetworkError err = job->reply()->error();
+    if (err != QNetworkReply::NoError) {
+//             /* If the source file changed during submission, lets try again */
+//             if( state == HBF_SOURCE_FILE_CHANGE ) {
+//                 if( attempts++ < 5 ) { /* FIXME: How often do we want to try? */
+//                     qDebug("SOURCE file has changed during upload, retry #%d in %d seconds!", attempts, 2*attempts);
+//                     sleep(2*attempts);
+//                     if( _previousFileSize == 0 ) {
+//                         _previousFileSize = _item._size;
+//                     } else {
+//                         _previousFileSize = trans->stat_size;
+//                     }
+//                     continue;
+//                 }
+//
+//                 const QString errMsg = tr("Local file changed during sync, syncing once it arrived completely");
+//                 done( SyncFileItem::SoftError, errMsg );
+//             } else if( state == HBF_USER_ABORTED ) {
+//                 const QString errMsg = tr("Sync was aborted by user.");
+//                 done( SyncFileItem::SoftError, errMsg );
+//             } else {
+//                 // Other HBF error conditions.
+//                 // FIXME: find out the error class.
+//                 _item._httpErrorCode = hbf_fail_http_code(trans.data());
+        _item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+        done(SyncFileItem::NormalError, job->reply()->errorString());
+        return;
+    }
+
+
+    // the file id should only be empty for new files up- or downloaded
+    QString fid = QString::fromUtf8(job->reply()->rawHeader("OC-FileID"));
+    if( !fid.isEmpty() ) {
+        if( !_item._fileId.isEmpty() && _item._fileId != fid ) {
+            qDebug() << "WARN: File ID changed!" << _item._fileId << fid;
+        }
+        _item._fileId = fid;
+    }
+
+    _item._etag = parseEtag(job->reply()->rawHeader("ETag"));
+
+    if (job->reply()->rawHeader("X-OC-MTime") != "accepted") {
+        //FIXME
+//             updateMTimeAndETag(uri.data(), _item._modtime);
+        done(SyncFileItem::NormalError, tr("No X-OC-MTime extension,  ownCloud 5 is required"));
+        return;
+    }
+
+    _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, _propagator->_localDir + _item._file));
+    // Remove from the progress database:
+    _propagator->_journal->setUploadInfo(_item._file, SyncJournalDb::UploadInfo());
+    _propagator->_journal->commit("upload file start");
+
+//     if (hbf_validate_source_file(trans.data()) == HBF_SOURCE_FILE_CHANGE) {
+//             /* Did the source file changed since the upload ?
+//              *               This is different from the previous check because the previous check happens between
+//              *               chunks while this one happens when the whole file has been uploaded.
+//              *
+//              *               The new etag is already stored in the database in the previous lines so in case of
+//              *               crash, we won't have a conflict but we will properly do a new upload
+//              */
+//
+//             if( attempts++ < 5 ) { /* FIXME: How often do we want to try? */
+//                 qDebug("SOURCE file has changed after upload, retry #%d in %d seconds!", attempts, 2*attempts);
+//                 sleep(2*attempts);
+//                 continue;
+//             }
+//
+//             // Still the file change error, but we tried a couple of times.
+//             // Ignore this file for now.
+//             // Lets remove the file from the server (at least if it is new) as it is different
+//             // from our file here.
+//             if( _item._instruction == CSYNC_INSTRUCTION_NEW ) {
+//                 QScopedPointer<char, QScopedPointerPodDeleter> uri(
+//                     ne_path_escape((_propagator->_remoteDir + _item._file).toUtf8()));
+//
+//                 int rc = ne_delete(_propagator->_session, uri.data());
+//                 qDebug() << "Remove the invalid file from server:" << rc;
+//             }
+//
+//             const QString errMsg = tr("Local file changed during sync, syncing once it arrived completely");
+//             done( SyncFileItem::SoftError, errMsg );
+//             return;
+//         }
+//
+    emit progress(Progress::EndUpload, _item, _item._size, _item._size);
+    done(SyncFileItem::Success);
+}
+
+}
diff --git a/src/mirall/owncloudpropagator_qnam.h b/src/mirall/owncloudpropagator_qnam.h
new file mode 100644
index 0000000..14eae73
--- /dev/null
+++ b/src/mirall/owncloudpropagator_qnam.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) by Olivier Goffart <ogoffart at owncloud.com>
+ * Copyright (C) by Klaas Freitag <freitag at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#pragma once
+
+#include "owncloudpropagator_p.h"
+#include "networkjobs.h"
+
+
+namespace Mirall {
+
+class PUTFileJob : public AbstractNetworkJob {
+    Q_OBJECT
+    QIODevice* _device;
+    QMap<QByteArray, QByteArray> _headers;
+
+public:
+    explicit PUTFileJob(Account* account, const QString& path, QIODevice *device, const QMap<QByteArray, QByteArray> &headers, QObject* parent = 0)
+    : AbstractNetworkJob(account, path, parent), _device(device), _headers(headers) {}
+
+    virtual void start();
+
+    virtual void finished() {
+        emit finishedSignal();
+    }
+
+signals:
+    void finishedSignal();
+};
+
+class PropagateUploadFileQNAM : public PropagateItemJob {
+    Q_OBJECT
+public:
+    PropagateUploadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item)  : PropagateItemJob(propagator, item) {}
+    void start();
+private slots:
+    void slotPutFinished();
+};
+
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git



More information about the Pkg-owncloud-commits mailing list