Welcome to mirror list, hosted at ThFree Co, Russian Federation.

syncfileitem.h « libsync « src - github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: eadbaddcaf3c8db3f86b2a371581cbdc5f47f559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
/*
 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */

#ifndef SYNCFILEITEM_H
#define SYNCFILEITEM_H

#include <QVector>
#include <QString>
#include <QDateTime>
#include <QMetaType>
#include <QSharedPointer>

#include <set>

#include <common/utility.h>
#include <csync.h>

#include "owncloudlib.h"

namespace OCC {

class SyncFileItem;
class SyncJournalFileRecord;
typedef QSharedPointer<SyncFileItem> SyncFileItemPtr;

/**
 * @brief The SyncFileItem class
 * @ingroup libsync
 */
class OWNCLOUDSYNC_EXPORT SyncFileItem
{
    Q_GADGET
public:
    enum Direction {
        None = 0,
        Up,
        Down
    };
    Q_ENUM(Direction)

    enum Status { // stored in 4 bits
        NoStatus,

        FatalError, ///< Error that causes the sync to stop
        NormalError, ///< Error attached to a particular file
        SoftError, ///< More like an information

        Success, ///< The file was properly synced

        /** Marks a conflict, old or new.
         *
         * With instruction:IGNORE: detected an old unresolved old conflict
         * With instruction:CONFLICT: a new conflict this sync run
         */
        Conflict,

        FileIgnored, ///< The file has an invalid name or is in the blacklisted with no retries left
        Restoration, ///< The file was restored because what should have been done was not allowed

        /** For errors that should only appear in the error view.
         *
         * Some errors also produce a summary message. Usually displaying that message is
         * sufficient, but the individual errors should still appear in the issues tab.
         *
         * These errors do cause the sync to fail.
         *
         * A NormalError that isn't as prominent.
         */
        DetailError,

        /** For files whose errors were blacklisted
         *
         * If an file is blacklisted due to an error it isn't even reattempted. These
         * errors should appear in the issues tab but should be silent otherwise.
         *
         * A SoftError caused by blacklisting.
         */
        BlacklistedError,

        /**
         * The file is excluded by the ignore list
         */
        Excluded,

        /**
         *  Similar to SoftError but will not cause any error handling
         */
        Message,

        /** For use in an array or vector for the number of items in this enum.
         */
        StatusCount
    };
    Q_ENUM(Status)

    SyncJournalFileRecord toSyncJournalFileRecordWithInode(const QString &localFileName) const;

    /** Creates a basic SyncFileItem from a DB record
     *
     * This is intended in particular for read-update-write cycles that need
     * to go through a a SyncFileItem.
     */
    static SyncFileItemPtr fromSyncJournalFileRecord(const SyncJournalFileRecord &rec);


    SyncFileItem()
        : _type(ItemTypeSkip)
        , _direction(None)
        , _serverHasIgnoredFiles(false)
        , _hasBlacklistEntry(false)
        , _status(NoStatus)
        , _isRestoration(false)
        , _isSelectiveSync(false)
        , _httpErrorCode(0)
        , _affectedItems(1)
        , _instruction(CSYNC_INSTRUCTION_NONE)
        , _modtime(0)
        , _size(0)
        , _inode(0)
        , _previousSize(0)
        , _previousModtime(0)
        , _relevantDirectoyInstruction(false)
    {
    }

    friend bool operator==(const SyncFileItem &item1, const SyncFileItem &item2)
    {
        return item1._originalFile == item2._originalFile;
    }

    friend bool operator<(const SyncFileItem &item1, const SyncFileItem &item2)
    {
        // Sort by destination
        auto d1 = item1.destination();
        auto d2 = item2.destination();

        // But this we need to order it so the slash come first. It should be this order:
        //  "foo", "foo/bar", "foo-bar"
        // This is important since we assume that the contents of a folder directly follows
        // its contents

        auto data1 = d1.constData();
        auto data2 = d2.constData();

        // Find the length of the largest prefix
        int prefixL = 0;
        auto minSize = std::min(d1.size(), d2.size());
        while (prefixL < minSize && data1[prefixL] == data2[prefixL]) {
            prefixL++;
        }

        if (prefixL == d2.size())
            return false;
        if (prefixL == d1.size())
            return true;

        if (data1[prefixL] == QLatin1Char('/'))
            return true;
        if (data2[prefixL] == QLatin1Char('/'))
            return false;

        return data1[prefixL] < data2[prefixL];
    }

    QString destination() const
    {
        if (!_renameTarget.isEmpty()) {
            return _renameTarget;
        }
        return _file;
    }

    bool isEmpty() const
    {
        return _file.isEmpty();
    }

    bool isDirectory() const
    {
        return _type == ItemTypeDirectory;
    }

    /**
     * True if the item had any kind of error.
     */
    bool hasErrorStatus() const
    {
        return _status == SyncFileItem::SoftError
            || _status == SyncFileItem::NormalError
            || _status == SyncFileItem::FatalError
            || !_errorString.isEmpty();
    }

    /**
     * Whether this item should appear on the issues tab.
     */
    bool showInIssuesTab() const
    {
        return hasErrorStatus() || _status == SyncFileItem::Conflict;
    }

    /**
     * Whether this item should appear on the protocol tab.
     */
    bool showInProtocolTab() const
    {
        return (!showInIssuesTab() || _status == SyncFileItem::Restoration)
            // Don't show conflicts that were resolved as "not a conflict after all"
            && !(_instruction == CSYNC_INSTRUCTION_CONFLICT && _status == SyncFileItem::Success);
    }

    // Variables useful for everybody

    /** The syncfolder-relative filesystem path that the operation is about
     *
     * For rename operation this is the rename source and the target is in _renameTarget.
     */
    QString _file;

    /** for renames: the name _file should be renamed to
     * for dehydrations: the name _file should become after dehydration (like adding a suffix)
     * otherwise empty. Use destination() to find the sync target.
     */
    QString _renameTarget;

    /** The db-path of this item.
     *
     * This can easily differ from _file and _renameTarget if parts of the path were renamed.
     */
    QString _originalFile;

    ItemType _type BITFIELD(3);
    Direction _direction BITFIELD(3);
    bool _serverHasIgnoredFiles BITFIELD(1);

    /// Whether there's an entry in the blacklist table.
    /// Note: that entry may have retries left, so this can be true
    /// without the status being FileIgnored.
    bool _hasBlacklistEntry BITFIELD(1);

    // Variables useful to report to the user
    Status _status BITFIELD(4);
    bool _isRestoration BITFIELD(1); // The original operation was forbidden, and this is a restoration
    bool _isSelectiveSync BITFIELD(1); // The file is removed or ignored because it is in the selective sync list
    quint16 _httpErrorCode;
    RemotePermissions _remotePerm;
    QString _errorString; // Contains a string only in case of error
    QString _messageString; // Contains a string only in case of hand crafted events
    QByteArray _responseTimeStamp;
    QByteArray _requestId; // X-Request-Id of the failed request
    quint32 _affectedItems; // the number of affected items by the operation on this item.
    // usually this value is 1, but for removes on dirs, it might be much higher.

    // Variables used by the propagator
    SyncInstructions _instruction;
    time_t _modtime;
    QByteArray _etag;
    qint64 _size;
    quint64 _inode;
    QByteArray _fileId;

    // This is the value for the 'new' side, matching with _size and _modtime.
    //
    // When is this set, and is it the local or the remote checksum?
    // - if mtime or size changed locally for *.eml files (local checksum)
    // - for potential renames of local files (local checksum)
    // - for conflicts (remote checksum)
    QByteArray _checksumHeader;

    // The size and modtime of the file getting overwritten (on the disk for downloads, on the server for uploads).
    qint64 _previousSize;
    time_t _previousModtime;

    QString _directDownloadUrl;
    QString _directDownloadCookies;

    bool _relevantDirectoyInstruction = false;
    bool _finished = false;
};


template <>
OWNCLOUDSYNC_EXPORT QString Utility::enumToDisplayName(SyncFileItem::Status s);


inline bool operator<(const SyncFileItemPtr &item1, const SyncFileItemPtr &item2)
{
    return *item1 < *item2;
}

using SyncFileItemSet = std::set<SyncFileItemPtr>;
}

Q_DECLARE_METATYPE(OCC::SyncFileItemSet)
Q_DECLARE_METATYPE(OCC::SyncFileItem)
Q_DECLARE_METATYPE(OCC::SyncFileItemPtr)

OWNCLOUDSYNC_EXPORT QDebug operator<<(QDebug debug, const OCC::SyncFileItem *item);
inline QDebug operator<<(QDebug debug, const OCC::SyncFileItemPtr &item)
{
    return debug << item.data();
}


#endif // SYNCFILEITEM_H