2013-10-03 13:27:29 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
|
|
|
*
|
2017-09-01 16:11:43 +00:00
|
|
|
* 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.
|
2013-10-03 13:27:29 +00:00
|
|
|
*
|
2017-09-01 16:11:43 +00:00
|
|
|
* 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
|
2013-10-03 13:27:29 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SYNCJOURNALDB_H
|
|
|
|
#define SYNCJOURNALDB_H
|
|
|
|
|
|
|
|
#include <QObject>
|
2013-10-16 09:59:54 +00:00
|
|
|
#include <QDateTime>
|
2013-11-11 10:11:45 +00:00
|
|
|
#include <QHash>
|
2021-05-04 14:31:45 +00:00
|
|
|
#include <QMutex>
|
2021-06-03 14:10:26 +00:00
|
|
|
#include <QVariant>
|
2017-09-14 13:50:13 +00:00
|
|
|
#include <functional>
|
2013-10-03 13:27:29 +00:00
|
|
|
|
2017-08-16 06:36:52 +00:00
|
|
|
#include "common/utility.h"
|
2017-09-01 16:11:43 +00:00
|
|
|
#include "common/ownsql.h"
|
2021-01-18 13:36:33 +00:00
|
|
|
#include "common/preparedsqlquerymanager.h"
|
2017-09-01 16:11:43 +00:00
|
|
|
#include "common/syncjournalfilerecord.h"
|
2018-12-20 10:24:41 +00:00
|
|
|
#include "common/result.h"
|
2019-01-23 14:12:02 +00:00
|
|
|
#include "common/pinstate.h"
|
2014-04-24 21:45:20 +00:00
|
|
|
|
2014-11-09 21:34:07 +00:00
|
|
|
namespace OCC {
|
2013-10-03 13:27:29 +00:00
|
|
|
class SyncJournalFileRecord;
|
|
|
|
|
2015-06-29 16:56:09 +00:00
|
|
|
/**
|
2015-10-05 03:20:09 +00:00
|
|
|
* @brief Class that handles the sync database
|
2014-04-01 11:41:47 +00:00
|
|
|
*
|
2015-10-05 03:20:09 +00:00
|
|
|
* This class is thread safe. All public functions lock the mutex.
|
2015-06-29 16:56:09 +00:00
|
|
|
* @ingroup libsync
|
2014-04-01 11:41:47 +00:00
|
|
|
*/
|
2017-09-01 16:11:43 +00:00
|
|
|
class OCSYNC_EXPORT SyncJournalDb : public QObject
|
2013-10-03 13:27:29 +00:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2020-08-12 14:14:48 +00:00
|
|
|
explicit SyncJournalDb(const QString &dbFilePath, QObject *parent = nullptr);
|
2021-08-17 10:39:31 +00:00
|
|
|
~SyncJournalDb() override;
|
2016-04-11 10:40:19 +00:00
|
|
|
|
2016-11-23 09:40:17 +00:00
|
|
|
/// Create a journal path for a specific configuration
|
2020-11-05 14:27:27 +00:00
|
|
|
static QString makeDbName(const QString &localPath,
|
|
|
|
const QUrl &remoteUrl,
|
2016-11-23 09:40:17 +00:00
|
|
|
const QString &remotePath,
|
|
|
|
const QString &user);
|
|
|
|
|
|
|
|
/// Migrate a csync_journal to the new path, if necessary. Returns false on error
|
|
|
|
static bool maybeMigrateDb(const QString &localPath, const QString &absoluteJournalPath);
|
|
|
|
|
2017-09-13 17:02:38 +00:00
|
|
|
// To verify that the record could be found check with SyncJournalFileRecord::isValid()
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] bool getFileRecord(const QString &filename, SyncJournalFileRecord *rec) { return getFileRecord(filename.toUtf8(), rec); }
|
|
|
|
[[nodiscard]] bool getFileRecord(const QByteArray &filename, SyncJournalFileRecord *rec);
|
|
|
|
[[nodiscard]] bool getFileRecordByE2eMangledName(const QString &mangledName, SyncJournalFileRecord *rec);
|
|
|
|
[[nodiscard]] bool getFileRecordByInode(quint64 inode, SyncJournalFileRecord *rec);
|
|
|
|
[[nodiscard]] bool getFileRecordsByFileId(const QByteArray &fileId, const std::function<void(const SyncJournalFileRecord &)> &rowCallback);
|
|
|
|
[[nodiscard]] bool getFilesBelowPath(const QByteArray &path, const std::function<void(const SyncJournalFileRecord&)> &rowCallback);
|
|
|
|
[[nodiscard]] bool listFilesInPath(const QByteArray &path, const std::function<void(const SyncJournalFileRecord&)> &rowCallback);
|
|
|
|
[[nodiscard]] Result<void, QString> setFileRecord(const SyncJournalFileRecord &record);
|
2015-11-10 14:05:00 +00:00
|
|
|
|
2021-06-03 14:10:26 +00:00
|
|
|
void keyValueStoreSet(const QString &key, QVariant value);
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] qint64 keyValueStoreGetInt(const QString &key, qint64 defaultValue);
|
2021-06-03 14:10:26 +00:00
|
|
|
void keyValueStoreDelete(const QString &key);
|
2021-05-04 14:31:45 +00:00
|
|
|
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] bool deleteFileRecord(const QString &filename, bool recursively = false);
|
|
|
|
[[nodiscard]] bool updateFileRecordChecksum(
|
|
|
|
const QString &filename,
|
2015-11-23 10:53:06 +00:00
|
|
|
const QByteArray &contentChecksum,
|
|
|
|
const QByteArray &contentChecksumType);
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] bool updateLocalMetadata(const QString &filename,
|
2022-09-20 21:03:39 +00:00
|
|
|
qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo);
|
2019-04-03 08:53:04 +00:00
|
|
|
|
2019-04-16 08:17:21 +00:00
|
|
|
/// Return value for hasHydratedOrDehydratedFiles()
|
|
|
|
struct HasHydratedDehydrated
|
|
|
|
{
|
|
|
|
bool hasHydrated = false;
|
|
|
|
bool hasDehydrated = false;
|
|
|
|
};
|
|
|
|
|
2019-04-03 08:53:04 +00:00
|
|
|
/** Returns whether the item or any subitems are dehydrated */
|
2019-04-16 08:17:21 +00:00
|
|
|
Optional<HasHydratedDehydrated> hasHydratedOrDehydratedFiles(const QByteArray &filename);
|
2019-04-03 08:53:04 +00:00
|
|
|
|
2013-10-04 12:44:57 +00:00
|
|
|
bool exists();
|
2014-10-21 13:41:11 +00:00
|
|
|
void walCheckpoint();
|
2013-12-03 13:47:32 +00:00
|
|
|
|
2022-09-30 17:12:08 +00:00
|
|
|
[[nodiscard]] QString databaseFilePath() const;
|
2016-11-22 14:30:12 +00:00
|
|
|
|
2017-09-14 13:50:13 +00:00
|
|
|
static qint64 getPHash(const QByteArray &);
|
2014-10-13 12:14:43 +00:00
|
|
|
|
2017-07-07 13:11:00 +00:00
|
|
|
void setErrorBlacklistEntry(const SyncJournalErrorBlacklistRecord &item);
|
2015-01-16 09:17:19 +00:00
|
|
|
void wipeErrorBlacklistEntry(const QString &file);
|
2017-07-11 13:54:01 +00:00
|
|
|
void wipeErrorBlacklistCategory(SyncJournalErrorBlacklistRecord::Category category);
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] int wipeErrorBlacklist();
|
2015-01-16 09:17:19 +00:00
|
|
|
int errorBlackListEntryCount();
|
2013-10-03 16:52:02 +00:00
|
|
|
|
2013-10-16 09:59:54 +00:00
|
|
|
struct DownloadInfo
|
|
|
|
{
|
|
|
|
QString _tmpfile;
|
|
|
|
QByteArray _etag;
|
2020-05-20 23:32:16 +00:00
|
|
|
int _errorCount = 0;
|
|
|
|
bool _valid = false;
|
2013-10-16 09:59:54 +00:00
|
|
|
};
|
|
|
|
struct UploadInfo
|
|
|
|
{
|
2020-05-20 23:32:16 +00:00
|
|
|
int _chunk = 0;
|
2019-02-13 09:15:33 +00:00
|
|
|
uint _transferid = 0;
|
|
|
|
qint64 _size = 0;
|
2020-05-20 23:32:16 +00:00
|
|
|
qint64 _modtime = 0;
|
|
|
|
int _errorCount = 0;
|
|
|
|
bool _valid = false;
|
2017-12-11 18:25:51 +00:00
|
|
|
QByteArray _contentChecksum;
|
2018-04-04 15:33:14 +00:00
|
|
|
/**
|
|
|
|
* Returns true if this entry refers to a chunked upload that can be continued.
|
|
|
|
* (As opposed to a small file transfer which is stored in the db so we can detect the case
|
|
|
|
* when the upload succeeded, but the connection was dropped before we got the answer)
|
|
|
|
*/
|
2022-09-30 17:12:08 +00:00
|
|
|
[[nodiscard]] bool isChunked() const { return _transferid != 0; }
|
2013-10-16 09:59:54 +00:00
|
|
|
};
|
|
|
|
|
2014-07-28 10:12:52 +00:00
|
|
|
struct PollInfo
|
|
|
|
{
|
2018-06-25 15:47:52 +00:00
|
|
|
QString _file; // The relative path of a file
|
|
|
|
QString _url; // the poll url. (This pollinfo is invalid if _url is empty)
|
2023-02-06 08:14:48 +00:00
|
|
|
qint64 _modtime = 0LL; // The modtime of the file being uploaded
|
|
|
|
qint64 _fileSize = 0LL;
|
2014-07-28 10:12:52 +00:00
|
|
|
};
|
|
|
|
|
2013-10-16 09:59:54 +00:00
|
|
|
DownloadInfo getDownloadInfo(const QString &file);
|
|
|
|
void setDownloadInfo(const QString &file, const DownloadInfo &i);
|
2014-09-03 10:11:03 +00:00
|
|
|
QVector<DownloadInfo> getAndDeleteStaleDownloadInfos(const QSet<QString> &keep);
|
2014-11-05 13:52:57 +00:00
|
|
|
int downloadInfoCount();
|
2014-09-03 10:11:03 +00:00
|
|
|
|
2013-10-16 09:59:54 +00:00
|
|
|
UploadInfo getUploadInfo(const QString &file);
|
|
|
|
void setUploadInfo(const QString &file, const UploadInfo &i);
|
2017-01-20 12:59:13 +00:00
|
|
|
// Return the list of transfer ids that were removed.
|
|
|
|
QVector<uint> deleteStaleUploadInfos(const QSet<QString> &keep);
|
2014-09-03 10:11:03 +00:00
|
|
|
|
2015-01-16 09:17:19 +00:00
|
|
|
SyncJournalErrorBlacklistRecord errorBlacklistEntry(const QString &);
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] bool deleteStaleErrorBlacklistEntries(const QSet<QString> &keep);
|
2014-09-03 10:11:03 +00:00
|
|
|
|
2019-06-27 13:47:04 +00:00
|
|
|
/// Delete flags table entries that have no metadata correspondent
|
|
|
|
void deleteStaleFlagsEntries();
|
|
|
|
|
2017-09-14 13:50:13 +00:00
|
|
|
void avoidRenamesOnNextSync(const QString &path) { avoidRenamesOnNextSync(path.toUtf8()); }
|
|
|
|
void avoidRenamesOnNextSync(const QByteArray &path);
|
2014-07-28 10:12:52 +00:00
|
|
|
void setPollInfo(const PollInfo &);
|
2018-01-28 16:50:10 +00:00
|
|
|
|
2014-07-28 10:12:52 +00:00
|
|
|
QVector<PollInfo> getPollInfos();
|
2013-11-20 12:44:01 +00:00
|
|
|
|
2015-05-20 14:28:06 +00:00
|
|
|
enum SelectiveSyncListType {
|
2015-05-26 12:41:29 +00:00
|
|
|
/** The black list is the list of folders that are unselected in the selective sync dialog.
|
|
|
|
* For the sync engine, those folders are considered as if they were not there, so the local
|
|
|
|
* folders will be deleted */
|
2015-05-20 14:28:06 +00:00
|
|
|
SelectiveSyncBlackList = 1,
|
2015-10-05 03:20:09 +00:00
|
|
|
/** When a shared folder has a size bigger than a configured size, it is by default not sync'ed
|
2015-05-26 12:41:29 +00:00
|
|
|
* Unless it is in the white list, in which case the folder is sync'ed and all its children.
|
|
|
|
* If a folder is both on the black and the white list, the black list wins */
|
2015-05-20 14:28:06 +00:00
|
|
|
SelectiveSyncWhiteList = 2,
|
2015-10-05 03:20:09 +00:00
|
|
|
/** List of big sync folders that have not been confirmed by the user yet and that the UI
|
2015-05-26 12:41:29 +00:00
|
|
|
* should notify about */
|
2022-12-07 18:43:27 +00:00
|
|
|
SelectiveSyncUndecidedList = 3,
|
|
|
|
/** List of encrypted folders that will need to be removed from the blacklist when E2EE gets set up*/
|
|
|
|
SelectiveSyncE2eFoldersToRemoveFromBlacklist = 4,
|
2015-05-20 14:28:06 +00:00
|
|
|
};
|
|
|
|
/* return the specified list from the database */
|
2016-04-06 13:01:28 +00:00
|
|
|
QStringList getSelectiveSyncList(SelectiveSyncListType type, bool *ok);
|
2015-05-20 14:28:06 +00:00
|
|
|
/* Write the selective sync list (remove all other entries of that list */
|
|
|
|
void setSelectiveSyncList(SelectiveSyncListType type, const QStringList &list);
|
|
|
|
|
2014-06-03 15:22:40 +00:00
|
|
|
/**
|
2018-02-07 12:05:41 +00:00
|
|
|
* Make sure that on the next sync fileName and its parents are discovered from the server.
|
2017-05-15 12:46:09 +00:00
|
|
|
*
|
2018-02-07 12:05:41 +00:00
|
|
|
* That means its metadata and, if it's a directory, its direct contents.
|
|
|
|
*
|
|
|
|
* Specifically, etag (md5 field) of fileName and all its parents are set to _invalid_.
|
2017-05-15 12:46:09 +00:00
|
|
|
* That causes a metadata difference and a resulting discovery from the remote for the
|
|
|
|
* affected folders.
|
|
|
|
*
|
|
|
|
* Since folders in the selective sync list will not be rediscovered (csync_ftw,
|
2018-02-07 12:05:41 +00:00
|
|
|
* _csync_detect_update skip them), the _invalid_ marker will stay. And any
|
2017-05-15 12:46:09 +00:00
|
|
|
* child items in the db will be ignored when reading a remote tree from the database.
|
2018-02-16 09:33:35 +00:00
|
|
|
*
|
|
|
|
* Any setFileRecord() call to affected directories before the next sync run will be
|
|
|
|
* adjusted to retain the invalid etag via _etagStorageFilter.
|
2014-06-03 15:22:40 +00:00
|
|
|
*/
|
2019-02-13 13:18:54 +00:00
|
|
|
void schedulePathForRemoteDiscovery(const QString &fileName) { schedulePathForRemoteDiscovery(fileName.toUtf8()); }
|
|
|
|
void schedulePathForRemoteDiscovery(const QByteArray &fileName);
|
2014-06-03 15:22:40 +00:00
|
|
|
|
2018-02-16 09:33:35 +00:00
|
|
|
/**
|
|
|
|
* Wipe _etagStorageFilter. Also done implicitly on close().
|
|
|
|
*/
|
|
|
|
void clearEtagStorageFilter();
|
|
|
|
|
2015-06-19 11:51:55 +00:00
|
|
|
/**
|
|
|
|
* Ensures full remote discovery happens on the next sync.
|
|
|
|
*
|
2019-02-13 13:18:54 +00:00
|
|
|
* Equivalent to calling schedulePathForRemoteDiscovery() for all files.
|
2015-06-19 11:51:55 +00:00
|
|
|
*/
|
|
|
|
void forceRemoteDiscoveryNextSync();
|
|
|
|
|
2015-10-05 03:20:09 +00:00
|
|
|
/* Because sqlite transactions are really slow, we encapsulate everything in big transactions
|
2013-11-18 08:59:59 +00:00
|
|
|
* Commit will actually commit the transaction and create a new one.
|
|
|
|
*/
|
2013-11-21 10:13:58 +00:00
|
|
|
void commit(const QString &context, bool startTrans = true);
|
2014-10-20 15:20:58 +00:00
|
|
|
void commitIfNeededAndStartNewTransaction(const QString &context);
|
2013-11-18 08:59:59 +00:00
|
|
|
|
2019-04-23 11:38:58 +00:00
|
|
|
/** Open the db if it isn't already.
|
|
|
|
*
|
|
|
|
* This usually creates some temporary files next to the db file, like
|
|
|
|
* $dbfile-shm or $dbfile-wal.
|
|
|
|
*
|
2023-06-02 11:55:08 +00:00
|
|
|
* returns true if it could be opened or is currently opened.
|
2014-04-01 11:41:47 +00:00
|
|
|
*/
|
2019-04-23 11:38:58 +00:00
|
|
|
bool open();
|
|
|
|
|
2023-06-02 11:55:08 +00:00
|
|
|
/** Returns whether the db is currently opened. */
|
2019-04-23 11:38:58 +00:00
|
|
|
bool isOpen();
|
|
|
|
|
|
|
|
/** Close the database */
|
|
|
|
void close();
|
2014-04-01 11:41:47 +00:00
|
|
|
|
2015-11-23 10:53:06 +00:00
|
|
|
/**
|
|
|
|
* Returns the checksum type for an id.
|
|
|
|
*/
|
|
|
|
QByteArray getChecksumType(int checksumTypeId);
|
|
|
|
|
2016-08-02 08:30:49 +00:00
|
|
|
/**
|
|
|
|
* The data-fingerprint used to detect backup
|
|
|
|
*/
|
|
|
|
void setDataFingerprint(const QByteArray &dataFingerprint);
|
|
|
|
QByteArray dataFingerprint();
|
|
|
|
|
2017-12-02 10:40:43 +00:00
|
|
|
|
|
|
|
// Conflict record functions
|
|
|
|
|
|
|
|
/// Store a new or updated record in the database
|
|
|
|
void setConflictRecord(const ConflictRecord &record);
|
|
|
|
|
2018-03-28 12:37:21 +00:00
|
|
|
/// Retrieve a conflict record by path of the file with the conflict tag
|
2017-12-02 10:40:43 +00:00
|
|
|
ConflictRecord conflictRecord(const QByteArray &path);
|
|
|
|
|
2022-11-30 09:34:49 +00:00
|
|
|
/// Retrieve a conflict record by path of the file with the conflict tag
|
|
|
|
ConflictRecord caseConflictRecordByBasePath(const QString &baseNamePath);
|
|
|
|
|
|
|
|
/// Retrieve a conflict record by path of the file with the conflict tag
|
|
|
|
ConflictRecord caseConflictRecordByPath(const QString &path);
|
|
|
|
|
|
|
|
/// Return all paths of files with a conflict tag in the name and records in the db
|
|
|
|
QByteArrayList caseClashConflictRecordPaths();
|
|
|
|
|
2018-03-28 12:37:21 +00:00
|
|
|
/// Delete a conflict record by path of the file with the conflict tag
|
2017-12-02 10:40:43 +00:00
|
|
|
void deleteConflictRecord(const QByteArray &path);
|
|
|
|
|
2018-03-28 12:37:21 +00:00
|
|
|
/// Return all paths of files with a conflict tag in the name and records in the db
|
2017-12-02 10:40:43 +00:00
|
|
|
QByteArrayList conflictRecordPaths();
|
|
|
|
|
2020-10-07 12:51:04 +00:00
|
|
|
/** Find the base name for a conflict file name, using journal or name pattern
|
|
|
|
*
|
|
|
|
* The path must be sync-folder relative.
|
|
|
|
*
|
|
|
|
* Will return an empty string if it's not even a conflict file by pattern.
|
|
|
|
*/
|
|
|
|
QByteArray conflictFileBaseName(const QByteArray &conflictName);
|
2017-12-02 10:40:43 +00:00
|
|
|
|
2017-02-15 12:27:41 +00:00
|
|
|
/**
|
|
|
|
* Delete any file entry. This will force the next sync to re-sync everything as if it was new,
|
|
|
|
* restoring everyfile on every remote. If a file is there both on the client and server side,
|
|
|
|
* it will be a conflict that will be automatically resolved if the file is the same.
|
|
|
|
*/
|
|
|
|
void clearFileTable();
|
|
|
|
|
2018-05-28 12:49:02 +00:00
|
|
|
/**
|
|
|
|
* Set the 'ItemTypeVirtualFileDownload' to all the files that have the ItemTypeVirtualFile flag
|
|
|
|
* within the directory specified path path
|
2019-01-08 11:24:15 +00:00
|
|
|
*
|
|
|
|
* The path "" marks everything.
|
2018-05-28 12:49:02 +00:00
|
|
|
*/
|
|
|
|
void markVirtualFileForDownloadRecursively(const QByteArray &path);
|
|
|
|
|
2023-01-25 17:09:37 +00:00
|
|
|
void setE2EeLockedFolder(const QByteArray &folderId, const QByteArray &folderToken);
|
|
|
|
QByteArray e2EeLockedFolder(const QByteArray &folderId);
|
|
|
|
QList<QPair<QByteArray, QByteArray>> e2EeLockedFolders();
|
|
|
|
void deleteE2EeLockedFolder(const QByteArray &folderId);
|
|
|
|
|
2019-01-29 09:53:47 +00:00
|
|
|
/** Grouping for all functions relating to pin states,
|
2018-12-20 10:24:41 +00:00
|
|
|
*
|
2019-01-29 09:53:47 +00:00
|
|
|
* Use internalPinStates() to get at them.
|
2018-12-20 10:24:41 +00:00
|
|
|
*/
|
2019-01-29 09:53:47 +00:00
|
|
|
struct OCSYNC_EXPORT PinStateInterface
|
|
|
|
{
|
|
|
|
PinStateInterface(const PinStateInterface &) = delete;
|
|
|
|
PinStateInterface(PinStateInterface &&) = delete;
|
2018-12-20 10:24:41 +00:00
|
|
|
|
2019-01-29 09:53:47 +00:00
|
|
|
/**
|
|
|
|
* Gets the PinState for the path without considering parents.
|
|
|
|
*
|
|
|
|
* If a path has no explicit PinState "Inherited" is returned.
|
|
|
|
*
|
|
|
|
* The path should not have a trailing slash.
|
|
|
|
* It's valid to use the root path "".
|
|
|
|
*
|
|
|
|
* Returns none on db error.
|
|
|
|
*/
|
|
|
|
Optional<PinState> rawForPath(const QByteArray &path);
|
2018-11-26 12:40:51 +00:00
|
|
|
|
2019-01-29 09:53:47 +00:00
|
|
|
/**
|
|
|
|
* Gets the PinState for the path after inheriting from parents.
|
|
|
|
*
|
|
|
|
* If the exact path has no entry or has an Inherited state,
|
|
|
|
* the state of the closest parent path is returned.
|
|
|
|
*
|
|
|
|
* The path should not have a trailing slash.
|
|
|
|
* It's valid to use the root path "".
|
|
|
|
*
|
|
|
|
* Never returns PinState::Inherited. If the root is "Inherited"
|
|
|
|
* or there's an error, "AlwaysLocal" is returned.
|
|
|
|
*
|
|
|
|
* Returns none on db error.
|
|
|
|
*/
|
|
|
|
Optional<PinState> effectiveForPath(const QByteArray &path);
|
2018-11-26 12:40:51 +00:00
|
|
|
|
2019-04-03 08:53:04 +00:00
|
|
|
/**
|
|
|
|
* Like effectiveForPath() but also considers subitem pin states.
|
|
|
|
*
|
|
|
|
* If the path's pin state and all subitem's pin states are identical
|
|
|
|
* then that pin state will be returned.
|
|
|
|
*
|
|
|
|
* If some subitem's pin state is different from the path's state,
|
|
|
|
* PinState::Inherited will be returned. Inherited isn't returned in
|
|
|
|
* any other cases.
|
|
|
|
*
|
|
|
|
* It's valid to use the root path "".
|
|
|
|
* Returns none on db error.
|
|
|
|
*/
|
|
|
|
Optional<PinState> effectiveForPathRecursive(const QByteArray &path);
|
|
|
|
|
2019-01-29 09:53:47 +00:00
|
|
|
/**
|
|
|
|
* Sets a path's pin state.
|
|
|
|
*
|
|
|
|
* The path should not have a trailing slash.
|
|
|
|
* It's valid to use the root path "".
|
|
|
|
*/
|
|
|
|
void setForPath(const QByteArray &path, PinState state);
|
2018-12-21 09:35:07 +00:00
|
|
|
|
2019-01-29 09:53:47 +00:00
|
|
|
/**
|
|
|
|
* Wipes pin states for a path and below.
|
|
|
|
*
|
|
|
|
* Used when the user asks a subtree to have a particular pin state.
|
|
|
|
* The path should not have a trailing slash.
|
|
|
|
* The path "" wipes every entry.
|
|
|
|
*/
|
|
|
|
void wipeForPathAndBelow(const QByteArray &path);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns list of all paths with their pin state as in the db.
|
|
|
|
*
|
|
|
|
* Returns nothing on db error.
|
|
|
|
* Note that this will have an entry for "".
|
|
|
|
*/
|
|
|
|
Optional<QVector<QPair<QByteArray, PinState>>> rawList();
|
|
|
|
|
|
|
|
SyncJournalDb *_db;
|
|
|
|
};
|
|
|
|
friend struct PinStateInterface;
|
|
|
|
|
|
|
|
/** Access to PinStates stored in the database.
|
2019-01-08 14:15:17 +00:00
|
|
|
*
|
2019-01-29 09:53:47 +00:00
|
|
|
* Important: Not all vfs plugins store the pin states in the database,
|
|
|
|
* prefer to use Vfs::pinState() etc.
|
2019-01-08 14:15:17 +00:00
|
|
|
*/
|
2019-01-29 09:53:47 +00:00
|
|
|
PinStateInterface internalPinStates();
|
2019-01-08 14:15:17 +00:00
|
|
|
|
2020-11-26 14:27:03 +00:00
|
|
|
/**
|
|
|
|
* Only used for auto-test:
|
|
|
|
* when positive, will decrease the counter for every database operation.
|
|
|
|
* reaching 0 makes the operation fails
|
|
|
|
*/
|
|
|
|
int autotestFailCounter = -1;
|
|
|
|
|
2023-01-24 20:21:34 +00:00
|
|
|
public slots:
|
|
|
|
/// Store a new or updated record in the database
|
2023-04-07 15:27:14 +00:00
|
|
|
void setCaseConflictRecord(const OCC::ConflictRecord &record);
|
2023-01-24 20:21:34 +00:00
|
|
|
|
|
|
|
/// Delete a case clash conflict record by path of the file with the conflict tag
|
|
|
|
void deleteCaseClashConflictByPathRecord(const QString &path);
|
|
|
|
|
2013-10-03 13:27:29 +00:00
|
|
|
private:
|
2017-09-14 14:34:14 +00:00
|
|
|
int getFileRecordCount();
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] bool updateDatabaseStructure();
|
|
|
|
[[nodiscard]] bool updateMetadataTableStructure();
|
|
|
|
[[nodiscard]] bool updateErrorBlacklistTableStructure();
|
2014-10-14 09:14:57 +00:00
|
|
|
bool sqlFail(const QString &log, const SqlQuery &query);
|
2013-11-25 14:11:37 +00:00
|
|
|
void commitInternal(const QString &context, bool startTrans = true);
|
|
|
|
void startTransaction();
|
|
|
|
void commitTransaction();
|
2018-03-14 10:50:55 +00:00
|
|
|
QVector<QByteArray> tableColumns(const QByteArray &table);
|
2014-04-01 11:41:47 +00:00
|
|
|
bool checkConnect();
|
2013-10-25 11:30:45 +00:00
|
|
|
|
2015-06-19 11:51:55 +00:00
|
|
|
// Same as forceRemoteDiscoveryNextSync but without acquiring the lock
|
|
|
|
void forceRemoteDiscoveryNextSyncLocked();
|
|
|
|
|
2015-10-28 10:00:03 +00:00
|
|
|
// Returns the integer id of the checksum type
|
|
|
|
//
|
|
|
|
// Returns 0 on failure and for empty checksum types.
|
2022-08-03 13:25:19 +00:00
|
|
|
[[nodiscard]] int mapChecksumType(const QByteArray &checksumType);
|
2015-10-28 10:00:03 +00:00
|
|
|
|
2014-10-14 09:14:57 +00:00
|
|
|
SqlDatabase _db;
|
2014-10-13 12:49:53 +00:00
|
|
|
QString _dbFile;
|
2021-09-03 19:55:41 +00:00
|
|
|
QRecursiveMutex _mutex; // Public functions are protected with the mutex.
|
2018-11-06 09:45:22 +00:00
|
|
|
QMap<QByteArray, int> _checksymTypeCache;
|
2023-02-06 09:38:59 +00:00
|
|
|
int _transaction = 0;
|
|
|
|
bool _metadataTableIsEmpty = false;
|
2015-10-30 13:03:08 +00:00
|
|
|
|
2018-02-16 09:33:35 +00:00
|
|
|
/* Storing etags to these folders, or their parent folders, is filtered out.
|
|
|
|
*
|
2019-02-13 13:18:54 +00:00
|
|
|
* When schedulePathForRemoteDiscovery() is called some etags to _invalid_ in the
|
2018-02-16 09:33:35 +00:00
|
|
|
* database. If this is done during a sync run, a later propagation job might
|
|
|
|
* undo that by writing the correct etag to the database instead. This filter
|
|
|
|
* will prevent this write and instead guarantee the _invalid_ etag stays in
|
|
|
|
* place.
|
|
|
|
*
|
|
|
|
* The list is cleared on close() (end of sync run) and explicitly with
|
|
|
|
* clearEtagStorageFilter() (start of sync run).
|
2018-02-07 12:05:41 +00:00
|
|
|
*
|
|
|
|
* The contained paths have a trailing /.
|
2014-08-07 10:10:32 +00:00
|
|
|
*/
|
2018-02-16 09:33:35 +00:00
|
|
|
QList<QByteArray> _etagStorageFilter;
|
2017-09-13 07:27:07 +00:00
|
|
|
|
|
|
|
/** The journal mode to use for the db.
|
|
|
|
*
|
|
|
|
* Typically WAL initially, but may be set to other modes via environment
|
|
|
|
* variable, for specific filesystems, or when WAL fails in a particular way.
|
|
|
|
*/
|
2018-03-14 10:50:55 +00:00
|
|
|
QByteArray _journalMode;
|
2021-01-18 13:36:33 +00:00
|
|
|
|
|
|
|
PreparedSqlQueryManager _queryManager;
|
2013-10-03 13:27:29 +00:00
|
|
|
};
|
|
|
|
|
2017-09-01 16:11:43 +00:00
|
|
|
bool OCSYNC_EXPORT
|
2014-11-19 13:14:54 +00:00
|
|
|
operator==(const SyncJournalDb::DownloadInfo &lhs,
|
|
|
|
const SyncJournalDb::DownloadInfo &rhs);
|
2017-09-01 16:11:43 +00:00
|
|
|
bool OCSYNC_EXPORT
|
2014-11-19 13:14:54 +00:00
|
|
|
operator==(const SyncJournalDb::UploadInfo &lhs,
|
|
|
|
const SyncJournalDb::UploadInfo &rhs);
|
2014-10-23 13:15:47 +00:00
|
|
|
|
2014-11-09 21:34:07 +00:00
|
|
|
} // namespace OCC
|
2013-10-03 13:27:29 +00:00
|
|
|
#endif // SYNCJOURNALDB_H
|