1 | /* |
2 | * Copyright (C) by Klaas Freitag <freitag@owncloud.com> |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * for more details. |
13 | */ |
14 | |
15 | #ifndef SYNCFILEITEM_H |
16 | #define SYNCFILEITEM_H |
17 | |
18 | #include <QVector> |
19 | #include <QString> |
20 | #include <QDateTime> |
21 | #include <QMetaType> |
22 | #include <QSharedPointer> |
23 | |
24 | #include <csync.h> |
25 | |
26 | namespace OCC { |
27 | |
28 | class SyncFileItem; |
29 | class SyncJournalFileRecord; |
30 | typedef QSharedPointer<SyncFileItem> SyncFileItemPtr; |
31 | |
32 | /** |
33 | * @brief The SyncFileItem class |
34 | * @ingroup libsync |
35 | */ |
36 | class SyncFileItem |
37 | { |
38 | public: |
39 | enum Direction { |
40 | None = 0, |
41 | Up, |
42 | Down |
43 | }; |
44 | |
45 | enum Status { // stored in 4 bits |
46 | NoStatus, |
47 | |
48 | FatalError, ///< Error that causes the sync to stop |
49 | NormalError, ///< Error attached to a particular file |
50 | SoftError, ///< More like an information |
51 | |
52 | Success, ///< The file was properly synced |
53 | |
54 | /** Marks a conflict, old or new. |
55 | * |
56 | * With instruction:IGNORE: detected an old unresolved old conflict |
57 | * With instruction:CONFLICT: a new conflict this sync run |
58 | */ |
59 | Conflict, |
60 | |
61 | FileIgnored, ///< The file is in the ignored list (or blacklisted with no retries left) |
62 | Restoration, ///< The file was restored because what should have been done was not allowed |
63 | |
64 | /** For errors that should only appear in the error view. |
65 | * |
66 | * Some errors also produce a summary message. Usually displaying that message is |
67 | * sufficient, but the individual errors should still appear in the issues tab. |
68 | * |
69 | * These errors do cause the sync to fail. |
70 | * |
71 | * A NormalError that isn't as prominent. |
72 | */ |
73 | DetailError, |
74 | |
75 | /** For files whose errors were blacklisted |
76 | * |
77 | * If an file is blacklisted due to an error it isn't even reattempted. These |
78 | * errors should appear in the issues tab but should be silent otherwise. |
79 | * |
80 | * A SoftError caused by blacklisting. |
81 | */ |
82 | BlacklistedError |
83 | }; |
84 | |
85 | SyncJournalFileRecord toSyncJournalFileRecordWithInode(const QString &localFileName); |
86 | |
87 | /** Creates a basic SyncFileItem from a DB record |
88 | * |
89 | * This is intended in particular for read-update-write cycles that need |
90 | * to go through a a SyncFileItem, like PollJob. |
91 | */ |
92 | static SyncFileItemPtr fromSyncJournalFileRecord(const SyncJournalFileRecord &rec); |
93 | |
94 | |
95 | SyncFileItem() |
96 | : _type(ItemTypeSkip) |
97 | , _direction(None) |
98 | , _serverHasIgnoredFiles(false) |
99 | , _hasBlacklistEntry(false) |
100 | , _errorMayBeBlacklisted(false) |
101 | , _status(NoStatus) |
102 | , _isRestoration(false) |
103 | , _httpErrorCode(0) |
104 | , _affectedItems(1) |
105 | , _instruction(CSYNC_INSTRUCTION_NONE) |
106 | , _modtime(0) |
107 | , _size(0) |
108 | , _inode(0) |
109 | , _previousSize(0) |
110 | , _previousModtime(0) |
111 | { |
112 | } |
113 | |
114 | friend bool operator==(const SyncFileItem &item1, const SyncFileItem &item2) |
115 | { |
116 | return item1._originalFile == item2._originalFile; |
117 | } |
118 | |
119 | friend bool operator<(const SyncFileItem &item1, const SyncFileItem &item2) |
120 | { |
121 | // Sort by destination |
122 | auto d1 = item1.destination(); |
123 | auto d2 = item2.destination(); |
124 | |
125 | // But this we need to order it so the slash come first. It should be this order: |
126 | // "foo", "foo/bar", "foo-bar" |
127 | // This is important since we assume that the contents of a folder directly follows |
128 | // its contents |
129 | |
130 | auto data1 = d1.constData(); |
131 | auto data2 = d2.constData(); |
132 | |
133 | // Find the length of the largest prefix |
134 | int prefixL = 0; |
135 | auto minSize = std::min(d1.size(), d2.size()); |
136 | while (prefixL < minSize && data1[prefixL] == data2[prefixL]) { |
137 | prefixL++; |
138 | } |
139 | |
140 | if (prefixL == d2.size()) |
141 | return false; |
142 | if (prefixL == d1.size()) |
143 | return true; |
144 | |
145 | if (data1[prefixL] == '/') |
146 | return true; |
147 | if (data2[prefixL] == '/') |
148 | return false; |
149 | |
150 | return data1[prefixL] < data2[prefixL]; |
151 | } |
152 | |
153 | QString destination() const |
154 | { |
155 | if (!_renameTarget.isEmpty()) { |
156 | return _renameTarget; |
157 | } |
158 | return _file; |
159 | } |
160 | |
161 | bool isEmpty() const |
162 | { |
163 | return _file.isEmpty(); |
164 | } |
165 | |
166 | bool isDirectory() const |
167 | { |
168 | return _type == ItemTypeDirectory; |
169 | } |
170 | |
171 | /** |
172 | * True if the item had any kind of error. |
173 | */ |
174 | bool hasErrorStatus() const |
175 | { |
176 | return _status == SyncFileItem::SoftError |
177 | || _status == SyncFileItem::NormalError |
178 | || _status == SyncFileItem::FatalError |
179 | || !_errorString.isEmpty(); |
180 | } |
181 | |
182 | /** |
183 | * Whether this item should appear on the issues tab. |
184 | */ |
185 | bool showInIssuesTab() const |
186 | { |
187 | return hasErrorStatus() || _status == SyncFileItem::Conflict; |
188 | } |
189 | |
190 | /** |
191 | * Whether this item should appear on the protocol tab. |
192 | */ |
193 | bool showInProtocolTab() const |
194 | { |
195 | return !showInIssuesTab() |
196 | // Don't show conflicts that were resolved as "not a conflict after all" |
197 | && !(_instruction == CSYNC_INSTRUCTION_CONFLICT && _status == SyncFileItem::Success); |
198 | } |
199 | |
200 | // Variables useful for everybody |
201 | QString _file; |
202 | QString _renameTarget; |
203 | ItemType _type BITFIELD(3); |
204 | Direction _direction BITFIELD(3); |
205 | bool _serverHasIgnoredFiles BITFIELD(1); |
206 | |
207 | /// Whether there's an entry in the blacklist table. |
208 | /// Note: that entry may have retries left, so this can be true |
209 | /// without the status being FileIgnored. |
210 | bool _hasBlacklistEntry BITFIELD(1); |
211 | |
212 | /** If true and NormalError, this error may be blacklisted |
213 | * |
214 | * Note that non-local errors (httpErrorCode!=0) may also be |
215 | * blacklisted independently of this flag. |
216 | */ |
217 | bool _errorMayBeBlacklisted BITFIELD(1); |
218 | |
219 | // Variables useful to report to the user |
220 | Status _status BITFIELD(4); |
221 | bool _isRestoration BITFIELD(1); // The original operation was forbidden, and this is a restoration |
222 | quint16 _httpErrorCode; |
223 | RemotePermissions _remotePerm; |
224 | QString _errorString; // Contains a string only in case of error |
225 | QByteArray _responseTimeStamp; |
226 | QByteArray _requestId; // X-Request-Id of the failed request |
227 | quint32 _affectedItems; // the number of affected items by the operation on this item. |
228 | // usually this value is 1, but for removes on dirs, it might be much higher. |
229 | |
230 | // Variables used by the propagator |
231 | csync_instructions_e _instruction; |
232 | QString _originalFile; // as it is in the csync tree |
233 | time_t _modtime; |
234 | QByteArray _etag; |
235 | quint64 _size; |
236 | quint64 _inode; |
237 | QByteArray _fileId; |
238 | |
239 | // This is the value for the 'new' side, matching with _size and _modtime. |
240 | // |
241 | // When is this set, and is it the local or the remote checksum? |
242 | // - if mtime or size changed locally for *.eml files (local checksum) |
243 | // - for potential renames of local files (local checksum) |
244 | // - for conflicts (remote checksum) |
245 | QByteArray ; |
246 | |
247 | // The size and modtime of the file getting overwritten (on the disk for downloads, on the server for uploads). |
248 | quint64 _previousSize; |
249 | time_t _previousModtime; |
250 | |
251 | QString _directDownloadUrl; |
252 | QString _directDownloadCookies; |
253 | }; |
254 | |
255 | inline bool operator<(const SyncFileItemPtr &item1, const SyncFileItemPtr &item2) |
256 | { |
257 | return *item1 < *item2; |
258 | } |
259 | |
260 | typedef QVector<SyncFileItemPtr> SyncFileItemVector; |
261 | } |
262 | |
263 | Q_DECLARE_METATYPE(OCC::SyncFileItem) |
264 | Q_DECLARE_METATYPE(OCC::SyncFileItemPtr) |
265 | |
266 | #endif // SYNCFILEITEM_H |
267 | |