Use SyncJournalDb in csync
authorJocelyn Turcotte <jturcotte@woboq.com>
Thu, 14 Sep 2017 13:50:13 +0000 (15:50 +0200)
committerRoeland Jago Douma <roeland@famdouma.nl>
Thu, 5 Oct 2017 20:01:37 +0000 (22:01 +0200)
This gets rid of the csync_statedb sqlite layer and use
the same code and same connection as the rest of the SyncEngine.

Missing functions are added to SyncJournalDb and change a few minor
things (like changing SyncJournalFileRecord::_modtime to be an int64
instead of a QDateTime, like it was in csync).

34 files changed:
src/common/syncjournaldb.cpp
src/common/syncjournaldb.h
src/common/syncjournalfilerecord.cpp
src/common/syncjournalfilerecord.h
src/csync/CMakeLists.txt
src/csync/csync.cpp
src/csync/csync.h
src/csync/csync_private.h
src/csync/csync_reconcile.cpp
src/csync/csync_statedb.cpp [deleted file]
src/csync/csync_statedb.h [deleted file]
src/csync/csync_update.cpp
src/csync/csync_util.cpp
src/csync/vio/csync_vio.cpp
src/gui/folder.cpp
src/libsync/owncloudpropagator.cpp
src/libsync/propagateremotemove.cpp
src/libsync/propagateuploadng.cpp
src/libsync/propagateuploadv1.cpp
src/libsync/propagatorjobs.cpp
src/libsync/syncengine.cpp
src/libsync/syncfileitem.cpp
test/CMakeLists.txt
test/csync/CMakeLists.txt
test/csync/csync_tests/check_csync_exclude.cpp
test/csync/csync_tests/check_csync_statedb_load.cpp [deleted file]
test/csync/csync_tests/check_csync_statedb_query.cpp [deleted file]
test/csync/csync_tests/check_csync_update.cpp
test/csync/vio_tests/check_vio.cpp
test/csync/vio_tests/check_vio_ext.cpp
test/testcsyncsqlite.cpp [deleted file]
test/testsyncengine.cpp
test/testsyncjournaldb.cpp
test/testuploadreset.cpp

index 2146e69450f6d96a8abc1d807adab8104857c9f3..d2b6fb2a78ab807c5413af9152793eb6d53dd618 100644 (file)
@@ -36,6 +36,26 @@ namespace OCC {
 
 Q_LOGGING_CATEGORY(lcDb, "sync.database", QtInfoMsg)
 
+#define GET_FILE_RECORD_QUERY \
+        "SELECT path, inode, modtime, type, md5, fileid, remotePerm, filesize," \
+        "  ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum" \
+        " FROM metadata" \
+        "  LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
+
+static void fillFileRecordFromGetQuery(SyncJournalFileRecord &rec, SqlQuery &query)
+{
+    rec._path = query.baValue(0);
+    rec._inode = query.intValue(1);
+    rec._modtime = query.int64Value(2);
+    rec._type = query.intValue(3);
+    rec._etag = query.baValue(4);
+    rec._fileId = query.baValue(5);
+    rec._remotePerm = RemotePermissions(query.baValue(6).constData());
+    rec._fileSize = query.int64Value(7);
+    rec._serverHasIgnoredFiles = (query.intValue(8) > 0);
+    rec._checksumHeader = query.baValue(9);
+}
+
 static QString defaultJournalMode(const QString &dbPath)
 {
 #ifdef Q_OS_WIN
@@ -500,14 +520,32 @@ bool SyncJournalDb::checkConnect()
 
     _getFileRecordQuery.reset(new SqlQuery(_db));
     if (_getFileRecordQuery->prepare(
-            "SELECT path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize,"
-            "  ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum"
-            " FROM metadata"
-            "  LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
+            GET_FILE_RECORD_QUERY
             " WHERE phash=?1")) {
         return sqlFail("prepare _getFileRecordQuery", *_getFileRecordQuery);
     }
 
+    _getFileRecordQueryByInode.reset(new SqlQuery(_db));
+    if (_getFileRecordQueryByInode->prepare(
+            GET_FILE_RECORD_QUERY
+            " WHERE inode=?1")) {
+        return sqlFail("prepare _getFileRecordQueryByInode", *_getFileRecordQueryByInode);
+    }
+
+    _getFileRecordQueryByFileId.reset(new SqlQuery(_db));
+    if (_getFileRecordQueryByFileId->prepare(
+            GET_FILE_RECORD_QUERY
+            " WHERE fileid=?1")) {
+        return sqlFail("prepare _getFileRecordQueryByFileId", *_getFileRecordQueryByFileId);
+    }
+
+    _getFilesBelowPathQuery.reset(new SqlQuery(_db));
+    if (_getFilesBelowPathQuery->prepare(
+            GET_FILE_RECORD_QUERY
+            " WHERE path > (?1||'/') AND path < (?1||'0') ORDER BY path||'/' ASC")) {
+        return sqlFail("prepare _getFilesBelowPathQuery", *_getFilesBelowPathQuery);
+    }
+
     _setFileRecordQuery.reset(new SqlQuery(_db));
     if (_setFileRecordQuery->prepare("INSERT OR REPLACE INTO metadata "
                                      "(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, contentChecksum, contentChecksumTypeId) "
@@ -651,6 +689,9 @@ void SyncJournalDb::close()
     commitTransaction();
 
     _getFileRecordQuery.reset(0);
+    _getFileRecordQueryByInode.reset(0);
+    _getFileRecordQueryByFileId.reset(0);
+    _getFilesBelowPathQuery.reset(0);
     _setFileRecordQuery.reset(0);
     _setFileRecordChecksumQuery.reset(0);
     _setFileRecordLocalMetadataQuery.reset(0);
@@ -860,18 +901,17 @@ QStringList SyncJournalDb::tableColumns(const QString &table)
     return columns;
 }
 
-qint64 SyncJournalDb::getPHash(const QString &file)
+qint64 SyncJournalDb::getPHash(const QByteArray &file)
 {
-    QByteArray utf8File = file.toUtf8();
     int64_t h;
 
     if (file.isEmpty()) {
         return -1;
     }
 
-    int len = utf8File.length();
+    int len = file.length();
 
-    h = c_jhash64((uint8_t *)utf8File.data(), len, 0);
+    h = c_jhash64((uint8_t *)file.data(), len, 0);
     return h;
 }
 
@@ -882,8 +922,8 @@ bool SyncJournalDb::setFileRecord(const SyncJournalFileRecord &_record)
 
     if (!_avoidReadFromDbOnNextSyncFilter.isEmpty()) {
         // If we are a directory that should not be read from db next time, don't write the etag
-        QString prefix = record._path + "/";
-        foreach (const QString &it, _avoidReadFromDbOnNextSyncFilter) {
+        QByteArray prefix = record._path + "/";
+        foreach (const QByteArray &it, _avoidReadFromDbOnNextSyncFilter) {
             if (it.startsWith(prefix)) {
                 qCInfo(lcDb) << "Filtered writing the etag of" << prefix << "because it is a prefix of" << it;
                 record._etag = "_invalid_";
@@ -899,13 +939,12 @@ bool SyncJournalDb::setFileRecord(const SyncJournalFileRecord &_record)
 
     qlonglong phash = getPHash(record._path);
     if (checkConnect()) {
-        QByteArray arr = record._path.toUtf8();
-        int plen = arr.length();
+        int plen = record._path.length();
 
-        QString etag(record._etag);
+        QByteArray etag(record._etag);
         if (etag.isEmpty())
             etag = "";
-        QString fileId(record._fileId);
+        QByteArray fileId(record._fileId);
         if (fileId.isEmpty())
             fileId = "";
         QByteArray remotePerm = record._remotePerm.toString();
@@ -920,8 +959,8 @@ bool SyncJournalDb::setFileRecord(const SyncJournalFileRecord &_record)
         _setFileRecordQuery->bindValue(5, 0); // uid Not used
         _setFileRecordQuery->bindValue(6, 0); // gid Not used
         _setFileRecordQuery->bindValue(7, 0); // mode Not used
-        _setFileRecordQuery->bindValue(8, QString::number(Utility::qDateTimeToTime_t(record._modtime)));
-        _setFileRecordQuery->bindValue(9, QString::number(record._type));
+        _setFileRecordQuery->bindValue(8, record._modtime);
+        _setFileRecordQuery->bindValue(9, record._type);
         _setFileRecordQuery->bindValue(10, etag);
         _setFileRecordQuery->bindValue(11, fileId);
         _setFileRecordQuery->bindValue(12, remotePerm);
@@ -949,7 +988,7 @@ bool SyncJournalDb::deleteFileRecord(const QString &filename, bool recursively)
         // if (!recursively) {
         // always delete the actual file.
 
-        qlonglong phash = getPHash(filename);
+        qlonglong phash = getPHash(filename.toUtf8());
         _deleteFileRecordPhash->reset_and_clear_bindings();
         _deleteFileRecordPhash->bindValue(1, phash);
 
@@ -972,7 +1011,7 @@ bool SyncJournalDb::deleteFileRecord(const QString &filename, bool recursively)
 }
 
 
-bool SyncJournalDb::getFileRecord(const QString &filename, SyncJournalFileRecord *rec)
+bool SyncJournalDb::getFileRecord(const QByteArray &filename, SyncJournalFileRecord *rec)
 {
     QMutexLocker locker(&_mutex);
 
@@ -995,19 +1034,7 @@ bool SyncJournalDb::getFileRecord(const QString &filename, SyncJournalFileRecord
         }
 
         if (_getFileRecordQuery->next()) {
-            rec->_path = _getFileRecordQuery->stringValue(0);
-            rec->_inode = _getFileRecordQuery->intValue(1);
-            //rec->_uid     = _getFileRecordQuery->value(2).toInt(&ok); Not Used
-            //rec->_gid     = _getFileRecordQuery->value(3).toInt(&ok); Not Used
-            //rec->_mode    = _getFileRecordQuery->intValue(4);
-            rec->_modtime = Utility::qDateTimeFromTime_t(_getFileRecordQuery->int64Value(5));
-            rec->_type = _getFileRecordQuery->intValue(6);
-            rec->_etag = _getFileRecordQuery->baValue(7);
-            rec->_fileId = _getFileRecordQuery->baValue(8);
-            rec->_remotePerm = RemotePermissions(_getFileRecordQuery->baValue(9).constData());
-            rec->_fileSize = _getFileRecordQuery->int64Value(10);
-            rec->_serverHasIgnoredFiles = (_getFileRecordQuery->intValue(11) > 0);
-            rec->_checksumHeader = _getFileRecordQuery->baValue(12);
+            fillFileRecordFromGetQuery(*rec, *_getFileRecordQuery);
         } else {
             int errId = _getFileRecordQuery->errorId();
             if (errId != SQLITE_DONE) { // only do this if the problem is different from SQLITE_DONE
@@ -1022,6 +1049,87 @@ bool SyncJournalDb::getFileRecord(const QString &filename, SyncJournalFileRecord
     return true;
 }
 
+bool SyncJournalDb::getFileRecordByInode(quint64 inode, SyncJournalFileRecord *rec)
+{
+    QMutexLocker locker(&_mutex);
+
+    // Reset the output var in case the caller is reusing it.
+    Q_ASSERT(rec);
+    rec->_path.clear();
+    Q_ASSERT(!rec->isValid());
+
+    if (!inode)
+        return true; // no error, yet nothing found (rec->isValid() == false)
+
+    if (!checkConnect())
+        return false;
+
+    _getFileRecordQueryByInode->reset_and_clear_bindings();
+    _getFileRecordQueryByInode->bindValue(1, inode);
+
+    if (!_getFileRecordQueryByInode->exec()) {
+        return false;
+    }
+
+    if (_getFileRecordQueryByInode->next()) {
+        fillFileRecordFromGetQuery(*rec, *_getFileRecordQueryByInode);
+    }
+
+    return true;
+}
+
+bool SyncJournalDb::getFileRecordByFileId(const QByteArray &fileId, SyncJournalFileRecord *rec)
+{
+    QMutexLocker locker(&_mutex);
+
+    // Reset the output var in case the caller is reusing it.
+    Q_ASSERT(rec);
+    rec->_path.clear();
+    Q_ASSERT(!rec->isValid());
+
+    if (fileId.isEmpty())
+        return true; // no error, yet nothing found (rec->isValid() == false)
+
+    if (!checkConnect())
+        return false;
+
+    _getFileRecordQueryByFileId->reset_and_clear_bindings();
+    _getFileRecordQueryByFileId->bindValue(1, fileId);
+
+    if (!_getFileRecordQueryByFileId->exec()) {
+        return false;
+    }
+
+    if (_getFileRecordQueryByFileId->next()) {
+        fillFileRecordFromGetQuery(*rec, *_getFileRecordQueryByFileId);
+    }
+
+    return true;
+}
+
+bool SyncJournalDb::getFilesBelowPath(const QByteArray &path, const std::function<void(const SyncJournalFileRecord&)> &rowCallback)
+{
+    QMutexLocker locker(&_mutex);
+
+    if (!checkConnect())
+        return false;
+
+    _getFilesBelowPathQuery->reset_and_clear_bindings();
+    _getFilesBelowPathQuery->bindValue(1, path);
+
+    if (!_getFilesBelowPathQuery->exec()) {
+        return false;
+    }
+
+    while (_getFilesBelowPathQuery->next()) {
+        SyncJournalFileRecord rec;
+        fillFileRecordFromGetQuery(rec, *_getFilesBelowPathQuery);
+        rowCallback(rec);
+    }
+
+    return true;
+}
+
 bool SyncJournalDb::postSyncCleanup(const QSet<QString> &filepathsToKeep,
     const QSet<QString> &prefixesToKeep)
 {
@@ -1038,10 +1146,10 @@ bool SyncJournalDb::postSyncCleanup(const QSet<QString> &filepathsToKeep,
         return false;
     }
 
-    QStringList superfluousItems;
+    QByteArrayList superfluousItems;
 
     while (query.next()) {
-        const QString file = query.stringValue(1);
+        const QString file = query.baValue(1);
         bool keep = filepathsToKeep.contains(file);
         if (!keep) {
             foreach (const QString &prefix, prefixesToKeep) {
@@ -1052,12 +1160,12 @@ bool SyncJournalDb::postSyncCleanup(const QSet<QString> &filepathsToKeep,
             }
         }
         if (!keep) {
-            superfluousItems.append(query.stringValue(0));
+            superfluousItems.append(query.baValue(0));
         }
     }
 
     if (superfluousItems.count()) {
-        QString sql = "DELETE FROM metadata WHERE phash in (" + superfluousItems.join(",") + ")";
+        QByteArray sql = "DELETE FROM metadata WHERE phash in (" + superfluousItems.join(",") + ")";
         qCInfo(lcDb) << "Sync Journal cleanup for" << superfluousItems;
         SqlQuery delQuery(_db);
         delQuery.prepare(sql);
@@ -1103,7 +1211,7 @@ bool SyncJournalDb::updateFileRecordChecksum(const QString &filename,
 
     qCInfo(lcDb) << "Updating file checksum" << filename << contentChecksum << contentChecksumType;
 
-    qlonglong phash = getPHash(filename);
+    qlonglong phash = getPHash(filename.toUtf8());
     if (!checkConnect()) {
         qCWarning(lcDb) << "Failed to connect database.";
         return false;
@@ -1132,7 +1240,7 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
 
     qCInfo(lcDb) << "Updating local metadata for:" << filename << modtime << size << inode;
 
-    qlonglong phash = getPHash(filename);
+    qlonglong phash = getPHash(filename.toUtf8());
     if (!checkConnect()) {
         qCWarning(lcDb) << "Failed to connect database.";
         return false;
@@ -1328,7 +1436,7 @@ SyncJournalDb::UploadInfo SyncJournalDb::getUploadInfo(const QString &file)
             res._transferid = _getUploadInfoQuery->intValue(1);
             res._errorCount = _getUploadInfoQuery->intValue(2);
             res._size = _getUploadInfoQuery->int64Value(3);
-            res._modtime = Utility::qDateTimeFromTime_t(_getUploadInfoQuery->int64Value(4));
+            res._modtime = _getUploadInfoQuery->int64Value(4);
             res._valid = ok;
         }
     }
@@ -1350,7 +1458,7 @@ void SyncJournalDb::setUploadInfo(const QString &file, const SyncJournalDb::Uplo
         _setUploadInfoQuery->bindValue(3, i._transferid);
         _setUploadInfoQuery->bindValue(4, i._errorCount);
         _setUploadInfoQuery->bindValue(5, i._size);
-        _setUploadInfoQuery->bindValue(6, Utility::qDateTimeToTime_t(i._modtime));
+        _setUploadInfoQuery->bindValue(6, i._modtime);
 
         if (!_setUploadInfoQuery->exec()) {
             return;
@@ -1539,11 +1647,11 @@ void SyncJournalDb::setErrorBlacklistEntry(const SyncJournalErrorBlacklistRecord
     _setErrorBlacklistQuery->reset_and_clear_bindings();
     _setErrorBlacklistQuery->bindValue(1, item._file);
     _setErrorBlacklistQuery->bindValue(2, item._lastTryEtag);
-    _setErrorBlacklistQuery->bindValue(3, QString::number(item._lastTryModtime));
+    _setErrorBlacklistQuery->bindValue(3, item._lastTryModtime);
     _setErrorBlacklistQuery->bindValue(4, item._retryCount);
     _setErrorBlacklistQuery->bindValue(5, item._errorString);
-    _setErrorBlacklistQuery->bindValue(6, QString::number(item._lastTryTime));
-    _setErrorBlacklistQuery->bindValue(7, QString::number(item._ignoreDuration));
+    _setErrorBlacklistQuery->bindValue(6, item._lastTryTime);
+    _setErrorBlacklistQuery->bindValue(7, item._ignoreDuration);
     _setErrorBlacklistQuery->bindValue(8, item._renameTarget);
     _setErrorBlacklistQuery->bindValue(9, item._errorCategory);
     _setErrorBlacklistQuery->exec();
@@ -1591,7 +1699,7 @@ void SyncJournalDb::setPollInfo(const SyncJournalDb::PollInfo &info)
     } else {
         SqlQuery query("INSERT OR REPLACE INTO poll (path, modtime, pollpath) VALUES( ? , ? , ? )", _db);
         query.bindValue(1, info._file);
-        query.bindValue(2, QString::number(info._modtime));
+        query.bindValue(2, info._modtime);
         query.bindValue(3, info._url);
         query.exec();
     }
@@ -1651,7 +1759,7 @@ void SyncJournalDb::setSelectiveSyncList(SyncJournalDb::SelectiveSyncListType ty
     }
 }
 
-void SyncJournalDb::avoidRenamesOnNextSync(const QString &path)
+void SyncJournalDb::avoidRenamesOnNextSync(const QByteArray &path)
 {
     QMutexLocker locker(&_mutex);
 
@@ -1671,7 +1779,7 @@ void SyncJournalDb::avoidRenamesOnNextSync(const QString &path)
     avoidReadFromDbOnNextSync(path);
 }
 
-void SyncJournalDb::avoidReadFromDbOnNextSync(const QString &fileName)
+void SyncJournalDb::avoidReadFromDbOnNextSync(const QByteArray &fileName)
 {
     // Make sure that on the next sync, fileName is not read from the DB but uses the PROPFIND to
     // get the info from the server
@@ -1798,6 +1906,7 @@ void SyncJournalDb::setDataFingerprint(const QByteArray &dataFingerprint)
 
 void SyncJournalDb::clearFileTable()
 {
+    QMutexLocker lock(&_mutex);
     SqlQuery query(_db);
     query.prepare("DELETE FROM metadata;");
     query.exec();
index 8ad2b08520627b0522edea1357ac9f84120b6923..10324aba7e45819e74df22e51cb2db8a95e9010c 100644 (file)
@@ -23,6 +23,7 @@
 #include <qmutex.h>
 #include <QDateTime>
 #include <QHash>
+#include <functional>
 
 #include "common/utility.h"
 #include "common/ownsql.h"
@@ -54,7 +55,11 @@ public:
     static bool maybeMigrateDb(const QString &localPath, const QString &absoluteJournalPath);
 
     // To verify that the record could be found check with SyncJournalFileRecord::isValid()
-    bool getFileRecord(const QString &filename, SyncJournalFileRecord *rec);
+    bool getFileRecord(const QString &filename, SyncJournalFileRecord *rec) { return getFileRecord(filename.toUtf8(), rec); }
+    bool getFileRecord(const QByteArray &filename, SyncJournalFileRecord *rec);
+    bool getFileRecordByInode(quint64 inode, SyncJournalFileRecord *rec);
+    bool getFileRecordByFileId(const QByteArray &fileId, SyncJournalFileRecord *rec);
+    bool getFilesBelowPath(const QByteArray &path, const std::function<void(const SyncJournalFileRecord&)> &rowCallback);
     bool setFileRecord(const SyncJournalFileRecord &record);
 
     /// Like setFileRecord, but preserves checksums
@@ -72,7 +77,7 @@ public:
 
     QString databaseFilePath() const;
 
-    static qint64 getPHash(const QString &);
+    static qint64 getPHash(const QByteArray &);
 
     void setErrorBlacklistEntry(const SyncJournalErrorBlacklistRecord &item);
     void wipeErrorBlacklistEntry(const QString &file);
@@ -105,7 +110,7 @@ public:
         int _chunk;
         int _transferid;
         quint64 _size; //currently unused
-        QDateTime _modtime;
+        qint64 _modtime;
         int _errorCount;
         bool _valid;
     };
@@ -114,7 +119,7 @@ public:
     {
         QString _file;
         QString _url;
-        time_t _modtime;
+        qint64 _modtime;
     };
 
     DownloadInfo getDownloadInfo(const QString &file);
@@ -130,7 +135,8 @@ public:
     SyncJournalErrorBlacklistRecord errorBlacklistEntry(const QString &);
     bool deleteStaleErrorBlacklistEntries(const QSet<QString> &keep);
 
-    void avoidRenamesOnNextSync(const QString &path);
+    void avoidRenamesOnNextSync(const QString &path) { avoidRenamesOnNextSync(path.toUtf8()); }
+    void avoidRenamesOnNextSync(const QByteArray &path);
     void setPollInfo(const PollInfo &);
     QVector<PollInfo> getPollInfos();
 
@@ -164,7 +170,8 @@ public:
      * _csync_detect_update skip them), the _invalid_ marker will stay and it. And any
      * child items in the db will be ignored when reading a remote tree from the database.
      */
-    void avoidReadFromDbOnNextSync(const QString &fileName);
+    void avoidReadFromDbOnNextSync(const QString &fileName) { avoidReadFromDbOnNextSync(fileName.toUtf8()); }
+    void avoidReadFromDbOnNextSync(const QByteArray &fileName);
 
     /**
      * Ensures full remote discovery happens on the next sync.
@@ -233,6 +240,9 @@ private:
 
     // NOTE! when adding a query, don't forget to reset it in SyncJournalDb::close
     QScopedPointer<SqlQuery> _getFileRecordQuery;
+    QScopedPointer<SqlQuery> _getFileRecordQueryByInode;
+    QScopedPointer<SqlQuery> _getFileRecordQueryByFileId;
+    QScopedPointer<SqlQuery> _getFilesBelowPathQuery;
     QScopedPointer<SqlQuery> _setFileRecordQuery;
     QScopedPointer<SqlQuery> _setFileRecordChecksumQuery;
     QScopedPointer<SqlQuery> _setFileRecordLocalMetadataQuery;
@@ -258,7 +268,7 @@ private:
      * It means that they should not be written to the DB in any case since doing
      * that would write the etag and would void the purpose of avoidReadFromDbOnNextSync
      */
-    QList<QString> _avoidReadFromDbOnNextSyncFilter;
+    QList<QByteArray> _avoidReadFromDbOnNextSyncFilter;
 
     /** The journal mode to use for the db.
      *
index c6a77b997e753c2b3f2e6c8fd96856a92ef52657..226c25d6c8622cb1baf539876d4b61f8d7ba16c9 100644 (file)
@@ -52,7 +52,7 @@ bool operator==(const SyncJournalFileRecord &lhs,
 {
     return lhs._path == rhs._path
         && lhs._inode == rhs._inode
-        && lhs._modtime.toTime_t() == rhs._modtime.toTime_t()
+        && lhs._modtime == rhs._modtime
         && lhs._type == rhs._type
         && lhs._etag == rhs._etag
         && lhs._fileId == rhs._fileId
index c6008713e3cafa94013e2d790a33fd9700038cd0..bc34ef1354279e74e45c5be7a4dbf818b9c766a1 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "ocsynclib.h"
 #include "remotepermissions.h"
+#include "common/utility.h"
 
 namespace OCC {
 
@@ -50,10 +51,11 @@ public:
      * It is used in the construction of private links.
      */
     QByteArray numericFileId() const;
+    QDateTime modDateTime() const { return Utility::qDateTimeFromTime_t(_modtime); }
 
-    QString _path;
+    QByteArray _path;
     quint64 _inode;
-    QDateTime _modtime;
+    qint64 _modtime;
     int _type;
     QByteArray _etag;
     QByteArray _fileId;
@@ -94,14 +96,14 @@ public:
     /// The error category. Sometimes used for special actions.
     Category _errorCategory;
 
-    time_t _lastTryModtime;
+    qint64 _lastTryModtime;
     QByteArray _lastTryEtag;
 
     /// The last time the operation was attempted (in s since epoch).
-    time_t _lastTryTime;
+    qint64 _lastTryTime;
 
     /// The number of seconds the file shall be ignored.
-    time_t _ignoreDuration;
+    qint64 _ignoreDuration;
 
     QString _file;
     QString _renameTarget;
index acb1cc7c2fc2696175484a078b2799b6e7d0985a..7014054317305fdcd3fc701081c69e04db36dadc 100644 (file)
@@ -67,7 +67,6 @@ set(csync_SRCS
   csync.cpp
   csync_exclude.cpp
   csync_log.cpp
-  csync_statedb.cpp
   csync_time.c
   csync_util.cpp
   csync_misc.cpp
index 6c36637b8a4a55fc28e81d6abebacf43b1aa438a..d2838884ac06da304ea365b833824e58ba7ba465 100644 (file)
@@ -36,7 +36,6 @@
 #include "c_lib.h"
 #include "csync_private.h"
 #include "csync_exclude.h"
-#include "csync_statedb.h"
 #include "csync_time.h"
 #include "csync_util.h"
 #include "csync_misc.h"
@@ -52,7 +51,9 @@
 #include "common/c_jhash.h"
 
 
-csync_s::csync_s(const char *localUri, const char *db_file) {
+csync_s::csync_s(const char *localUri, OCC::SyncJournalDb *statedb)
+  : statedb(statedb)
+{
   size_t len = 0;
 
   /* remove trailing slashes */
@@ -60,8 +61,6 @@ csync_s::csync_s(const char *localUri, const char *db_file) {
   while(len > 0 && localUri[len - 1] == '/') --len;
 
   local.uri = c_strndup(localUri, len);
-
-  statedb.file = c_strdup(db_file);
 }
 
 int csync_update(CSYNC *ctx) {
@@ -74,12 +73,6 @@ int csync_update(CSYNC *ctx) {
   }
   ctx->status_code = CSYNC_STATUS_OK;
 
-  /* Path of database file is set in csync_init */
-  if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
-      rc = -1;
-      return rc;
-  }
-
   ctx->status_code = CSYNC_STATUS_OK;
 
   csync_memstat_check();
@@ -97,7 +90,7 @@ int csync_update(CSYNC *ctx) {
     if(ctx->status_code == CSYNC_STATUS_OK) {
         ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
     }
-    goto out;
+    return rc;
   }
 
   csync_gettime(&finish);
@@ -116,7 +109,7 @@ int csync_update(CSYNC *ctx) {
       if(ctx->status_code == CSYNC_STATUS_OK) {
           ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
       }
-      goto out;
+      return rc;
   }
 
   csync_gettime(&finish);
@@ -130,9 +123,6 @@ int csync_update(CSYNC *ctx) {
   ctx->status |= CSYNC_STATUS_UPDATE;
 
   rc = 0;
-
-out:
-  csync_statedb_close(ctx);
   return rc;
 }
 
@@ -149,11 +139,6 @@ int csync_reconcile(CSYNC *ctx) {
   /* Reconciliation for local replica */
   csync_gettime(&start);
 
-  if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
-    rc = -1;
-    return rc;
-  }
-
   ctx->current = LOCAL_REPLICA;
 
   rc = csync_reconcile_updates(ctx);
@@ -168,7 +153,7 @@ int csync_reconcile(CSYNC *ctx) {
       if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
           ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
       }
-      goto out;
+      return rc;
   }
 
   /* Reconciliation for remote replica */
@@ -188,16 +173,13 @@ int csync_reconcile(CSYNC *ctx) {
       if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
           ctx->status_code = csync_errno_to_status(errno,  CSYNC_STATUS_RECONCILE_ERROR );
       }
-      goto out;
+      return rc;
   }
 
   ctx->status |= CSYNC_STATUS_RECONCILE;
 
   rc = 0;
-
-out:
-  csync_statedb_close(ctx);
-  return 0;
+  return rc;
 }
 
 /*
@@ -326,13 +308,6 @@ int csync_s::reinitialize() {
 
   status_code = CSYNC_STATUS_OK;
 
-  if (statedb.db != NULL
-      && csync_statedb_close(this) < 0) {
-    CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "ERR: closing of statedb failed.");
-    rc = -1;
-  }
-  statedb.db = NULL;
-
   remote.read_from_db = 0;
   read_remote_from_db = true;
   db_is_empty = false;
@@ -348,13 +323,6 @@ int csync_s::reinitialize() {
 }
 
 csync_s::~csync_s() {
-  if (statedb.db != NULL
-      && csync_statedb_close(this) < 0) {
-    CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "ERR: closing of statedb failed.");
-  }
-  statedb.db = NULL;
-
-  SAFE_FREE(statedb.file);
   SAFE_FREE(local.uri);
   SAFE_FREE(error_string);
 }
index ef2d3badad043144ded395130cd762f8e274633e..4dfa989f159ba455adae7398bcb52e20034fd5ba 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "std/c_private.h"
 #include "ocsynclib.h"
+#include "common/syncjournalfilerecord.h"
+
 #include <sys/stat.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -200,6 +202,22 @@ struct OCSYNC_EXPORT csync_file_stat_s {
     , error_status(CSYNC_STATUS_OK)
     , instruction(CSYNC_INSTRUCTION_NONE)
   { }
+
+  static std::unique_ptr<csync_file_stat_t> fromSyncJournalFileRecord(const OCC::SyncJournalFileRecord &rec)
+  {
+    std::unique_ptr<csync_file_stat_t> st(new csync_file_stat_t);
+    st->path = rec._path;
+    st->inode = rec._inode;
+    st->modtime = rec._modtime;
+    st->type = static_cast<csync_ftw_type_e>(rec._type);
+    st->etag = rec._etag;
+    st->file_id = rec._fileId;
+    st->remotePerm = rec._remotePerm;
+    st->size = rec._fileSize;
+    st->has_ignored_files = rec._serverHasIgnoredFiles;
+    st->checksumHeader = rec._checksumHeader;
+    return st;
+  }
 };
 
 /**
index f3398f7a7bccfc38ff3394b5dd6944e7b2d7619d..c898eeabeb11f0d47ee481ad98bd31d17eab84d1 100644 (file)
@@ -39,6 +39,7 @@
 #include <sqlite3.h>
 #include <map>
 
+#include "common/syncjournaldb.h"
 #include "config_csync.h"
 #include "std/c_lib.h"
 #include "std/c_private.h"
@@ -103,17 +104,7 @@ struct OCSYNC_EXPORT csync_s {
   } callbacks;
   c_strlist_t *excludes = nullptr;
   
-  struct {
-    char *file = nullptr;
-    sqlite3 *db = nullptr;
-    bool exists = false;
-
-    sqlite3_stmt* by_hash_stmt = nullptr;
-    sqlite3_stmt* by_fileid_stmt = nullptr;
-    sqlite3_stmt* by_inode_stmt = nullptr;
-
-    int lastReturnValue;
-  } statedb;
+  OCC::SyncJournalDb *statedb;
 
   struct {
     std::map<QByteArray, QByteArray> folder_renamed_to; // map from->to
@@ -159,7 +150,7 @@ struct OCSYNC_EXPORT csync_s {
 
   bool ignore_hidden_files = true;
 
-  csync_s(const char *localUri, const char *db_file);
+  csync_s(const char *localUri, OCC::SyncJournalDb *statedb);
   ~csync_s();
   int reinitialize();
 
index 76fd084089610abfbbd8b2bba7fa65732fc7e518..2fdaa7f38ad063e20b0a2c0988895c0606c2767a 100644 (file)
@@ -24,7 +24,6 @@
 #include "csync_private.h"
 #include "csync_reconcile.h"
 #include "csync_util.h"
-#include "csync_statedb.h"
 #include "csync_rename.h"
 #include "common/c_jhash.h"
 #include "common/asserts.h"
@@ -104,8 +103,6 @@ static bool _csync_is_collision_safe_hash(const char *checksum_header)
  * source and the destination, have been changed, the newer file wins.
  */
 static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
-    std::unique_ptr<csync_file_stat_t> tmp;
-
     csync_s::FileMap *other_tree = nullptr;
 
     /* we need the opposite tree! */
@@ -153,35 +150,34 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
             }
             cur->instruction = CSYNC_INSTRUCTION_REMOVE;
             break;
-        case CSYNC_INSTRUCTION_EVAL_RENAME:
+        case CSYNC_INSTRUCTION_EVAL_RENAME: {
+            OCC::SyncJournalFileRecord base;
             if(ctx->current == LOCAL_REPLICA ) {
                 /* use the old name to find the "other" node */
-                tmp = csync_statedb_get_stat_by_inode(ctx, cur->inode);
+                ctx->statedb->getFileRecordByInode(cur->inode, &base);
                 qCDebug(lcReconcile, "Finding opposite temp through inode %" PRIu64 ": %s",
-                          cur->inode, tmp ? "true":"false");
+                          cur->inode, base.isValid() ? "true":"false");
             } else {
                 ASSERT( ctx->current == REMOTE_REPLICA );
-                tmp = csync_statedb_get_stat_by_file_id(ctx, cur->file_id);
+                ctx->statedb->getFileRecordByFileId(cur->file_id, &base);
                 qCDebug(lcReconcile, "Finding opposite temp through file ID %s: %s",
-                          cur->file_id.constData(), tmp ? "true":"false");
+                          cur->file_id.constData(), base.isValid() ? "true":"false");
             }
 
-            if( tmp ) {
-                if( !tmp->path.isEmpty() ) {
-                    /* First, check that the file is NOT in our tree (another file with the same name was added) */
-                    csync_s::FileMap *our_tree = ctx->current == REMOTE_REPLICA ? &ctx->remote.files : &ctx->local.files;
-                       if (our_tree->findFile(tmp->path)) {
-                        qCDebug(lcReconcile, "Origin found in our tree : %s", tmp->path.constData());
-                    } else {
+            if( base.isValid() ) {
+                /* First, check that the file is NOT in our tree (another file with the same name was added) */
+                csync_s::FileMap *our_tree = ctx->current == REMOTE_REPLICA ? &ctx->remote.files : &ctx->local.files;
+                       if (our_tree->findFile(base._path)) {
+                        qCDebug(lcReconcile, "Origin found in our tree : %s", base._path.constData());
+                } else {
                     /* Find the temporar file in the other tree.
                     * If the renamed file could not be found in the opposite tree, that is because it
                     * is not longer existing there, maybe because it was renamed or deleted.
                     * The journal is cleaned up later after propagation.
                     */
-                    other = other_tree->findFile(tmp->path);
+                    other = other_tree->findFile(base._path);
                     qCDebug(lcReconcile, "Temporary opposite (%s) %s",
-                            tmp->path.constData() , other ? "found": "not found" );
-                    }
+                            base._path.constData() , other ? "found": "not found" );
                 }
 
                 if(!other) {
@@ -213,9 +209,9 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
                     cur->instruction = CSYNC_INSTRUCTION_NONE;
                     other->instruction = CSYNC_INSTRUCTION_SYNC;
                 }
-           }
-
+            }
             break;
+        }
         default:
             break;
         }
diff --git a/src/csync/csync_statedb.cpp b/src/csync/csync_statedb.cpp
deleted file mode 100644 (file)
index b489b67..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * libcsync -- a library to sync a directory with another
- *
- * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
- * Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config_csync.h"
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <assert.h>
-#include <sqlite3.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "c_lib.h"
-#include "csync_private.h"
-#include "csync_statedb.h"
-#include "csync_util.h"
-#include "csync_misc.h"
-#include "csync_exclude.h"
-
-#include "c_string.h"
-#include "common/c_jhash.h"
-#include "c_utf8.h"
-#include "csync_time.h"
-
-#define CSYNC_LOG_CATEGORY_NAME "csync.statedb"
-#include "csync_log.h"
-#include "csync_rename.h"
-
-// Needed for PRIu64 on MinGW in C++ mode.
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#define BUF_SIZE 16
-
-#define sqlite_open(A, B) sqlite3_open_v2(A,B, SQLITE_OPEN_READONLY+SQLITE_OPEN_NOMUTEX, NULL)
-
-#define SQLTM_TIME 150
-#define SQLTM_COUNT 10
-
-#define SQLITE_BUSY_HANDLED(F) if(1) { \
-    int n = 0; \
-    do { rc = F ; \
-      if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) { \
-         n++; \
-         csync_sleep(SQLTM_TIME); \
-      } \
-    }while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED))); \
-  }
-
-
-void csync_set_statedb_exists(CSYNC *ctx, int val) {
-  ctx->statedb.exists = val;
-}
-
-int csync_get_statedb_exists(CSYNC *ctx) {
-  return ctx->statedb.exists;
-}
-
-static int _csync_check_db_integrity(sqlite3 *db) {
-    c_strlist_t *result = NULL;
-    int rc = -1;
-
-    result = csync_statedb_query(db, "PRAGMA quick_check;");
-    if (result != NULL) {
-        /* There is  a result */
-        if (result->count > 0) {
-            if (c_streq(result->vector[0], "ok")) {
-                rc = 0;
-            }
-        }
-        c_strlist_destroy(result);
-    }
-
-    if( sqlite3_threadsafe() == 0 ) {
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "* WARNING: SQLite module is not threadsafe!");
-        rc = -1;
-    }
-
-    return rc;
-}
-
-static int _csync_statedb_is_empty(sqlite3 *db) {
-  c_strlist_t *result = NULL;
-  int rc = 0;
-
-  result = csync_statedb_query(db, "SELECT COUNT(phash) FROM metadata LIMIT 1 OFFSET 0;");
-  if (result == NULL) {
-    rc = 1;
-  }
-  c_strlist_destroy(result);
-
-  return rc;
-}
-
-#ifndef NDEBUG
-static void sqlite_profile( void *x, const char* sql, sqlite3_uint64 time)
-{
-    (void)x;
-    CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
-              "_SQL_ %s: %llu", sql, time);
-
-}
-#endif
-
-int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
-  int rc = -1;
-  c_strlist_t *result = NULL;
-  sqlite3 *db = NULL;
-
-  if( !ctx ) {
-      return -1;
-  }
-
-  if (ctx->statedb.db) {
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open");
-      ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
-      return -1;
-  }
-
-  ctx->statedb.lastReturnValue = SQLITE_OK;
-
-  /* Openthe database */
-  if (sqlite_open(statedb, &db) != SQLITE_OK) {
-    const char *errmsg= sqlite3_errmsg(ctx->statedb.db);
-    CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.",
-              errmsg ? errmsg : "<no sqlite3 errormsg>");
-
-    rc = -1;
-    ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
-    goto out;
-  }
-
-  if (_csync_check_db_integrity(db) != 0) {
-      const char *errmsg= sqlite3_errmsg(db);
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: sqlite3 integrity check failed - bail out: %s.",
-                errmsg ? errmsg : "<no sqlite3 errormsg>");
-      rc = -1;
-      ctx->status_code = CSYNC_STATUS_STATEDB_CORRUPTED;
-      goto out;
-  }
-
-  if (_csync_statedb_is_empty(db)) {
-    CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb contents doesn't exist");
-    csync_set_statedb_exists(ctx, 0);
-  } else {
-    csync_set_statedb_exists(ctx, 1);
-  }
-
-  /* Print out the version */
-  //
-  result = csync_statedb_query(db, "SELECT sqlite_version();");
-  if (result && result->count >= 1) {
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3 version \"%s\"", *result->vector);
-  }
-  c_strlist_destroy(result);
-
-  /* optimization for speeding up SQLite */
-  result = csync_statedb_query(db, "PRAGMA synchronous = NORMAL;");
-  c_strlist_destroy(result);
-  result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
-  c_strlist_destroy(result);
-
-  /* set a busy handler with 5 seconds timeout */
-  sqlite3_busy_timeout(db, 5000);
-
-#ifndef NDEBUG
-  sqlite3_profile(db, sqlite_profile, 0 );
-#endif
-  *pdb = db;
-
-  CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Success");
-
-  return 0;
-out:
-  sqlite3_close(db);
-  return rc;
-}
-
-int csync_statedb_close(CSYNC *ctx) {
-  int rc = 0;
-
-  if (!ctx) {
-      return -1;
-  }
-
-  /* deallocate query resources */
-  if( ctx->statedb.by_fileid_stmt ) {
-      sqlite3_finalize(ctx->statedb.by_fileid_stmt);
-      ctx->statedb.by_fileid_stmt = NULL;
-  }
-  if( ctx->statedb.by_hash_stmt ) {
-      sqlite3_finalize(ctx->statedb.by_hash_stmt);
-      ctx->statedb.by_hash_stmt = NULL;
-  }
-  if( ctx->statedb.by_inode_stmt) {
-      sqlite3_finalize(ctx->statedb.by_inode_stmt);
-      ctx->statedb.by_inode_stmt = NULL;
-  }
-
-  ctx->statedb.lastReturnValue = SQLITE_OK;
-
-  int sr = sqlite3_close(ctx->statedb.db);
-  CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3_close=%d", sr);
-
-  ctx->statedb.db = 0;
-
-  return rc;
-}
-
-#define METADATA_QUERY                                             \
-    "path, inode, modtime, type, md5, fileid, remotePerm, " \
-    "filesize, ignoredChildrenRemote, "                            \
-    "contentchecksumtype.name || ':' || contentChecksum "          \
-    "FROM metadata "                                               \
-    "LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
-
-// This funciton parses a line from the metadata table into the given csync_file_stat
-// structure which it is also allocating.
-// Note that this function calls laso sqlite3_step to actually get the info from db and
-// returns the sqlite return type.
-static int _csync_file_stat_from_metadata_table( std::unique_ptr<csync_file_stat_t> &st, sqlite3_stmt *stmt )
-{
-    int rc = SQLITE_ERROR;
-
-    if( ! stmt ) {
-       CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Fatal: Statement is NULL.");
-       return SQLITE_ERROR;
-    }
-
-    // Callers should all use METADATA_QUERY for their column list.
-    assert(sqlite3_column_count(stmt) == 10);
-
-    SQLITE_BUSY_HANDLED( sqlite3_step(stmt) );
-
-    if( rc == SQLITE_ROW ) {
-        st.reset(new csync_file_stat_t);
-
-        st->path = (char*)sqlite3_column_text(stmt, 0);
-        st->inode = sqlite3_column_int64(stmt, 1);
-        st->modtime = strtoul((char*)sqlite3_column_text(stmt, 2), NULL, 10);
-        st->type = static_cast<enum csync_ftw_type_e>(sqlite3_column_int(stmt, 3));
-        st->etag = (char*)sqlite3_column_text(stmt, 4);
-        st->file_id = (char*)sqlite3_column_text(stmt, 5);
-        const char *permStr = (char *)sqlite3_column_text(stmt, 6);
-        // If permStr is empty, construct a null RemotePermissions.  We make sure that non-null
-        // permissions are never empty in RemotePermissions.toString()
-        st->remotePerm = permStr && *permStr ? OCC::RemotePermissions(permStr) : OCC::RemotePermissions();
-        st->size = sqlite3_column_int64(stmt, 7);
-        st->has_ignored_files = sqlite3_column_int(stmt, 8);
-        st->checksumHeader = (char *)sqlite3_column_text(stmt, 9);
-    } else {
-        if( rc != SQLITE_DONE ) {
-            CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Query results in %d", rc);
-        }
-    }
-    return rc;
-}
-
-/* caller must free the memory */
-std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_path(CSYNC *ctx, const QByteArray &path)
-{
-  std::unique_ptr<csync_file_stat_t> st;
-  int rc;
-
-  if( !ctx || ctx->db_is_empty ) {
-      return NULL;
-  }
-
-  if( ctx->statedb.by_hash_stmt == NULL ) {
-      const char *hash_query = "SELECT " METADATA_QUERY " WHERE phash=?1";
-
-      SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, hash_query, strlen(hash_query), &ctx->statedb.by_hash_stmt, NULL));
-      ctx->statedb.lastReturnValue = rc;
-      if( rc != SQLITE_OK ) {
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
-          return NULL;
-      }
-  }
-
-  if( ctx->statedb.by_hash_stmt == NULL ) {
-    return NULL;
-  }
-
-  uint64_t phash = c_jhash64((const uint8_t*)path.constData(), path.size(), 0);
-  sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash);
-
-  rc = _csync_file_stat_from_metadata_table(st, ctx->statedb.by_hash_stmt);
-  ctx->statedb.lastReturnValue = rc;
-  if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) )  {
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
-  }
-  sqlite3_reset(ctx->statedb.by_hash_stmt);
-
-  return st;
-}
-
-std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_file_id(CSYNC *ctx,
-                                                      const char *file_id ) {
-    std::unique_ptr<csync_file_stat_t> st;
-    int rc = 0;
-
-    if (!file_id) {
-        return 0;
-    }
-    if (c_streq(file_id, "")) {
-        return 0;
-    }
-
-    if( !ctx || ctx->db_is_empty ) {
-        return NULL;
-    }
-
-    if( ctx->statedb.by_fileid_stmt == NULL ) {
-        const char *query = "SELECT " METADATA_QUERY " WHERE fileid=?1";
-
-        SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, query, strlen(query), &ctx->statedb.by_fileid_stmt, NULL));
-        ctx->statedb.lastReturnValue = rc;
-        if( rc != SQLITE_OK ) {
-            CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for file id query.");
-            return NULL;
-        }
-    }
-
-    /* bind the query value */
-    sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
-
-    rc = _csync_file_stat_from_metadata_table(st, ctx->statedb.by_fileid_stmt);
-    ctx->statedb.lastReturnValue = rc;
-    if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
-    }
-    // clear the resources used by the statement.
-    sqlite3_reset(ctx->statedb.by_fileid_stmt);
-
-    return st;
-}
-
-/* caller must free the memory */
-std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_inode(CSYNC *ctx,
-                                                  uint64_t inode)
-{
-  std::unique_ptr<csync_file_stat_t> st;
-  int rc;
-
-  if (!inode) {
-      return NULL;
-  }
-
-  if( !ctx || ctx->db_is_empty ) {
-      return NULL;
-  }
-
-  if( ctx->statedb.by_inode_stmt == NULL ) {
-      const char *inode_query = "SELECT " METADATA_QUERY " WHERE inode=?1";
-
-      SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, inode_query, strlen(inode_query), &ctx->statedb.by_inode_stmt, NULL));
-      ctx->statedb.lastReturnValue = rc;
-      if( rc != SQLITE_OK ) {
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for inode query.");
-          return NULL;
-      }
-  }
-
-  if( ctx->statedb.by_inode_stmt == NULL ) {
-    return NULL;
-  }
-
-  sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode);
-
-  rc = _csync_file_stat_from_metadata_table(st, ctx->statedb.by_inode_stmt);
-  ctx->statedb.lastReturnValue = rc;
-  if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
-  }
-  sqlite3_reset(ctx->statedb.by_inode_stmt);
-
-  return st;
-}
-
-int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
-    int rc;
-    sqlite3_stmt *stmt = NULL;
-    int64_t cnt = 0;
-
-    if( !path ) {
-        return -1;
-    }
-
-    if( !ctx || ctx->db_is_empty ) {
-        return -1;
-    }
-
-    /*  Select the entries for anything that starts with  (path+'/')
-     * In other words, anything that is between  path+'/' and path+'0',
-     * (because '0' follows '/' in ascii)
-     */
-    const char *below_path_query = "SELECT " METADATA_QUERY " WHERE path > (?||'/') AND path < (?||'0') ORDER BY path||'/' ASC";
-    SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, below_path_query, -1, &stmt, NULL));
-    ctx->statedb.lastReturnValue = rc;
-    if( rc != SQLITE_OK ) {
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
-      return -1;
-    }
-
-    if (stmt == NULL) {
-      return -1;
-    }
-
-    sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
-    sqlite3_bind_text(stmt, 2, path, -1, SQLITE_STATIC);
-
-    cnt = 0;
-
-    ctx->statedb.lastReturnValue = rc;
-    do {
-        std::unique_ptr<csync_file_stat_t> st;
-
-        rc = _csync_file_stat_from_metadata_table(st, stmt);
-        if( st ) {
-            /* When selective sync is used, the database may have subtrees with a parent
-             * whose etag (md5) is _invalid_. These are ignored and shall not appear in the
-             * remote tree.
-             * Sometimes folders that are not ignored by selective sync get marked as
-             * _invalid_, but that is not a problem as the next discovery will retrieve
-             * their correct etags again and we don't run into this case.
-             */
-            if( st->etag == "_invalid_") {
-                CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s selective sync excluded", st->path.constData());
-                QByteArray skipbase = st->path;
-                skipbase += '/';
-
-                /* Skip over all entries with the same base path. Note that this depends
-                 * strongly on the ordering of the retrieved items. */
-                do {
-                    st.reset();
-                    rc = _csync_file_stat_from_metadata_table(st, stmt);
-                    if( st ) {
-                        if( !st->path.startsWith(skipbase) )
-                            break;
-                        CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s selective sync excluded because the parent is", st->path.constData());
-                    }
-                } while( rc == SQLITE_ROW );
-
-                /* End of data? */
-                if( rc != SQLITE_ROW || !st ) {
-                    continue;
-                }
-            }
-
-            /* Check for exclusion from the tree.
-             * Note that this is only a safety net in case the ignore list changes
-             * without a full remote discovery being triggered. */
-            CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type);
-            if (excluded != CSYNC_NOT_EXCLUDED) {
-                CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", st->path.constData(), excluded);
-
-                if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
-                        || excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
-                    st.reset();
-                    continue;
-                }
-
-                st->instruction = CSYNC_INSTRUCTION_IGNORE;
-            }
-
-            /* store into result list. */
-            QByteArray path = st->path;
-            ctx->remote.files[path] = std::move(st);
-            cnt++;
-        }
-    } while( rc == SQLITE_ROW );
-
-    ctx->statedb.lastReturnValue = rc;
-    if( rc != SQLITE_DONE ) {
-        ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
-    } else {
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%" PRId64 " entries read below path %s from db.", cnt, path);
-    }
-    sqlite3_finalize(stmt);
-
-    return 0;
-}
-
-/* query the statedb, caller must free the memory */
-c_strlist_t *csync_statedb_query(sqlite3 *db,
-                                 const char *statement) {
-  int err = SQLITE_OK;
-  int rc = SQLITE_OK;
-  size_t i = 0;
-  size_t busy_count = 0;
-  size_t retry_count = 0;
-  size_t column_count = 0;
-  sqlite3_stmt *stmt;
-  const char *tail = NULL;
-  const char *field = NULL;
-  c_strlist_t *result = NULL;
-  int row = 0;
-
-  do {
-    /* compile SQL program into a virtual machine, reattempteing if busy */
-    do {
-      if (busy_count) {
-        csync_sleep(100);
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3_prepare: BUSY counter: %zu", busy_count);
-      }
-      err = sqlite3_prepare(db, statement, -1, &stmt, &tail);
-    } while (err == SQLITE_BUSY && busy_count ++ < 120);
-
-    if (err != SQLITE_OK) {
-      if (err == SQLITE_BUSY) {
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Gave up waiting for lock to clear");
-      }
-      CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN,
-                "sqlite3_compile error: %s - on query %s",
-                sqlite3_errmsg(db), statement);
-      break;
-    } else {
-      busy_count = 0;
-      column_count = sqlite3_column_count(stmt);
-
-      /* execute virtual machine by iterating over rows */
-      for(;;) {
-        err = sqlite3_step(stmt);
-
-        if (err == SQLITE_BUSY) {
-          if (busy_count++ > 120) {
-            CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Busy counter has reached its maximum. Aborting this sql statement");
-            break;
-          }
-          csync_sleep(100);
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_step: BUSY counter: %zu", busy_count);
-          continue;
-        }
-
-        if (err == SQLITE_MISUSE) {
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite3_step: MISUSE!!");
-        }
-
-        if (err == SQLITE_DONE) {
-          if (result == NULL) {
-            result = c_strlist_new(1);
-          }
-          break;
-        }
-
-        if (err == SQLITE_ERROR) {
-          break;
-        }
-
-       row++;
-        if( result ) {
-            result = c_strlist_expand(result, row*column_count);
-        } else {
-            result = c_strlist_new(column_count);
-        }
-
-        if (result == NULL) {
-          return NULL;
-        }
-
-        /* iterate over columns */
-        for (i = 0; i < column_count; i++) {
-          field = (const char *) sqlite3_column_text(stmt, i);
-          if (!field)
-              field = "";
-          // CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_column_text: %s", field);
-          if (c_strlist_add(result, field) < 0) {
-            c_strlist_destroy(result);
-            return NULL;
-          }
-        }
-      } /* end infinite for loop */
-
-      /* deallocate vm resources */
-      rc = sqlite3_finalize(stmt);
-
-      if (err != SQLITE_DONE && rc != SQLITE_SCHEMA) {
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite_step error: %s - on query: %s", sqlite3_errmsg(db), statement);
-        if (result != NULL) {
-          c_strlist_destroy(result);
-        }
-        return NULL;
-      }
-
-      if (rc == SQLITE_SCHEMA) {
-        retry_count ++;
-        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "SQLITE_SCHEMA error occurred on query: %s", statement);
-        if (retry_count < 10) {
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Retrying now.");
-        } else {
-          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "RETRY count has reached its maximum. Aborting statement: %s", statement);
-          if (result != NULL) {
-            c_strlist_destroy(result);
-          }
-          result = c_strlist_new(1);
-        }
-      }
-    }
-  } while (rc == SQLITE_SCHEMA && retry_count < 10);
-
-  return result;
-}
-
-/* vim: set ts=8 sw=2 et cindent: */
diff --git a/src/csync/csync_statedb.h b/src/csync/csync_statedb.h
deleted file mode 100644 (file)
index 28c1cc8..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * libcsync -- a library to sync a directory with another
- *
- * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
- * Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file csync_private.h
- *
- * @brief Private interface of csync
- *
- * @defgroup csyncstatedbInternals csync statedb internals
- * @ingroup csyncInternalAPI
- *
- * @{
- */
-
-#ifndef _CSYNC_STATEDB_H
-#define _CSYNC_STATEDB_H
-
-#include "c_lib.h"
-#include "csync_private.h"
-
-void csync_set_statedb_exists(CSYNC *ctx, int val);
-
-int csync_get_statedb_exists(CSYNC *ctx);
-
-/**
- * @brief Load the statedb.
- *
- * This function tries to load the statedb. If it doesn't exists it creates
- * the sqlite3 database, but doesn't create the tables. This will be done when
- * csync gets destroyed.
- *
- * @param ctx      The csync context.
- * @param statedb  Path to the statedb file (sqlite3 db).
- *
- * @return 0 on success, less than 0 if an error occurred with errno set.
- */
-OCSYNC_EXPORT int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb);
-
-OCSYNC_EXPORT int csync_statedb_close(CSYNC *ctx);
-
-OCSYNC_EXPORT std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_path(CSYNC *ctx, const QByteArray &path);
-
-OCSYNC_EXPORT std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_inode(CSYNC *ctx, uint64_t inode);
-
-OCSYNC_EXPORT std::unique_ptr<csync_file_stat_t> csync_statedb_get_stat_by_file_id(CSYNC *ctx, const char *file_id);
-
-/**
- * @brief Query all files metadata inside and below a path.
- * @param ctx        The csync context.
- * @param path       The path.
- *
- * This function queries all metadata of all files inside or below the
- * given path. The result is a linear string list with a multiple of 9
- * entries. For each result file there are 9 strings which are phash,
- * path, inode, uid, gid, mode, modtime, type and md5 (unique id).
- *
- * Note that not only the files in the given path are part of the result
- * but also the files in directories below the given path. Ie. if the
- * parameter path is /home/kf/test, we have /home/kf/test/file.txt in
- * the result but also /home/kf/test/homework/another_file.txt
- *
- * @return   A stringlist containing a multiple of 9 entries.
- */
-int csync_statedb_get_below_path(CSYNC *ctx, const char *path);
-
-/**
- * @brief A generic statedb query.
- *
- * @param ctx        The csync context.
- * @param statement  The SQL statement to execute
- * 
- * @return   A stringlist of the entries of a column. An emtpy stringlist if
- *           nothing has been found. NULL on error.
- */
-c_strlist_t *csync_statedb_query(sqlite3 *db, const char *statement);
-
-/**
- * }@
- */
-#endif /* _CSYNC_STATEDB_H */
-/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
index c42eaa9280cfae22f73c3a50347ecfa1be5011a5..8f88c324b678881a6097bc34e712753ec179e572 100644 (file)
@@ -35,7 +35,6 @@
 
 #include "csync_private.h"
 #include "csync_exclude.h"
-#include "csync_statedb.h"
 #include "csync_update.h"
 #include "csync_util.h"
 #include "csync_misc.h"
@@ -74,10 +73,6 @@ static bool _csync_sameextension(const char *p1, const char *p2) {
 }
 #endif
 
-static bool _last_db_return_error(CSYNC* ctx) {
-    return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW;
-}
-
 static QByteArray _rel_to_abs(CSYNC* ctx, const QByteArray &relativePath) {
     return QByteArray() % const_cast<const char *>(ctx->local.uri) % '/' % relativePath;
 }
@@ -111,7 +106,7 @@ static bool _csync_mtime_equal(time_t a, time_t b)
  * See doc/dev/sync-algorithm.md for an overview.
  */
 static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
-  std::unique_ptr<csync_file_stat_t> tmp;
+  OCC::SyncJournalFileRecord base;
   CSYNC_EXCLUDE_TYPE excluded;
 
   if (fs == NULL) {
@@ -173,48 +168,46 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
    * renamed, the db gets queried by the inode of the file as that one
    * does not change on rename.
    */
-  tmp = csync_statedb_get_stat_by_path(ctx, fs->path);
-
-  if(_last_db_return_error(ctx)) {
+  if(!ctx->statedb->getFileRecord(fs->path, &base)) {
       ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
       return -1;
   }
 
-  if(tmp && tmp->path == fs->path ) { /* there is an entry in the database */
+  if(base.isValid()) { /* there is an entry in the database */
       /* we have an update! */
       qCInfo(lcUpdate, "Database entry found, compare: %" PRId64 " <-> %" PRId64
                                           ", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
                                           ", size: %" PRId64 " <-> %" PRId64 ", perms: %x <-> %x, ignore: %d",
-                ((int64_t) fs->modtime), ((int64_t) tmp->modtime),
-                fs->etag.constData(), tmp->etag.constData(), (uint64_t) fs->inode, (uint64_t) tmp->inode,
-                (uint64_t) fs->size, (uint64_t) tmp->size, *reinterpret_cast<short*>(&fs->remotePerm), *reinterpret_cast<short*>(&tmp->remotePerm), tmp->has_ignored_files );
-      if (ctx->current == REMOTE_REPLICA && fs->etag != tmp->etag) {
+                ((int64_t) fs->modtime), ((int64_t) base._modtime),
+                fs->etag.constData(), base._etag.constData(), (uint64_t) fs->inode, (uint64_t) base._inode,
+                (uint64_t) fs->size, (uint64_t) base._fileSize, *reinterpret_cast<short*>(&fs->remotePerm), *reinterpret_cast<short*>(&base._remotePerm), base._serverHasIgnoredFiles );
+      if (ctx->current == REMOTE_REPLICA && fs->etag != base._etag) {
           fs->instruction = CSYNC_INSTRUCTION_EVAL;
 
           // Preserve the EVAL flag later on if the type has changed.
-          if (tmp->type != fs->type) {
+          if (base._type != fs->type) {
               fs->child_modified = true;
           }
 
           goto out;
       }
       if (ctx->current == LOCAL_REPLICA &&
-              (!_csync_mtime_equal(fs->modtime, tmp->modtime)
+              (!_csync_mtime_equal(fs->modtime, base._modtime)
                // zero size in statedb can happen during migration
-               || (tmp->size != 0 && fs->size != tmp->size))) {
+               || (base._fileSize != 0 && fs->size != base._fileSize))) {
 
           // Checksum comparison at this stage is only enabled for .eml files,
           // check #4754 #4755
           bool isEmlFile = csync_fnmatch("*.eml", fs->path, FNM_CASEFOLD) == 0;
-          if (isEmlFile && fs->size == tmp->size && !tmp->checksumHeader.isEmpty()) {
+          if (isEmlFile && fs->size == base._fileSize && !base._checksumHeader.isEmpty()) {
               if (ctx->callbacks.checksum_hook) {
                   fs->checksumHeader = ctx->callbacks.checksum_hook(
-                      _rel_to_abs(ctx, fs->path), tmp->checksumHeader,
+                      _rel_to_abs(ctx, fs->path), base._checksumHeader,
                       ctx->callbacks.checksum_userdata);
               }
               bool checksumIdentical = false;
               if (!fs->checksumHeader.isEmpty()) {
-                  checksumIdentical = fs->checksumHeader == tmp->checksumHeader;
+                  checksumIdentical = fs->checksumHeader == base._checksumHeader;
               }
               if (checksumIdentical) {
                   qCDebug(lcUpdate, "NOTE: Checksums are identical, file did not actually change: %s", fs->path.constData());
@@ -224,16 +217,16 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
           }
 
           // Preserve the EVAL flag later on if the type has changed.
-          if (tmp->type != fs->type) {
+          if (base._type != fs->type) {
               fs->child_modified = true;
           }
 
           fs->instruction = CSYNC_INSTRUCTION_EVAL;
           goto out;
       }
-      bool metadata_differ = (ctx->current == REMOTE_REPLICA && (fs->file_id != tmp->file_id
-                                                          || fs->remotePerm != tmp->remotePerm))
-                           || (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode);
+      bool metadata_differ = (ctx->current == REMOTE_REPLICA && (fs->file_id != base._fileId
+                                                          || fs->remotePerm != base._remotePerm))
+                           || (ctx->current == LOCAL_REPLICA && fs->inode != base._inode);
       if (fs->type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA
               && !metadata_differ && ctx->read_remote_from_db) {
           /* If both etag and file id are equal for a directory, read all contents from
@@ -248,7 +241,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
        * that so that the reconciler can make advantage of.
        */
       if( ctx->current == REMOTE_REPLICA ) {
-          fs->has_ignored_files = tmp->has_ignored_files;
+          fs->has_ignored_files = base._serverHasIgnoredFiles;
       }
       if (metadata_differ) {
           /* file id or permissions has changed. Which means we need to update them in the DB. */
@@ -262,9 +255,8 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
       if (ctx->current == LOCAL_REPLICA) {
           qCDebug(lcUpdate, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode);
 
-          tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
-
-          if(_last_db_return_error(ctx)) {
+          OCC::SyncJournalFileRecord base;
+          if(!ctx->statedb->getFileRecordByInode(fs->inode, &base)) {
               ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
               return -1;
           }
@@ -273,23 +265,23 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
           fs->instruction = CSYNC_INSTRUCTION_NEW;
 
           bool isRename =
-              tmp && tmp->inode == fs->inode && tmp->type == fs->type
-                  && (tmp->modtime == fs->modtime || fs->type == CSYNC_FTW_TYPE_DIR)
+              base.isValid() && base._inode == fs->inode && base._type == fs->type
+                  && (base._modtime == fs->modtime || fs->type == CSYNC_FTW_TYPE_DIR)
 #ifdef NO_RENAME_EXTENSION
-                  && _csync_sameextension(tmp->path, fs->path)
+                  && _csync_sameextension(base._path, fs->path)
 #endif
               ;
 
 
           // Verify the checksum where possible
-          if (isRename && !tmp->checksumHeader.isEmpty() && ctx->callbacks.checksum_hook
+          if (isRename && !base._checksumHeader.isEmpty() && ctx->callbacks.checksum_hook
               && fs->type == CSYNC_FTW_TYPE_FILE) {
                   fs->checksumHeader = ctx->callbacks.checksum_hook(
-                      _rel_to_abs(ctx, fs->path), tmp->checksumHeader,
+                      _rel_to_abs(ctx, fs->path), base._checksumHeader,
                       ctx->callbacks.checksum_userdata);
               if (!fs->checksumHeader.isEmpty()) {
-                  qCDebug(lcUpdate, "checking checksum of potential rename %s %s <-> %s", fs->path.constData(), fs->checksumHeader.constData(), tmp->checksumHeader.constData());
-                  isRename = fs->checksumHeader == tmp->checksumHeader;
+                  qCDebug(lcUpdate, "checking checksum of potential rename %s %s <-> %s", fs->path.constData(), fs->checksumHeader.constData(), base._checksumHeader.constData());
+                  isRename = fs->checksumHeader == base._checksumHeader;
               }
           }
 
@@ -298,31 +290,30 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
               /* inode found so the file has been renamed */
               fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
               if (fs->type == CSYNC_FTW_TYPE_DIR) {
-                  csync_rename_record(ctx, tmp->path, fs->path);
+                  csync_rename_record(ctx, base._path, fs->path);
               }
           }
           goto out;
 
       } else {
           /* Remote Replica Rename check */
-          tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
-
-          if(_last_db_return_error(ctx)) {
+          OCC::SyncJournalFileRecord base;
+          if(!ctx->statedb->getFileRecordByFileId(fs->file_id, &base)) {
               ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
               return -1;
           }
-          if(tmp ) {                           /* tmp existing at all */
-              if (tmp->type != fs->type) {
+          if (base.isValid()) {                           /* tmp existing at all */
+              if (base._type != fs->type) {
                   qCWarning(lcUpdate, "file types different is not!");
                   fs->instruction = CSYNC_INSTRUCTION_NEW;
                   goto out;
               }
-              qCDebug(lcUpdate, "remote rename detected based on fileid %s --> %s", tmp->path.constData(), fs->path.constData());
+              qCDebug(lcUpdate, "remote rename detected based on fileid %s --> %s", base._path.constData(), fs->path.constData());
               fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
               if (fs->type == CSYNC_FTW_TYPE_DIR) {
-                  csync_rename_record(ctx, tmp->path, fs->path);
+                  csync_rename_record(ctx, base._path, fs->path);
               } else {
-                  if( tmp->etag != fs->etag ) {
+                  if( base._etag != fs->etag ) {
                       /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ETags are different!"); */
                       /* File with different etag, don't do a rename, but download the file again */
                       fs->instruction = CSYNC_INSTRUCTION_NEW;
@@ -442,10 +433,59 @@ int csync_walker(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
 
 static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
 {
-    if( csync_statedb_get_below_path(ctx, uri) < 0 ) {
-        qCWarning(lcUpdate, "StateDB could not be read!");
+    int64_t count = 0;
+    QByteArray skipbase;
+    auto rowCallback = [ctx, &count, &skipbase](const OCC::SyncJournalFileRecord &rec) {
+        /* When selective sync is used, the database may have subtrees with a parent
+         * whose etag (md5) is _invalid_. These are ignored and shall not appear in the
+         * remote tree.
+         * Sometimes folders that are not ignored by selective sync get marked as
+         * _invalid_, but that is not a problem as the next discovery will retrieve
+         * their correct etags again and we don't run into this case.
+         */
+        if( rec._etag == "_invalid_") {
+            qCDebug(lcUpdate, "%s selective sync excluded", rec._path.constData());
+            skipbase = rec._path;
+            skipbase += '/';
+            return;
+        }
+
+        /* Skip over all entries with the same base path. Note that this depends
+         * strongly on the ordering of the retrieved items. */
+        if( !skipbase.isEmpty() && rec._path.startsWith(skipbase) ) {
+            qCDebug(lcUpdate, "%s selective sync excluded because the parent is", rec._path.constData());
+            return;
+        } else {
+            skipbase.clear();
+        }
+
+        std::unique_ptr<csync_file_stat_t> st = csync_file_stat_t::fromSyncJournalFileRecord(rec);
+
+        /* Check for exclusion from the tree.
+         * Note that this is only a safety net in case the ignore list changes
+         * without a full remote discovery being triggered. */
+        CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type);
+        if (excluded != CSYNC_NOT_EXCLUDED) {
+            qDebug(lcUpdate, "%s excluded (%d)", st->path.constData(), excluded);
+
+            if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
+                    || excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
+                return;
+            }
+
+            st->instruction = CSYNC_INSTRUCTION_IGNORE;
+        }
+
+        /* store into result list. */
+        ctx->remote.files[rec._path] = std::move(st);
+        ++count;
+    };
+
+    if (!ctx->statedb->getFilesBelowPath(uri, rowCallback)) {
+        ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
         return false;
     }
+    qDebug(lcUpdate, "%" PRId64 " entries read below path %s from db.", count, uri);
 
     return true;
 }
index d90a2eacc3284a5460ffb11e6eb25047ff087c83..afafafa5b4183cac21effc92ad1b52950148f340 100644 (file)
@@ -36,7 +36,6 @@
 
 #define CSYNC_LOG_CATEGORY_NAME "csync.util"
 #include "csync_log.h"
-#include "csync_statedb.h"
 
 typedef struct {
   const char *instr_str;
index 611fb111b0dc48c18f6d74bd5e9229eff000e74f..3e9403c0ee9c2faf0b6d111dd38cb2c4c5e5a402 100644 (file)
@@ -30,7 +30,6 @@
 #include "csync_util.h"
 #include "vio/csync_vio.h"
 #include "vio/csync_vio_local.h"
-#include "csync_statedb.h"
 #include "common/c_jhash.h"
 
 csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
index 9f20f53fdee4c4197d04a40d78f6fcce24d755f6..c61c4ea68a23f3d2d1186f54f8a9901d22313827 100644 (file)
@@ -470,7 +470,7 @@ void Folder::slotWatchedPathChanged(const QString &path)
         SyncJournalFileRecord record;
         if (_journal.getFileRecord(relativePath, &record)
             && record.isValid()
-            && !FileSystem::fileChanged(path, record._fileSize, Utility::qDateTimeToTime_t(record._modtime))) {
+            && !FileSystem::fileChanged(path, record._fileSize, record._modtime)) {
             qCInfo(lcFolder) << "Ignoring spurious notification for file" << relativePath;
             return; // probably a spurious notification
         }
index 8af558fa73701098d1e55ae2b39dc30d9c3ab927..4673e9b340ec6294d6cd7c66eadf979c35a1ff37 100644 (file)
@@ -112,13 +112,13 @@ PropagateItemJob::~PropagateItemJob()
     }
 }
 
-static time_t getMinBlacklistTime()
+static qint64 getMinBlacklistTime()
 {
     return qMax(qgetenv("OWNCLOUD_BLACKLIST_TIME_MIN").toInt(),
         25); // 25 seconds
 }
 
-static time_t getMaxBlacklistTime()
+static qint64 getMaxBlacklistTime()
 {
     int v = qgetenv("OWNCLOUD_BLACKLIST_TIME_MAX").toInt();
     if (v > 0)
@@ -142,15 +142,15 @@ static SyncJournalErrorBlacklistRecord createBlacklistEntry(
     entry._renameTarget = item._renameTarget;
     entry._retryCount = old._retryCount + 1;
 
-    static time_t minBlacklistTime(getMinBlacklistTime());
-    static time_t maxBlacklistTime(qMax(getMaxBlacklistTime(), minBlacklistTime));
+    static qint64 minBlacklistTime(getMinBlacklistTime());
+    static qint64 maxBlacklistTime(qMax(getMaxBlacklistTime(), minBlacklistTime));
 
     // The factor of 5 feels natural: 25s, 2 min, 10 min, ~1h, ~5h, ~24h
     entry._ignoreDuration = old._ignoreDuration * 5;
 
     if (item._httpErrorCode == 403) {
         qCWarning(lcPropagator) << "Probably firewall error: " << item._httpErrorCode << ", blacklisting up to 1h only";
-        entry._ignoreDuration = qMin(entry._ignoreDuration, time_t(60 * 60));
+        entry._ignoreDuration = qMin(entry._ignoreDuration, qint64(60 * 60));
 
     } else if (item._httpErrorCode == 413 || item._httpErrorCode == 415) {
         qCWarning(lcPropagator) << "Fatal Error condition" << item._httpErrorCode << ", maximum blacklist ignore time!";
index 74152f02815579d9af850ea34478e1c6ab739c7a..37ca9fecd04366335910db9392c9fc04d07c7299 100644 (file)
@@ -171,7 +171,7 @@ void PropagateRemoteMove::finalize()
     propagator()->_journal->deleteFileRecord(_item->_originalFile);
 
     SyncJournalFileRecord record = _item->toSyncJournalFileRecordWithInode(propagator()->getFilePath(_item->_renameTarget));
-    record._path = _item->_renameTarget;
+    record._path = _item->_renameTarget.toUtf8();
     if (oldRecord.isValid()) {
         record._checksumHeader = oldRecord._checksumHeader;
         if (record._fileSize != oldRecord._fileSize) {
index 6d3ddfb80f0f649d643e53186c4618de1a473e74..5026f28a378f9f34ec3dbfa10696d41ec6f6ee1e 100644 (file)
@@ -83,7 +83,7 @@ void PropagateUploadFileNG::doStartUpload()
     propagator()->_activeJobList.append(this);
 
     const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file);
-    if (progressInfo._valid && Utility::qDateTimeToTime_t(progressInfo._modtime) == _item->_modtime) {
+    if (progressInfo._valid && progressInfo._modtime == _item->_modtime) {
         _transferId = progressInfo._transferid;
         auto url = chunkUrl();
         auto job = new LsColJob(propagator()->account(), url, this);
@@ -229,7 +229,7 @@ void PropagateUploadFileNG::startNewUpload()
     SyncJournalDb::UploadInfo pi;
     pi._valid = true;
     pi._transferid = _transferId;
-    pi._modtime = Utility::qDateTimeFromTime_t(_item->_modtime);
+    pi._modtime = _item->_modtime;
     propagator()->_journal->setUploadInfo(_item->_file, pi);
     propagator()->_journal->commit("Upload info");
     QMap<QByteArray, QByteArray> headers;
index 0d0b2cd0fcdc0b181a207b561c3e0a36fcf5d1c8..c8b0e421df9065919e7df6c06c4aacd50448d4d9 100644 (file)
@@ -43,7 +43,7 @@ void PropagateUploadFileV1::doStartUpload()
 
     const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file);
 
-    if (progressInfo._valid && Utility::qDateTimeToTime_t(progressInfo._modtime) == _item->_modtime) {
+    if (progressInfo._valid && progressInfo._modtime == _item->_modtime) {
         _startChunk = progressInfo._chunk;
         _transferId = progressInfo._transferid;
         qCInfo(lcPropagateUpload) << _item->_file << ": Resuming from chunk " << _startChunk;
@@ -272,7 +272,7 @@ void PropagateUploadFileV1::slotPutFinished()
         }
         pi._chunk = (currentChunk + _startChunk + 1) % _chunkCount; // next chunk to start with
         pi._transferid = _transferId;
-        pi._modtime = Utility::qDateTimeFromTime_t(_item->_modtime);
+        pi._modtime = _item->_modtime;
         pi._errorCount = 0; // successful chunk upload resets
         propagator()->_journal->setUploadInfo(_item->_file, pi);
         propagator()->_journal->commit("Upload info");
index 949f36b4b684c07c9ef2ae3fe2ee674f96cc8791..49ecfe1569dc1122f9400fa1e07759afed19ea33 100644 (file)
@@ -240,7 +240,7 @@ void PropagateLocalRename::start()
     _item->_file = _item->_renameTarget;
 
     SyncJournalFileRecord record = _item->toSyncJournalFileRecordWithInode(targetFile);
-    record._path = _item->_renameTarget;
+    record._path = _item->_renameTarget.toUtf8();
     if (oldRecord.isValid()) {
         record._checksumHeader = oldRecord._checksumHeader;
     }
index d34c516cd776a79bad9eed08f93cf36280c9a4a1..f329d42cddf74914068dd40bccc9a2922dc674d8 100644 (file)
@@ -87,8 +87,7 @@ SyncEngine::SyncEngine(AccountPtr account, const QString &localPath,
     // Everything in the SyncEngine expects a trailing slash for the localPath.
     ASSERT(localPath.endsWith(QLatin1Char('/')));
 
-    const QString dbFile = _journal->databaseFilePath();
-    _csync_ctx.reset(new CSYNC(localPath.toUtf8().data(), dbFile.toUtf8().data()));
+    _csync_ctx.reset(new CSYNC(localPath.toUtf8().data(), journal));
 
     _excludedFiles.reset(new ExcludedFiles(&_csync_ctx->excludes));
     _syncFileStatusTracker.reset(new SyncFileStatusTracker(this));
index 0e6d8cb2abf81475c00e8eb5b5aa182b7f015365..bfea07163c779818a5fc41050f44e1978f8e922e 100644 (file)
@@ -26,8 +26,8 @@ Q_LOGGING_CATEGORY(lcFileItem, "sync.fileitem", QtInfoMsg)
 SyncJournalFileRecord SyncFileItem::toSyncJournalFileRecordWithInode(const QString &localFileName)
 {
     SyncJournalFileRecord rec;
-    rec._path = _file;
-    rec._modtime = Utility::qDateTimeFromTime_t(_modtime);
+    rec._path = _file.toUtf8();
+    rec._modtime = _modtime;
     rec._type = _type;
     rec._etag = _etag;
     rec._fileId = _fileId;
@@ -57,7 +57,7 @@ SyncFileItemPtr SyncFileItem::fromSyncJournalFileRecord(const SyncJournalFileRec
     SyncFileItemPtr item(new SyncFileItem);
     item->_file = rec._path;
     item->_inode = rec._inode;
-    item->_modtime = Utility::qDateTimeToTime_t(rec._modtime);
+    item->_modtime = rec._modtime;
     item->_type = static_cast<SyncFileItem::Type>(rec._type);
     item->_etag = rec._etag;
     item->_fileId = rec._fileId;
index d6b68cb5c27af8d42e76b2d641c2877f9738b6d1..d5cc8615fb908ee488a2cf285cdb90560071aef1 100644 (file)
@@ -33,7 +33,6 @@ IF( APPLE )
 list(APPEND FolderWatcher_SRC ../src/gui/folderwatcher_mac.cpp)
 list(APPEND FolderWatcher_SRC ../src/gui/socketapisocket_mac.mm)
 ENDIF()
-owncloud_add_test(CSyncSqlite "")
 owncloud_add_test(NetrcParser ../src/cmd/netrcparser.cpp)
 owncloud_add_test(OwnSql "")
 owncloud_add_test(SyncJournalDB "")
index 237c52e27224eca9100d2ef1886fa3490880d6f5..5cb0590e42644a9bae693afacecb7aa1cd2123e9 100644 (file)
@@ -32,13 +32,9 @@ add_cmocka_test(check_std_c_time std_tests/check_std_c_time.c ${TEST_TARGET_LIBR
 
 add_cmocka_test(check_csync_log csync_tests/check_csync_log.cpp ${TEST_TARGET_LIBRARIES})
 add_cmocka_test(check_csync_exclude csync_tests/check_csync_exclude.cpp ${TEST_TARGET_LIBRARIES})
-add_cmocka_test(check_csync_statedb_load csync_tests/check_csync_statedb_load.cpp ${TEST_TARGET_LIBRARIES})
 add_cmocka_test(check_csync_util csync_tests/check_csync_util.cpp ${TEST_TARGET_LIBRARIES})
 add_cmocka_test(check_csync_misc csync_tests/check_csync_misc.cpp ${TEST_TARGET_LIBRARIES})
 
-# csync tests which require init
-add_cmocka_test(check_csync_statedb_query csync_tests/check_csync_statedb_query.cpp ${TEST_TARGET_LIBRARIES})
-
 # vio
 add_cmocka_test(check_vio vio_tests/check_vio.cpp ${TEST_TARGET_LIBRARIES})
 add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.cpp ${TEST_TARGET_LIBRARIES})
index 0525942ac15f6c55f14cb0a29d9feee10ec205d8..3f0180e42c1a78c8a980692a212b1958e2abdbd7 100644 (file)
@@ -32,7 +32,7 @@
 static int setup(void **state) {
     CSYNC *csync;
 
-    csync = new CSYNC("/tmp/check_csync1", "");
+    csync = new CSYNC("/tmp/check_csync1", new OCC::SyncJournalDb(""));
 
     *state = csync;
     return 0;
@@ -42,7 +42,7 @@ static int setup_init(void **state) {
     CSYNC *csync;
     int rc;
 
-    csync = new CSYNC("/tmp/check_csync1", "");
+    csync = new CSYNC("/tmp/check_csync1", new OCC::SyncJournalDb(""));
 
     rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
     assert_int_equal(rc, 0);
@@ -67,7 +67,9 @@ static int teardown(void **state) {
     CSYNC *csync = (CSYNC*)*state;
     int rc;
 
+    auto statedb = csync->statedb;
     delete csync;
+    delete statedb;
 
     rc = system("rm -rf /tmp/check_csync1");
     assert_int_equal(rc, 0);
diff --git a/test/csync/csync_tests/check_csync_statedb_load.cpp b/test/csync/csync_tests/check_csync_statedb_load.cpp
deleted file mode 100644 (file)
index f5761f9..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * libcsync -- a library to sync a directory with another
- *
- * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <string.h>
-
-#define CSYNC_TEST 1
-#include "csync_statedb.cpp"
-
-#include "torture.h"
-
-#define TESTDB "/tmp/check_csync1/test.db"
-
-static int setup(void **state) {
-    CSYNC *csync;
-    int rc;
-
-    rc = system("rm -rf /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-
-    rc = system("mkdir -p /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-
-    csync = new CSYNC("/tmp/check_csync1", TESTDB);
-    *state = csync;
-
-    sqlite3 *db = NULL;
-    rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
-    assert_int_equal(rc, SQLITE_OK);
-
-    rc = sqlite3_close(db);
-    assert_int_equal(rc, SQLITE_OK);
-
-    return 0;
-}
-
-static int teardown(void **state) {
-    CSYNC *csync = (CSYNC*)*state;
-    int rc;
-
-    delete csync;
-
-    rc = system("rm -rf /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-
-    *state = NULL;
-    
-    return 0;
-}
-
-static void check_csync_statedb_load(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    int rc;
-
-    rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-    assert_int_equal(rc, 0);
-
-    sqlite3_close(csync->statedb.db);
-}
-
-static void check_csync_statedb_close(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    csync_stat_t sb;
-    time_t modtime;
-    mbchar_t *testdb = c_utf8_path_to_locale(TESTDB);
-    int rc;
-
-    /* statedb not written */
-    csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-
-    rc = _tstat(testdb, &sb);
-    assert_int_equal(rc, 0);
-    modtime = sb.st_mtime;
-
-    rc = csync_statedb_close(csync);
-    assert_int_equal(rc, 0);
-
-    rc = _tstat(testdb, &sb);
-    assert_int_equal(rc, 0);
-    assert_int_equal(modtime, sb.st_mtime);
-
-    csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-
-    rc = _tstat(testdb, &sb);
-    assert_int_equal(rc, 0);
-    modtime = sb.st_mtime;
-
-    /* wait a sec or the modtime will be the same */
-    sleep(1);
-
-    /* statedb written */
-    rc = csync_statedb_close(csync);
-    assert_int_equal(rc, 0);
-
-    rc = _tstat(testdb, &sb);
-    assert_int_equal(rc, 0);
-
-    c_free_locale_string(testdb);
-}
-
-int torture_run_tests(void)
-{
-    const struct CMUnitTest tests[] = {
-        cmocka_unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
-    };
-
-    return cmocka_run_group_tests(tests, NULL, NULL);
-}
-
diff --git a/test/csync/csync_tests/check_csync_statedb_query.cpp b/test/csync/csync_tests/check_csync_statedb_query.cpp
deleted file mode 100644 (file)
index 7f3988a..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * libcsync -- a library to sync a directory with another
- *
- * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define CSYNC_TEST 1
-#include "csync_statedb.cpp"
-
-#include "torture.h"
-
-#define TESTDB "/tmp/check_csync1/test.db"
-#define TESTDBTMP "/tmp/check_csync1/test.db.ctmp"
-
-
-static int setup(void **state)
-{
-    CSYNC *csync;
-    int rc = 0;
-
-    rc = system("rm -rf /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-    rc = system("mkdir -p /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-    rc = system("mkdir -p /tmp/check_csync");
-    assert_int_equal(rc, 0);
-    csync = new CSYNC("/tmp/check_csync1", TESTDB);
-
-    sqlite3 *db = NULL;
-    rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
-    assert_int_equal(rc, SQLITE_OK);
-    rc = sqlite3_close(db);
-    assert_int_equal(rc, SQLITE_OK);
-
-    rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-    assert_int_equal(rc, 0);
-
-    *state = csync;
-    
-    return 0;
-}
-
-static int setup_db(void **state)
-{
-    char *errmsg;
-    int rc = 0;
-    sqlite3 *db = NULL;
-
-    const char *sql = "CREATE TABLE IF NOT EXISTS metadata ("
-        "phash INTEGER(8),"
-        "pathlen INTEGER,"
-        "path VARCHAR(4096),"
-        "inode INTEGER,"
-        "uid INTEGER,"
-        "gid INTEGER,"
-        "mode INTEGER,"
-        "modtime INTEGER(8),"
-        "type INTEGER,"
-        "md5 VARCHAR(32),"
-        "PRIMARY KEY(phash)"
-        ");";
-
-        const char *sql2 = "INSERT INTO metadata"
-                           "(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES"
-                           "(42, 42, 'Its funny stuff', 23, 42, 43, 55, 66, 2, 54);";
-
-
-    setup(state);
-    rc = sqlite3_open( TESTDB, &db);
-    assert_int_equal(rc, SQLITE_OK);
-
-    rc = sqlite3_exec( db, sql, NULL, NULL, &errmsg );
-    assert_int_equal(rc, SQLITE_OK);
-
-    rc = sqlite3_exec( db, sql2, NULL, NULL, &errmsg );
-    assert_int_equal(rc, SQLITE_OK);
-
-    sqlite3_close(db);
-    
-    return 0;
-
-}
-
-static int teardown(void **state) {
-    CSYNC *csync = (CSYNC*)*state;
-    int rc = 0;
-
-    delete csync;
-    rc = system("rm -rf /tmp/check_csync");
-    assert_int_equal(rc, 0);
-    rc = system("rm -rf /tmp/check_csync1");
-    assert_int_equal(rc, 0);
-
-    *state = NULL;
-    
-    return 0;
-}
-
-
-static void check_csync_statedb_query_statement(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    c_strlist_t *result;
-
-    result = csync_statedb_query(csync->statedb.db, "");
-    assert_null(result);
-    if (result != NULL) {
-      c_strlist_destroy(result);
-    }
-
-    result = csync_statedb_query(csync->statedb.db, "SELECT;");
-    assert_null(result);
-    if (result != NULL) {
-      c_strlist_destroy(result);
-    }
-}
-
-static void check_csync_statedb_drop_tables(void **state)
-{
-    // CSYNC *csync = (CSYNC*)*state;
-    int rc = 0;
-    (void) state;
-
-    // rc = csync_statedb_drop_tables(csync->statedb.db);
-    assert_int_equal(rc, 0);
-    // rc = csync_statedb_create_tables(csync->statedb.db);
-    assert_int_equal(rc, 0);
-    // rc = csync_statedb_drop_tables(csync->statedb.db);
-    assert_int_equal(rc, 0);
-}
-
-static void check_csync_statedb_insert_metadata(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    std::unique_ptr<csync_file_stat_t> st;
-    int i, rc = 0;
-
-    // rc = csync_statedb_create_tables(csync->statedb.db);
-    assert_int_equal(rc, 0);
-
-    for (i = 0; i < 100; i++) {
-        st.reset(new csync_file_stat_t);
-        st->path = QString("file_%1").arg(i).toUtf8();
-
-        csync->local.files[st->path] = std::move(st);
-    }
-
-    // rc = csync_statedb_insert_metadata(csync, csync->statedb.db);
-    assert_int_equal(rc, 0);
-}
-
-static void check_csync_statedb_write(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    std::unique_ptr<csync_file_stat_t> st;
-    int i, rc = 0;
-
-    for (i = 0; i < 100; i++) {
-        st.reset(new csync_file_stat_t);
-        st->path = QString("file_%1").arg(i).toUtf8();
-
-        csync->local.files[st->path] = std::move(st);
-        assert_int_equal(rc, 0);
-    }
-
-    // rc = csync_statedb_write(csync, csync->statedb.db);
-    assert_int_equal(rc, 0);
-}
-
-
-static void check_csync_statedb_get_stat_by_path_not_found(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    std::unique_ptr<csync_file_stat_t> tmp;
-
-    tmp = csync_statedb_get_stat_by_path(csync, "666");
-    assert_null(tmp.get());
-}
-
-
-static void check_csync_statedb_get_stat_by_inode_not_found(void **state)
-{
-    CSYNC *csync = (CSYNC*)*state;
-    std::unique_ptr<csync_file_stat_t> tmp;
-
-    tmp = csync_statedb_get_stat_by_inode(csync, (ino_t) 666);
-    assert_null(tmp.get());
-}
-
-int torture_run_tests(void)
-{
-    const struct CMUnitTest tests[] = {
-        cmocka_unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_path_not_found, setup_db, teardown),
-        cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
-    };
-
-    return cmocka_run_group_tests(tests, NULL, NULL);
-}
-
index 4fae4e1a75ef0218a033d71076cea28a59eb1692..db6819907208369a549b86e9ca3a4c3be9e33d0a 100644 (file)
@@ -98,12 +98,10 @@ static int setup(void **state)
     assert_int_equal(rc, 0);
     rc = system("mkdir -p /tmp/check_csync1");
     assert_int_equal(rc, 0);
-    csync = new CSYNC("/tmp/check_csync1", TESTDB);
 
     /* Create a new db with metadata */
     sqlite3 *db;
-    // csync->statedb.file = c_strdup(TESTDB);
-    rc = sqlite3_open(csync->statedb.file, &db);
+    rc = sqlite3_open(TESTDB, &db);
     statedb_create_metadata_table(db);
     if( firstrun ) {
         statedb_insert_metadata(db);
@@ -111,8 +109,8 @@ static int setup(void **state)
     }
     sqlite3_close(db);
 
-    rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-    assert_int_equal(rc, 0);
+    csync = new CSYNC("/tmp/check_csync1", new OCC::SyncJournalDb(TESTDB));
+    assert_true(csync->statedb->isConnected());
 
     *state = csync;
     
@@ -128,7 +126,7 @@ static int setup_ftw(void **state)
     assert_int_equal(rc, 0);
     rc = system("mkdir -p /tmp/check_csync1");
     assert_int_equal(rc, 0);
-    csync = new CSYNC("/tmp", TESTDB);
+    csync = new CSYNC("/tmp", new OCC::SyncJournalDb(TESTDB));
 
     sqlite3 *db = NULL;
     rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
@@ -137,10 +135,9 @@ static int setup_ftw(void **state)
     rc = sqlite3_close(db);
     assert_int_equal(rc, SQLITE_OK);
 
-    rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
-    assert_int_equal(rc, 0);
+    csync = new CSYNC("/tmp", new OCC::SyncJournalDb(TESTDB));
+    assert_true(csync->statedb->isConnected());
 
-    csync->statedb.file = c_strdup( TESTDB );
     *state = csync;
     
     return 0;
@@ -150,8 +147,10 @@ static int teardown(void **state)
 {
     CSYNC *csync = (CSYNC*)*state;
 
-    unlink( csync->statedb.file);
+    unlink(TESTDB);
+    auto statedb = csync->statedb;
     delete csync;
+    delete statedb;
 
     *state = NULL;
     
@@ -288,7 +287,6 @@ static void check_csync_detect_update_db_rename(void **state)
     int rc = 0;
 
     fs = create_fstat("wurst.txt", 0, 42);
-    csync_set_statedb_exists(csync, 1);
 
     rc = _csync_detect_update(csync, std::move(fs));
     assert_int_equal(rc, 0);
index 0607dcaa83fd15ae48d03358a274da28a0e1c58f..884accf43d8e4b6e4038a135135985ed36418988 100644 (file)
@@ -49,7 +49,7 @@ static int setup(void **state)
     rc = system("rm -rf /tmp/csync_test");
     assert_int_equal(rc, 0);
 
-    csync = new CSYNC("/tmp/check_csync1", "");
+    csync = new CSYNC("/tmp/check_csync1", new OCC::SyncJournalDb(""));
 
     csync->current = LOCAL_REPLICA;
 
@@ -78,7 +78,9 @@ static int teardown(void **state) {
     CSYNC *csync = (CSYNC*)*state;
     int rc;
 
+    auto statedb = csync->statedb;
     delete csync;
+    delete statedb;
 
     rc = chdir(wd_buffer);
     assert_int_equal(rc, 0);
index 625285ce08225e43ab7777dff3025fa810479f9a..f86ce9591aaf08fcc671e98f769fdcae457893f1 100644 (file)
@@ -97,7 +97,7 @@ static int setup_testenv(void **state) {
     statevar *mystate = (statevar*)malloc( sizeof(statevar) );
     mystate->result = NULL;
 
-    mystate->csync = new CSYNC("/tmp/check_csync1", "");
+    mystate->csync = new CSYNC("/tmp/check_csync1", new OCC::SyncJournalDb(""));
 
     mystate->csync->current = LOCAL_REPLICA;
 
@@ -124,7 +124,9 @@ static int teardown(void **state) {
 
     output("================== Tearing down!\n");
 
+    auto statedb = csync->statedb;
     delete csync;
+    delete statedb;
 
     rc = _tchdir(wd_buffer);
     assert_int_equal(rc, 0);
diff --git a/test/testcsyncsqlite.cpp b/test/testcsyncsqlite.cpp
deleted file mode 100644 (file)
index 093ee43..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-   This software is in the public domain, furnished "as is", without technical
-   support, and with no warranty, express or implied, as to its usefulness for
-   any purpose.
-*/
-
-#include "csync_statedb.h"
-#include "csync_private.h"
-#include <QtTest>
-
-
-class TestCSyncSqlite : public QObject
-{
-    Q_OBJECT
-
-private:
-    CSYNC *_ctx;
-private slots:
-    void initTestCase() {
-        int rc;
-
-        QString db = QCoreApplication::applicationDirPath() + "/test_journal.db";
-        _ctx = new CSYNC("/tmp/check_csync1", db.toLocal8Bit());
-
-        rc = csync_statedb_load(_ctx, _ctx->statedb.file, &(_ctx->statedb.db));
-        QVERIFY(rc == 0);
-    }
-
-    void testFullResult() {
-        std::unique_ptr<csync_file_stat_t> st = csync_statedb_get_stat_by_path( _ctx, "test2/zu/zuzu" );
-        QVERIFY(st.get());
-        QCOMPARE( QString::fromUtf8(st->path), QLatin1String("test2/zu/zuzu") );
-        QCOMPARE( QString::number(st->inode), QString::number(1709554));
-        QCOMPARE( QString::number(st->modtime), QString::number(1384415006));
-        QCOMPARE( QString::number(st->type), QString::number(2));
-        QCOMPARE( QString::fromUtf8(st->etag), QLatin1String("52847f2090665"));
-        QCOMPARE( QString::fromUtf8(st->file_id), QLatin1String("00000557525d5af3d9625"));
-
-    }
-
-    void testByHash() {
-        std::unique_ptr<csync_file_stat_t> st = csync_statedb_get_stat_by_path(_ctx, "documents/c1");
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("documents/c1"));
-
-        st = csync_statedb_get_stat_by_path(_ctx, "documents/c1/c2");
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("documents/c1/c2"));
-    }
-
-    void testByInode() {
-        std::unique_ptr<csync_file_stat_t> st = csync_statedb_get_stat_by_inode(_ctx, 1709555);
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("test2/zu/zuzu/zuzuzu"));
-
-        st = csync_statedb_get_stat_by_inode(_ctx, 1706571);
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("Shared/for_kf/a2"));
-    }
-
-    void testByFileId() {
-        std::unique_ptr<csync_file_stat_t> st = csync_statedb_get_stat_by_file_id(_ctx, "00000556525d5af3d9625");
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("test2/zu"));
-
-        st = csync_statedb_get_stat_by_file_id(_ctx, "-0000001525d5af3d9625");
-        QVERIFY(st.get());
-        QCOMPARE(QString::fromUtf8(st->path), QLatin1String("Shared"));
-    }
-
-    void cleanupTestCase() {
-        csync_statedb_close(_ctx);
-        delete _ctx;
-        _ctx = nullptr;
-    }
-
-};
-
-QTEST_GUILESS_MAIN(TestCSyncSqlite)
-#include "testcsyncsqlite.moc"
index 032937b625c9ef95b03cd359d377a2be2fbf8416..a4c4c5be4f13230c2226c13f5b3a1704b2a1072a 100644 (file)
@@ -183,7 +183,7 @@ private slots:
         // Remove subFolderA with selectiveSync:
         fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
                                                                 {"parentFolder/subFolderA/"});
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync("parentFolder/subFolderA/");
+        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
 
         fakeFolder.syncOnce();
 
@@ -238,7 +238,7 @@ private slots:
         // folders are uploaded anyway is some circumstances.
         FakeFolder fakeFolder{FileInfo{ QString(), {
             FileInfo { QStringLiteral("parentFolder"), {
-                FileInfo{ QStringLiteral("subFolder"), {
+                FileInfo{ QStringLiteral("subFolderA"), {
                     { QStringLiteral("fileA.txt"), 400 },
                     { QStringLiteral("fileB.txt"), 400, 'o' },
                     FileInfo { QStringLiteral("subsubFolder"), {
@@ -252,23 +252,24 @@ private slots:
                             { QStringLiteral("fileF.txt"), 400, 'o' }
                         }}
                     }}
-                }}
+                }},
+                FileInfo{ QStringLiteral("subFolderB"), {} }
             }}
         }}};
 
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         auto expectedServerState = fakeFolder.currentRemoteState();
 
-        // Remove subFolder with selectiveSync:
+        // Remove subFolderA with selectiveSync:
         fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
-                                                                {"parentFolder/subFolder/"});
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync("parentFolder/subFolder/");
+                                                                {"parentFolder/subFolderA/"});
+        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
 
         // But touch local file before the next sync, such that the local folder
         // can't be removed
-        fakeFolder.localModifier().setContents("parentFolder/subFolder/fileB.txt", 'n');
-        fakeFolder.localModifier().setContents("parentFolder/subFolder/subsubFolder/fileD.txt", 'n');
-        fakeFolder.localModifier().setContents("parentFolder/subFolder/anotherFolder/subsubFolder/fileF.txt", 'n');
+        fakeFolder.localModifier().setContents("parentFolder/subFolderA/fileB.txt", 'n');
+        fakeFolder.localModifier().setContents("parentFolder/subFolderA/subsubFolder/fileD.txt", 'n');
+        fakeFolder.localModifier().setContents("parentFolder/subFolderA/anotherFolder/subsubFolder/fileF.txt", 'n');
 
         // Several follow-up syncs don't change the state at all,
         // in particular the remote state doesn't change and fileB.txt
@@ -282,14 +283,15 @@ private slots:
                 QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
                 // The local state should still have subFolderA
                 auto local = fakeFolder.currentLocalState();
-                QVERIFY(local.find("parentFolder/subFolder"));
-                QVERIFY(!local.find("parentFolder/subFolder/fileA.txt"));
-                QVERIFY(local.find("parentFolder/subFolder/fileB.txt"));
-                QVERIFY(!local.find("parentFolder/subFolder/subsubFolder/fileC.txt"));
-                QVERIFY(local.find("parentFolder/subFolder/subsubFolder/fileD.txt"));
-                QVERIFY(!local.find("parentFolder/subFolder/anotherFolder/subsubFolder/fileE.txt"));
-                QVERIFY(local.find("parentFolder/subFolder/anotherFolder/subsubFolder/fileF.txt"));
-                QVERIFY(!local.find("parentFolder/subFolder/anotherFolder/emptyFolder"));
+                QVERIFY(local.find("parentFolder/subFolderA"));
+                QVERIFY(!local.find("parentFolder/subFolderA/fileA.txt"));
+                QVERIFY(local.find("parentFolder/subFolderA/fileB.txt"));
+                QVERIFY(!local.find("parentFolder/subFolderA/subsubFolder/fileC.txt"));
+                QVERIFY(local.find("parentFolder/subFolderA/subsubFolder/fileD.txt"));
+                QVERIFY(!local.find("parentFolder/subFolderA/anotherFolder/subsubFolder/fileE.txt"));
+                QVERIFY(local.find("parentFolder/subFolderA/anotherFolder/subsubFolder/fileF.txt"));
+                QVERIFY(!local.find("parentFolder/subFolderA/anotherFolder/emptyFolder"));
+                QVERIFY(local.find("parentFolder/subFolderB"));
             }
         }
     }
index 5219dd8cf0e373afd22d0325b0abe3fe75ce6d55..0575c0ed5f2bcba473e9f81ffdd06497aaa738af 100644 (file)
@@ -26,9 +26,9 @@ public:
         QVERIFY(_tempDir.isValid());
     }
 
-    QDateTime dropMsecs(QDateTime time)
+    qint64 dropMsecs(QDateTime time)
     {
-        return Utility::qDateTimeFromTime_t(Utility::qDateTimeToTime_t(time));
+        return Utility::qDateTimeToTime_t(time);
     }
 
 private slots:
@@ -46,7 +46,7 @@ private slots:
     void testFileRecord()
     {
         SyncJournalFileRecord record;
-        QVERIFY(_db.getFileRecord("nonexistant", &record));
+        QVERIFY(_db.getFileRecord(QByteArrayLiteral("nonexistant"), &record));
         QVERIFY(!record.isValid());
 
         record._path = "foo";
@@ -61,13 +61,13 @@ private slots:
         QVERIFY(_db.setFileRecord(record));
 
         SyncJournalFileRecord storedRecord;
-        QVERIFY(_db.getFileRecord("foo", &storedRecord));
+        QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo"), &storedRecord));
         QVERIFY(storedRecord == record);
 
         // Update checksum
         record._checksumHeader = "Adler32:newchecksum";
         _db.updateFileRecordChecksum("foo", "newchecksum", "Adler32");
-        QVERIFY(_db.getFileRecord("foo", &storedRecord));
+        QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo"), &storedRecord));
         QVERIFY(storedRecord == record);
 
         // Update metadata
@@ -79,11 +79,11 @@ private slots:
         record._remotePerm = RemotePermissions("NV");
         record._fileSize = 289055;
         _db.setFileRecordMetadata(record);
-        QVERIFY(_db.getFileRecord("foo", &storedRecord));
+        QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo"), &storedRecord));
         QVERIFY(storedRecord == record);
 
         QVERIFY(_db.deleteFileRecord("foo"));
-        QVERIFY(_db.getFileRecord("foo", &record));
+        QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo"), &record));
         QVERIFY(!record.isValid());
     }
 
@@ -95,11 +95,11 @@ private slots:
             record._path = "foo-checksum";
             record._remotePerm = RemotePermissions("RW");
             record._checksumHeader = "MD5:mychecksum";
-            record._modtime = QDateTime::currentDateTimeUtc();
+            record._modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTimeUtc());
             QVERIFY(_db.setFileRecord(record));
 
             SyncJournalFileRecord storedRecord;
-            QVERIFY(_db.getFileRecord("foo-checksum", &storedRecord));
+            QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo-checksum"), &storedRecord));
             QVERIFY(storedRecord._path == record._path);
             QVERIFY(storedRecord._remotePerm == record._remotePerm);
             QVERIFY(storedRecord._checksumHeader == record._checksumHeader);
@@ -108,19 +108,19 @@ private slots:
 
             // Attention: compare time_t types here, as QDateTime seem to maintain
             // milliseconds internally, which disappear in sqlite. Go for full seconds here.
-            QVERIFY(storedRecord._modtime.toTime_t() == record._modtime.toTime_t());
+            QVERIFY(storedRecord._modtime == record._modtime);
             QVERIFY(storedRecord == record);
         }
         {
             SyncJournalFileRecord record;
             record._path = "foo-nochecksum";
             record._remotePerm = RemotePermissions("RWN");
-            record._modtime = QDateTime::currentDateTimeUtc();
+            record._modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTimeUtc());
 
             QVERIFY(_db.setFileRecord(record));
 
             SyncJournalFileRecord storedRecord;
-            QVERIFY(_db.getFileRecord("foo-nochecksum", &storedRecord));
+            QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo-nochecksum"), &storedRecord));
             QVERIFY(storedRecord == record);
         }
     }
index 9c92d9a1d0e4e5543172699d7085f0e1a8c6bd44..ba5489c3a2df2e4e46c7ebf53c24873e8a12c5b0 100644 (file)
@@ -35,7 +35,7 @@ private slots:
         SyncJournalDb::UploadInfo uploadInfo;
         uploadInfo._transferid = 1;
         uploadInfo._valid = true;
-        uploadInfo._modtime = modTime;
+        uploadInfo._modtime = Utility::qDateTimeToTime_t(modTime);
         fakeFolder.syncEngine().journal()->setUploadInfo("A/a0", uploadInfo);
 
         fakeFolder.uploadState().mkdir("1");