summaryrefslogtreecommitdiff
path: root/plugins-alternative/CopyEngine/Rsync/ListThread.h
blob: ab4ad649541fd30471d9ab13a5aab5132d0bb20c (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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/** \file ListThread.h
\brief Define the list thread, and management to the action to do
\author alpha_one_x86
\version 0.3
\date 2011 */

#ifndef LISTTHREAD_H
#define LISTTHREAD_H

#include <QThread>
#include <QObject>
#include <QList>
#include <QStringList>
#include <QFileInfo>
#include <QSemaphore>
#include <QTextStream>
#include <QFile>

#include "../../../interface/PluginInterface_CopyEngine.h"
#include "scanFileOrFolder.h"
#include "TransferThread.h"
#include "MkPath.h"
#include "RmPath.h"
#include "Environment.h"

/// \brief Define the list thread, and management to the action to do
class ListThread : public QThread
{
	Q_OBJECT
public:
	explicit ListThread(FacilityInterface * facilityInterface);
	~ListThread();
	//duplication copy detection
	/** \brief compare the current sources of the copy, with the passed arguments
	 * \param sources the sources list to compares with the current sources list
	 * \return true if have same sources, else false (or empty) */
	bool haveSameSource(QStringList sources);
	/** \brief compare the current destination of the copy, with the passed arguments
	 * \param destination the destination to compares with the current destination
	 * \return true if have same destination, else false (or empty) */
	bool haveSameDestination(QString destination);
	//external soft like file browser have send copy/move list to do
	/** \brief send copy with destination
	 * \param sources the sources list to copy
	 * \param destination the destination to copy
	 * \return true if the copy have been accepted */
	bool newCopy(QStringList sources,QString destination);
	/** \brief send move without destination, ask the destination
	 * \param sources the sources list to move
	 * \param destination the destination to move
	 * \return true if the move have been accepted */
	bool newMove(QStringList sources,QString destination);
	/** \brief get the speed limitation
	 * < -1 if not able, 0 if disabled */
	qint64 getSpeedLimitation();
	/** \brief to set drives detected
	 * specific to this copy engine */
	void setDrive(QStringList drives);
	/// \brief to set the collision action
	void setCollisionAction(FileExistsAction alwaysDoThisActionForFileExists);
	/** \brief to sync the transfer list
	 * Used when the interface is changed, useful to minimize the memory size */
	void syncTransferList();
	/// \brief to store one action to do
	struct actionToDoTransfer
	{
		quint64 id;
		qint64 size;///< Used to set: used in case of transfer or remainingInode for drop folder
		QFileInfo source;///< Used to set: source for transfer, folder to create, folder to drop
		QFileInfo destination;
		CopyMode mode;
		bool isRunning;///< store if the action si running
		//TransferThread * transfer; // -> see transferThreadList
	};
	QList<actionToDoTransfer> actionToDoListTransfer;
	/// \brief get action type
	enum ActionType
	{
		ActionType_MkPath=1,
		ActionType_RmPath=2,
		ActionType_RmSync=3
	};
	/// \brief to store one action to do
	struct actionToDoInode
	{
		ActionType type;///< \see ActionType
		quint64 id;
		qint64 size;///< Used to set: used in case of transfer or remainingInode for drop folder
		QFileInfo folder;///< Used to set: source for transfer, folder to create, folder to drop
		bool isRunning;///< store if the action si running
	};
	QList<actionToDoInode> actionToDoListInode;
	QList<actionToDoInode> actionToDoListInode_afterTheTransfer;
	int numberOfInodeOperation;
	//dir operation thread queue
	MkPath mkPathQueue;
	RmPath rmPathQueue;
	//to get the return value from copyEngine
	bool getReturnBoolToCopyEngine();
	QPair<quint64,quint64> getReturnPairQuint64ToCopyEngine();
	ItemOfCopyList getReturnItemOfCopyListToCopyEngine();

	void set_doChecksum(bool doChecksum);
	void set_checksumIgnoreIfImpossible(bool checksumIgnoreIfImpossible);
	void set_checksumOnlyOnError(bool checksumOnlyOnError);
	void set_osBuffer(bool osBuffer);
	void set_osBufferLimited(bool osBufferLimited);
public slots:
	//action on the copy
	/// \brief put the transfer in pause
	void pause();
	/// \brief resume the transfer
	void resume();
	/** \brief skip one transfer entry
	 * \param id id of the file to remove */
	void skip(const quint64 &id);
	/** \brief skip as interanl one transfer entry
	 * \param id id of the file to remove */
	bool skipInternal(const quint64 &id);
	/// \brief cancel all the transfer
	void cancel();
	//edit the transfer list
	/** \brief remove the selected item
	 * \param ids ids is the id list of the selected items */
	void removeItems(const QList<int> &ids);
	/** \brief move on top of the list the selected item
	 * \param ids ids is the id list of the selected items */
	void moveItemsOnTop(QList<int> ids);
	/** \brief move up the list the selected item
	 * \param ids ids is the id list of the selected items */
	void moveItemsUp(QList<int> ids);
	/** \brief move down the list the selected item
	 * \param ids ids is the id list of the selected items */
	void moveItemsDown(QList<int> ids);
	/** \brief move on bottom of the list the selected item
	 * \param ids ids is the id list of the selected items */
	void moveItemsOnBottom(QList<int> ids);

	/** \brief give the forced mode, to export/import transfer list */
	void forceMode(const CopyMode &mode);
	/// \brief export the transfer list into a file
	void exportTransferList(const QString &fileName);
	/// \brief import the transfer list into a file
	void importTransferList(const QString &fileName);

	/// \brief set the folder local colision
	void setFolderColision(FolderExistsAction alwaysDoThisActionForFolderExists);
	/** \brief to set the speed limitation
	 * -1 if not able, 0 if disabled */
	bool setSpeedLimitation(const qint64 &speedLimitation);
	/// \brief set the copy info and options before runing
	void setRightTransfer(const bool doRightTransfer);
	/// \brief set keep date
	void setKeepDate(const bool keepDate);
	/// \brief set block size in KB
	void setBlockSize(const int blockSize);
	/// \brief set auto start
	void setAutoStart(const bool autoStart);
	/// \brief set rsync
	void setRsync(const bool rsync);
	/// \brief set check destination folder
	void setCheckDestinationFolderExists(const bool checkDestinationFolderExists);
	/// \brief set data local to the thread
	void setAlwaysFileExistsAction(FileExistsAction alwaysDoThisActionForFileExists);
	/// \brief do new actions, start transfer
	void doNewActions_start_transfer();
	/** \brief lunch the pre-op or inode op
	  1) locate the next next item to do into the both list
	    1a) optimisation posible on the mkpath/rmpath
	  2) determine what need be lunched
	  3) lunch it, rerun the 2)
	  */
	void doNewActions_inode_manipulation();
	/// \brief restart transfer if it can
	void restartTransferIfItCan();

	/// \brief update the transfer stat
	void newTransferStat(TransferStat stat,quint64 id);

	void set_osBufferLimit(unsigned int osBufferLimit);
	void set_setFilters(QList<Filters_rules> include,QList<Filters_rules> exclude);
	void set_sendNewRenamingRules(QString firstRenamingRule,QString otherRenamingRule);

	//send action done
	void sendActionDone();
	//send progression
	void sendProgression();
private:
	QSemaphore mkpathTransfer;
	QString sourceDrive;
	bool sourceDriveMultiple;
	bool stopIt;
	QString destinationDrive;
	bool destinationDriveMultiple;
	QList<scanFileOrFolder *> scanFileOrFolderThreadsPool;
	int numberOfTransferIntoToDoList;
	QList<TransferThread *>		transferThreadList;
	scanFileOrFolder *		newScanThread(CopyMode mode);
	quint64				bytesToTransfer;
	quint64				bytesTransfered;
	bool				autoStart;
	bool				rsync;
	bool				putInPause;
	QList<returnActionOnCopyList>	actionDone;///< to action to send to the interface
	quint64				idIncrementNumber;///< to store the last id returned
	qint64				actualRealByteTransfered;
	int				preOperationNumber;
	int				numberOfTranferRuning;
	int				maxSpeed;///< in KB/s, assume as 0KB/s as default like every where
	FolderExistsAction		alwaysDoThisActionForFolderExists;
	bool				checkDestinationFolderExists;
	bool				doChecksum;
	bool				checksumIgnoreIfImpossible;
	bool				checksumOnlyOnError;
	bool				osBuffer;
	bool				osBufferLimited;
	unsigned int			osBufferLimit;
	QList<Filters_rules>		include,exclude;
	CopyMode			mode;
	bool				forcedMode;
	QString				firstRenamingRule;
	QString				otherRenamingRule;

	//add file transfer to do
	quint64 addToTransfer(const QFileInfo& source,const QFileInfo& destination,const CopyMode& mode);
	//generate id number
	quint64 generateIdNumber();
	//warning the first entry is accessible will copy
	bool removeItems(quint64 id);
	//put on top
	bool moveOnTopItem(quint64 id);
	//move up
	bool moveUpItem(quint64 id);
	//move down
	bool moveDownItem(quint64 id);
	//put on bottom
	bool moveOnBottomItem(quint64 id);
	//general transfer
	void startGeneralTransfer();
	//debug windows if needed
	#ifdef ULTRACOPIER_PLUGIN_DEBUG_WINDOW
	QTimer timerUpdateDebugDialog;
	#endif
	FacilityInterface * facilityInterface;
	//temp variable for not always alocate the memory
	int int_for_loop,int_for_internal_loop,int_for_transfer_thread_search,loop_size,loop_sub_size,loop_sub_size_transfer_thread_search,number_rm_path_moved;
	TransferThread *temp_transfer_thread;
	bool isFound;
	bool updateTheStatus_listing,updateTheStatus_copying;
	EngineActionInProgress updateTheStatus_action_in_progress;
	QSemaphore waitConstructor,waitCancel;
	int actionToDoListTransfer_count,actionToDoListInode_count;
	bool doTransfer,doInode;
	qint64 oversize;//used as temp variable
	qint64 currentProgression;
	qint64 copiedSize,totalSize,localOverSize;
	QList<ProgressionItem> progressionList;
	TransferThread* currentTransferThread;
	//memory variable for transfer thread creation
	bool doRightTransfer;
	bool keepDate;
	int blockSize;
	QStringList drives;
	FileExistsAction alwaysDoThisActionForFileExists;
	//to return value to the copyEngine
	bool returnBoolToCopyEngine;
	QPair<quint64,quint64> returnPairQuint64ToCopyEngine;
	QList<ItemOfCopyList> returnListItemOfCopyListToCopyEngine;
	ItemOfCopyList returnItemOfCopyListToCopyEngine;
	ProgressionItem tempItem;

	void realByteTransfered();
private slots:
	void scanThreadHaveFinish(bool skipFirstRemove=false);
	void updateTheStatus();
	void fileTransfer(const QFileInfo &sourceFileInfo,const QFileInfo &destinationFileInfo,const CopyMode &mode);
	//mkpath event
	void mkPathFirstFolderFinish();
	//rmpath event
	void rmPathFirstFolderFinish();
	//transfer is finished
	void transferIsFinished();
	/** \brief put the current file at bottom in case of error
	\note ONLY IN CASE OF ERROR */
	void transferPutAtBottom();
	//transfer is finished
	void transferInodeIsClosed();
	//debug windows if needed
	#ifdef ULTRACOPIER_PLUGIN_DEBUG_WINDOW
	void timedUpdateDebugDialog();
	#endif
	//dialog message
	/// \note Can be call without queue because all call will be serialized
	void fileAlreadyExists(const QFileInfo &source,const QFileInfo &destination,const bool &isSame);
	/// \note Can be call without queue because all call will be serialized
	void errorOnFile(const QFileInfo &fileInfo,const QString &errorString);
	/// \note Can be call without queue because all call will be serialized
	void folderAlreadyExists(const QFileInfo &source,const QFileInfo &destination,const bool &isSame);
	/// \note Can be call without queue because all call will be serialized
	void errorOnFolder(const QFileInfo &fileInfo,const QString &errorString);
	//to run the thread
	void run();
	/// \to create transfer thread
	void createTransferThread();
	//mk path to do
	quint64 addToMkPath(const QString& folder);
	//add rm path to do
	void addToRmPath(const QString& folder,const int& inodeToRemove);
	//rsync rm
	void addToRmForRsync(const QString& inode);
	//send the progression, after full reset of the interface (then all is empty)
	void syncTransferList_internal();
signals:
        //send information about the copy
        void actionInProgess(EngineActionInProgress);	//should update interface information on this event

	void newActionOnList(const QList<returnActionOnCopyList> &);///very important, need be temporized to group the modification to do and not flood the interface
	void syncReady();

	/** \brief to get the progression for a specific file
	 * \param id the id of the transfer, id send during population the transfer list
	 * first = current transfered byte, second = byte to transfer */
	void pushFileProgression(const QList<ProgressionItem> &progressionList);
	//get information about the copy
	/** \brief to get the general progression
	 * first = current transfered byte, second = byte to transfer */
	void pushGeneralProgression(const quint64 &,const quint64 &);

	void newFolderListing(const QString &path);
	void newCollisionAction(QString action);
	void newErrorAction(QString action);
        void isInPause(bool);

	//when can be deleted
	void canBeDeleted();

        //send error occurred
        void error(QString path,quint64 size,QDateTime mtime,QString error);
        //for the extra logging
        void rmPath(QString path);
        void mkPath(QString path);
        /// \brief To debug source
	#ifdef ULTRACOPIER_PLUGIN_DEBUG
	void debugInformation(DebugLevel level,QString fonction,QString text,QString file,int ligne);
	#endif
	#ifdef ULTRACOPIER_PLUGIN_DEBUG_WINDOW
	void updateTheDebugInfo(QStringList,QStringList,int);
	#endif

	//other signal
	/// \note Can be call without queue because all call will be serialized
	void send_fileAlreadyExists(QFileInfo source,QFileInfo destination,bool isSame,TransferThread * thread);
	/// \note Can be call without queue because all call will be serialized
	void send_errorOnFile(QFileInfo fileInfo,QString errorString,TransferThread * thread);
	/// \note Can be call without queue because all call will be serialized
	void send_folderAlreadyExists(QFileInfo source,QFileInfo destination,bool isSame,scanFileOrFolder * thread);
	/// \note Can be call without queue because all call will be serialized
	void send_errorOnFolder(QFileInfo fileInfo,QString errorString,scanFileOrFolder * thread);
	//send the progression
	void send_syncTransferList();
	//mkpath error event
	void mkPathErrorOnFolder(QFileInfo fileInfo,QString errorString);
	//rmpath error event
	void rmPathErrorOnFolder(QFileInfo fileInfo,QString errorString);
	//to close
	void tryCancel();
	//to ask new transfer thread
	void askNewTransferThread();

	void warningTransferList(QString warning);
	void errorTransferList(QString error);
	void send_sendNewRenamingRules(QString firstRenamingRule,QString otherRenamingRule);
	void send_realBytesTransfered(quint64);
};

#endif // LISTTHREAD_H