summaryrefslogtreecommitdiff
path: root/plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp')
-rw-r--r--plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp422
1 files changed, 345 insertions, 77 deletions
diff --git a/plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp b/plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp
index 359a705..7550d8c 100644
--- a/plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp
+++ b/plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp
@@ -6,22 +6,21 @@
#ifdef Q_CC_GNU
//this next header is needed to change file time/date under gcc
#include <utime.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
#endif
-/// \todo manage case resume after error, because previously inode opt free before
-/// \todo manage error in pre and post operation
-/// \todo remove destination when canceled
-/// \todo test if source if closed by end but write error
-/// \todo pointer for readThread and writeThread to destroy the read before the write (prevent dead lock)
-
-/// \bug continue progress when write error
+#ifndef Q_OS_UNIX
+#include <windows.h>
+#endif
TransferThread::TransferThread()
{
start();
moveToThread(this);
needSkip = false;
- stat = Idle;
+ transfer_stat = TransferStat_Idle;
stopIt = false;
fileExistsAction = FileExists_NotSet;
alwaysDoFileExistsAction= FileExists_NotSet;
@@ -46,7 +45,7 @@ TransferThread::~TransferThread()
void TransferThread::run()
{
//ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start: "+QString::number((qint64)QThread::currentThreadId()));
- stat = Idle;
+ transfer_stat = TransferStat_Idle;
stopIt = false;
fileExistsAction = FileExists_NotSet;
alwaysDoFileExistsAction= FileExists_NotSet;
@@ -57,17 +56,18 @@ void TransferThread::run()
connect(this,SIGNAL(internalStartPreOperation()), this, SLOT(preOperation()), Qt::QueuedConnection);
connect(this,SIGNAL(internalStartPostOperation()), this, SLOT(postOperation()), Qt::QueuedConnection);
//the state change operation
- connect(&readThread,SIGNAL(readIsStopped()), &readThread, SLOT(postOperation()), Qt::QueuedConnection);
+ //connect(&readThread,SIGNAL(readIsStopped()), &readThread, SLOT(postOperation()), Qt::QueuedConnection);//commented to do the checksum
connect(&readThread,SIGNAL(opened()), this, SLOT(readIsReady()), Qt::QueuedConnection);
connect(&writeThread,SIGNAL(opened()), this, SLOT(writeIsReady()), Qt::QueuedConnection);
connect(&readThread,SIGNAL(readIsStopped()), this, SLOT(readIsStopped()), Qt::QueuedConnection);
connect(&writeThread,SIGNAL(writeIsStopped()), this, SLOT(writeIsStopped()), Qt::QueuedConnection);
connect(&readThread,SIGNAL(readIsStopped()), &writeThread, SLOT(endIsDetected()), Qt::QueuedConnection);
- connect(&writeThread,SIGNAL(writeIsStopped()), &writeThread, SLOT(postOperation()), Qt::QueuedConnection);
- connect(&readThread,SIGNAL(readIsStopped()), this, SLOT(readIsFinish()), Qt::QueuedConnection);
+ //connect(&writeThread,SIGNAL(writeIsStopped()), &writeThread, SLOT(postOperation()), Qt::QueuedConnection);//commented to do the checksum
connect(&readThread,SIGNAL(closed()), this, SLOT(readIsClosed()), Qt::QueuedConnection);
connect(&writeThread,SIGNAL(closed()), this, SLOT(writeIsClosed()), Qt::QueuedConnection);
connect(&writeThread,SIGNAL(reopened()), this, SLOT(writeThreadIsReopened()), Qt::QueuedConnection);
+ connect(&readThread,SIGNAL(checksumFinish(QByteArray)), this, SLOT(readChecksumFinish(QByteArray)), Qt::QueuedConnection);
+ connect(&writeThread,SIGNAL(checksumFinish(QByteArray)),this, SLOT(writeChecksumFinish(QByteArray)), Qt::QueuedConnection);
//error management
connect(&readThread,SIGNAL(isSeekToZeroAndWait()), this, SLOT(readThreadIsSeekToZeroAndWait()), Qt::QueuedConnection);
connect(&readThread,SIGNAL(resumeAfterErrorByRestartAtTheLastPosition()), this, SLOT(readThreadResumeAfterError()), Qt::QueuedConnection);
@@ -80,13 +80,12 @@ void TransferThread::run()
connect(&writeThread,SIGNAL(debugInformation(DebugLevel,QString,QString,QString,int)),this,SIGNAL(debugInformation(DebugLevel,QString,QString,QString,int)),Qt::QueuedConnection);
#endif
- /// \todo do the current post opt only after the read write opt
exec();
}
-TransferThread::TransferStat TransferThread::getStat()
+TransferStat TransferThread::getStat()
{
- return stat;
+ return transfer_stat;
}
void TransferThread::startTheTransfer()
@@ -96,7 +95,7 @@ void TransferThread::startTheTransfer()
void TransferThread::internalStartTheTransfer()
{
- if(stat==Idle)
+ if(transfer_stat==TransferStat_Idle)
{
if(mode!=Move)
{
@@ -105,12 +104,12 @@ void TransferThread::internalStartTheTransfer()
}
return;
}
- if(stat==PostOperation)
+ if(transfer_stat==TransferStat_PostOperation)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] can't start transfert at PostOperation");
return;
}
- if(stat==Transfer)
+ if(transfer_stat==TransferStat_Transfer)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] can't start transfert at Transfer");
return;
@@ -133,13 +132,13 @@ void TransferThread::internalStartTheTransfer()
void TransferThread::setFiles(const QString &source,const qint64 &size,const QString &destination,const CopyMode &mode)
{
- if(stat!=Idle)
+ if(transfer_stat!=TransferStat_Idle)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] already used, source: "+source+", destination: "+destination);
return;
}
//to prevent multiple file alocation into ListThread::doNewActions_inode_manipulation()
- stat = PreOperation;
+ transfer_stat = TransferStat_PreOperation;
//emit pushStat(stat,transferId);
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start, source: "+source+", destination: "+destination);
this->source = source;
@@ -150,13 +149,14 @@ void TransferThread::setFiles(const QString &source,const qint64 &size,const QSt
canStartTransfer = false;
sended_state_preOperationStopped= false;
canBeMovedDirectlyVariable = false;
+ fileContentError = false;
resetExtraVariable();
emit internalStartPreOperation();
}
void TransferThread::setFileExistsAction(const FileExistsAction &action)
{
- if(stat!=PreOperation)
+ if(transfer_stat!=TransferStat_PreOperation)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] already used, source: "+source+", destination: "+destination);
return;
@@ -177,7 +177,7 @@ void TransferThread::setFileExistsAction(const FileExistsAction &action)
void TransferThread::setFileRename(const QString &nameForRename)
{
- if(stat!=PreOperation)
+ if(transfer_stat!=TransferStat_PreOperation)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] already used, source: "+source+", destination: "+destination);
return;
@@ -207,6 +207,7 @@ void TransferThread::resetExtraVariable()
readIsReadyVariable = false;
writeIsReadyVariable = false;
readIsFinishVariable = false;
+ writeIsFinishVariable = false;
readIsClosedVariable = false;
writeIsClosedVariable = false;
needSkip = false;
@@ -217,7 +218,7 @@ void TransferThread::resetExtraVariable()
void TransferThread::preOperation()
{
- if(stat!=PreOperation)
+ if(transfer_stat!=TransferStat_PreOperation)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] already used, source: "+source+", destination: "+destination);
return;
@@ -258,7 +259,7 @@ void TransferThread::tryOpen()
if(!writeIsOpenVariable)
{
writeError=false;
- writeThread.open(destination,sourceInfo.size());
+ writeThread.open(destination,size,osBuffer && (!osBufferLimited || (osBufferLimited && size<osBufferLimit)));
}
}
@@ -275,7 +276,6 @@ bool TransferThread::isSame()
bool TransferThread::destinationExists()
{
- /// \todo do the overwrite: FileExists_OverwriteIfNotSameModificationDate
//check if destination exists
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] overwrite: "+QString::number(fileExistsAction)+", always action: "+QString::number(alwaysDoFileExistsAction));
if(alwaysDoFileExistsAction==FileExists_Overwrite || readError || writeError)
@@ -284,7 +284,7 @@ bool TransferThread::destinationExists()
{
if(fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_Skip)
{
- stat=Idle;
+ transfer_stat=TransferStat_Idle;
emit postOperationStopped();
return true;
}
@@ -293,31 +293,42 @@ bool TransferThread::destinationExists()
QString absolutePath=destinationInfo.absolutePath();
QString fileName=destinationInfo.fileName();
QString suffix="";
+ QString newFileName;
+ //resolv the suffix
if(fileName.contains(QRegExp("^(.*)(\\.[a-z0-9]+)$")))
{
suffix=fileName;
suffix.replace(QRegExp("^(.*)(\\.[a-z0-9]+)$"),"\\2");
fileName.replace(QRegExp("^(.*)(\\.[a-z0-9]+)$"),"\\1");
}
+ //resolv the new name
+ int num=1;
do
{
- if(!fileName.startsWith(tr("Copy of ")))
- fileName=tr("Copy of ")+fileName;
- else
+ if(num==1)
{
- if(fileName.contains(QRegExp("_[0-9]+$")))
+ if(firstRenamingRule=="")
+ newFileName=tr("%1 - copy").arg(fileName);
+ else
{
- QString number=fileName;
- number.replace(QRegExp("^.*_([0-9]+)$"),"\\1");
- int num=number.toInt()+1;
- fileName.remove(QRegExp("[0-9]+$"));
- fileName+=QString::number(num);
+ newFileName=firstRenamingRule;
+ newFileName.replace("%name%",fileName);
}
+ }
+ else
+ {
+ if(otherRenamingRule=="")
+ newFileName=tr("%1 - copy (%2)").arg(fileName).arg(num);
else
- fileName+="_2";
+ {
+ newFileName=otherRenamingRule;
+ newFileName.replace("%name%",fileName);
+ newFileName.replace("%number%",QString::number(num));
+ }
}
- destination=absolutePath+QDir::separator()+fileName+suffix;
+ destination=absolutePath+QDir::separator()+newFileName+suffix;
destinationInfo.setFile(destination);
+ num++;
}
while(destinationInfo.exists());
return false;
@@ -328,7 +339,7 @@ bool TransferThread::destinationExists()
return false;
else
{
- stat=Idle;
+ transfer_stat=TransferStat_Idle;
emit postOperationStopped();
return true;
}
@@ -339,7 +350,7 @@ bool TransferThread::destinationExists()
return false;
else
{
- stat=Idle;
+ transfer_stat=TransferStat_Idle;
emit postOperationStopped();
return true;
}
@@ -423,7 +434,7 @@ void TransferThread::ifCanStartTransfer()
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] readIsReadyVariable: "+QString::number(readIsReadyVariable)+", writeIsReadyVariable: "+QString::number(writeIsReadyVariable));
if(readIsReadyVariable && writeIsReadyVariable)
{
- stat=WaitForTheTransfer;
+ transfer_stat=TransferStat_WaitForTheTransfer;
sended_state_readStopped = false;
sended_state_writeStopped = false;
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] stat=WaitForTheTransfer");
@@ -435,7 +446,7 @@ void TransferThread::ifCanStartTransfer()
if(canStartTransfer)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] stat=Transfer");
- stat=Transfer;
+ transfer_stat=TransferStat_Transfer;
if(!canBeMovedDirectlyVariable)
{
needRemove=true;
@@ -443,7 +454,7 @@ void TransferThread::ifCanStartTransfer()
}
else
tryMoveDirectly();
- emit pushStat(stat,transferId);
+ emit pushStat(transfer_stat,transferId);
}
//else
//emit pushStat(stat,transferId);
@@ -481,6 +492,7 @@ void TransferThread::setKeepDate(const bool keepDate)
void TransferThread::setMaxSpeed(int maxSpeed)
{
int interval=readThread.setMaxSpeed(maxSpeed);
+ writeThread.setMaxSpeed(maxSpeed);
if(maxSpeed>0)
{
clockForTheCopySpeed.setInterval(interval);
@@ -498,18 +510,22 @@ void TransferThread::setMaxSpeed(int maxSpeed)
bool TransferThread::setBlockSize(const unsigned int blockSize)
{
this->blockSize=blockSize;
- return readThread.setBlockSize(blockSize);
+ return readThread.setBlockSize(blockSize) && writeThread.setBlockSize(blockSize);
}
//pause the copy
void TransferThread::pause()
{
+ if(transfer_stat==TransferStat_Idle)
+ return;
readThread.pause();
}
//resume the copy
void TransferThread::resume()
{
+ if(transfer_stat==TransferStat_Idle)
+ return;
readThread.resume();
}
@@ -517,6 +533,8 @@ void TransferThread::resume()
void TransferThread::stop()
{
stopIt=true;
+ if(transfer_stat==TransferStat_Idle)
+ return;
readThread.stop();
writeThread.stop();
}
@@ -531,8 +549,82 @@ void TransferThread::readIsFinish()
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start");
readIsFinishVariable=true;
canStartTransfer=false;
- stat=PostTransfer;
- emit pushStat(stat,transferId);
+ //check here if need start checksuming or not
+ real_doChecksum=doChecksum && (!checksumOnlyOnError || fileContentError);
+ if(real_doChecksum)
+ {
+ readIsFinishVariable=false;
+ transfer_stat=TransferStat_Checksum;
+ sourceChecksum=QByteArray();
+ destinationChecksum=QByteArray();
+ readThread.startCheckSum();
+ }
+ else
+ {
+ transfer_stat=TransferStat_PostTransfer;
+ readThread.postOperation();
+ }
+ emit pushStat(transfer_stat,transferId);
+}
+
+void TransferThread::writeIsFinish()
+{
+ if(writeIsFinishVariable)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] double event dropped");
+ return;
+ }
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start");
+ writeIsFinishVariable=true;
+ //check here if need start checksuming or not
+ if(real_doChecksum)
+ {
+ writeIsFinishVariable=false;
+ transfer_stat=TransferStat_Checksum;
+ writeThread.startCheckSum();
+ }
+ else
+ writeThread.postOperation();
+}
+
+void TransferThread::readChecksumFinish(const QByteArray& checksum)
+{
+ sourceChecksum=checksum;
+ compareChecksum();
+}
+
+void TransferThread::writeChecksumFinish(const QByteArray& checksum)
+{
+ destinationChecksum=checksum;
+ compareChecksum();
+}
+
+void TransferThread::compareChecksum()
+{
+ if(sourceChecksum.size()==0)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] the checksum of source is missing");
+ return;
+ }
+ if(destinationChecksum.size()==0)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] the checksum of destination is missing");
+ return;
+ }
+ if(sourceChecksum==destinationChecksum)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] the checksum match");
+ readThread.postOperation();
+ writeThread.postOperation();
+ transfer_stat=TransferStat_PostTransfer;
+ emit pushStat(transfer_stat,transferId);
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] the checksum not match");
+ //emit error here, and wait to resume
+ emit errorOnFile(destinationInfo,tr("The checksums not match"));
+ }
}
void TransferThread::readIsClosed()
@@ -569,14 +661,19 @@ bool TransferThread::checkIfAllIsClosed()
if((!readIsReadyVariable || readIsClosedVariable) && (!writeIsReadyVariable || writeIsClosedVariable))
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] emit internalStartPostOperation() to do the real post operation");
- stat=PostOperation;
+ transfer_stat=TransferStat_PostOperation;
//emit pushStat(stat,transferId);
emit internalStartPostOperation();
return true;
}
else
{
- ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] wait self close");
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] "+QString("wait self close: readIsReadyVariable: %1, readIsClosedVariable: %2, writeIsReadyVariable: %3, writeIsClosedVariable: %4")
+ .arg(readIsReadyVariable)
+ .arg(readIsClosedVariable)
+ .arg(writeIsReadyVariable)
+ .arg(writeIsClosedVariable)
+ );
return false;
}
}
@@ -585,9 +682,9 @@ bool TransferThread::checkIfAllIsClosed()
/// \todo the rights copy
void TransferThread::postOperation()
{
- if(stat!=PostOperation)
+ if(transfer_stat!=TransferStat_PostOperation)
{
- ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] need be in transfer, source: "+source+", destination: "+destination+", stat:"+QString::number(stat));
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] need be in transfer, source: "+source+", destination: "+destination+", stat:"+QString::number(transfer_stat));
return;
}
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start");
@@ -633,7 +730,7 @@ void TransferThread::postOperation()
else
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] try remove destination but not exists!");
}
- stat=Idle;
+ transfer_stat=TransferStat_Idle;
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] emit postOperationStopped()");
emit postOperationStopped();
}
@@ -673,6 +770,7 @@ void TransferThread::getWriteError()
return;
}
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start");
+ fileContentError = true;
writeError = true;
writeIsReadyVariable = false;
writeError_source_seeked = false;
@@ -688,6 +786,7 @@ void TransferThread::getReadError()
return;
}
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start");
+ fileContentError = true;
readError = true;
writeIsReadyVariable = false;
readIsReadyVariable = false;
@@ -698,16 +797,16 @@ void TransferThread::getReadError()
void TransferThread::retryAfterError()
{
//opening error
- if(stat==PreOperation)
+ if(transfer_stat==TransferStat_PreOperation)
{
- ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] is not idle, source: "+source+", destination: "+destination+", stat: "+QString::number(stat));
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] is not idle, source: "+source+", destination: "+destination+", stat: "+QString::number(transfer_stat));
tryOpen();
return;
}
//data streaming error
- if(stat!=PostOperation && stat!=Transfer)
+ if(transfer_stat!=TransferStat_PostOperation && transfer_stat!=TransferStat_Transfer && transfer_stat!=TransferStat_Checksum)
{
- ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] is not idle, source: "+source+", destination: "+destination+", stat: "+QString::number(stat));
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Critical,"["+QString::number(id)+"] is not idle, source: "+source+", destination: "+destination+", stat: "+QString::number(transfer_stat));
return;
}
if(canBeMovedDirectlyVariable)
@@ -716,6 +815,26 @@ void TransferThread::retryAfterError()
tryMoveDirectly();
return;
}
+ if(transfer_stat==TransferStat_Checksum)
+ {
+ if(writeError)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start and resume the write error");
+ writeThread.reopen();
+ }
+ else if(readError)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start and resume the read error");
+ readThread.reopen();
+ }
+ else //only checksum difference
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] retry all the transfer");
+ canStartTransfer=true;
+ ifCanStartTransfer();
+ }
+ return;
+ }
if(writeError)
{
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start and resume the write error");
@@ -739,6 +858,11 @@ void TransferThread::writeThreadIsReopened()
return;
}
writeError_destination_reopened=true;
+ if(transfer_stat==TransferStat_Checksum)
+ {
+ writeThread.startCheckSum();
+ return;
+ }
if(writeError_source_seeked && writeError_destination_reopened)
resumeTransferAfterWriteError();
}
@@ -796,6 +920,7 @@ void TransferThread::readIsStopped()
}
else
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] drop dual read stopped");
+ readIsFinish();
}
void TransferThread::writeIsStopped()
@@ -809,6 +934,7 @@ void TransferThread::writeIsStopped()
}
else
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] double event dropped");
+ writeIsFinish();
}
void TransferThread::timeOfTheBlockCopyFinished()
@@ -840,32 +966,100 @@ bool TransferThread::changeFileDateTime(const QString &source,const QString &des
if(maxTime>=sourceInfo.lastModified())
return;
*/
- QFileInfo fileInfo(destination);
- time_t ctime=fileInfo.created().toTime_t();
- time_t actime=fileInfo.lastRead().toTime_t();
- time_t modtime=fileInfo.lastModified().toTime_t();
- #ifdef Q_CC_GNU
- //this function avalaible on unix and mingw
- utimbuf butime;
- butime.actime=actime;
- butime.modtime=modtime;
- //creation time not exists into unix world
- Q_UNUSED(ctime)
- return utime(source.toLatin1().data(),&butime)==0;
+ /** Why not do it with Qt? Because it not support setModificationTime(), and get the time with Qt, that's mean use local time where in C is UTC time */
+ #ifdef Q_OS_UNIX
+ #ifdef Q_OS_LINUX
+ struct stat info;
+ stat(source.toLatin1().data(),&info);
+ time_t ctime=info.st_ctim.tv_sec;
+ time_t actime=info.st_atim.tv_sec;
+ time_t modtime=info.st_mtim.tv_sec;
+ //this function avalaible on unix and mingw
+ utimbuf butime;
+ butime.actime=actime;
+ butime.modtime=modtime;
+ //creation time not exists into unix world
+ Q_UNUSED(ctime)
+ return utime(destination.toLatin1().data(),&butime)==0;
+ #else //mainly for mac
+ QFileInfo fileInfo(destination);
+ time_t ctime=fileInfo.created().toTime_t();
+ time_t actime=fileInfo.lastRead().toTime_t();
+ time_t modtime=fileInfo.lastModified().toTime_t();
+ //this function avalaible on unix and mingw
+ utimbuf butime;
+ butime.actime=actime;
+ butime.modtime=modtime;
+ //creation time not exists into unix world
+ Q_UNUSED(ctime)
+ return utime(destination.toLatin1().data(),&butime)==0;
+ #endif
#else
- return false;
+ #ifdef Q_OS_WIN32
+ #ifdef ULTRACOPIER_PLUGIN_SET_TIME_UNIX_WAY
+ struct __stat64 info;
+ _stat64(source.toLatin1().data(),&info);
+ time_t ctime=info.st_ctime;
+ time_t actime=info.st_atime;
+ time_t modtime=info.st_mtime;
+ //this function avalaible on unix and mingw
+ utimbuf butime;
+ butime.actime=actime;
+ butime.modtime=modtime;
+ //creation time not exists into unix world
+ Q_UNUSED(ctime)
+ return utime(destination.toLatin1().data(),&butime)==0;
+ #else
+ wchar_t filePath[65535];
+ source.toWCharArray(filePath);
+ HANDLE hFileSouce = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ destination.toWCharArray(filePath);
+ HANDLE hFileDestination = CreateFile(filePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if(hFileSouce == INVALID_HANDLE_VALUE)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] open failed to read");
+ return false;
+ }
+ if(hFileDestination == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hFileSouce);
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] open failed to write");
+ return false;
+ }
+ FILETIME ftCreate, ftAccess, ftWrite;
+ if(!GetFileTime(hFileSouce, &ftCreate, &ftAccess, &ftWrite))
+ {
+ CloseHandle(hFileSouce);
+ CloseHandle(hFileDestination);
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] unable to get the file time");
+ return false;
+ }
+ if(!SetFileTime(hFileDestination, &ftCreate, &ftAccess, &ftWrite))
+ {
+ CloseHandle(hFileSouce);
+ CloseHandle(hFileDestination);
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] unable to set the file time");
+ return false;
+ }
+ CloseHandle(hFileSouce);
+ CloseHandle(hFileDestination);
+ return true;
+ #endif
+ #else
+ return false;
+ #endif
#endif
- return true;
+ return false;
}
//skip the copy
void TransferThread::skip()
{
- ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start with stat: "+QString::number(stat));
- switch(stat)
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] start with stat: "+QString::number(transfer_stat));
+ switch(transfer_stat)
{
- case PreOperation:
- case WaitForTheTransfer:
+ case TransferStat_PreOperation:
+ case TransferStat_WaitForTheTransfer:
needSkip=true;
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] case WaitForTheTransfer or PreOperation, readIsReadyVariable: "+QString::number(readIsReadyVariable)+", readIsClosedVariable: "+QString::number(readIsClosedVariable)+", writeIsReadyVariable: "+QString::number(writeIsReadyVariable)+", writeIsClosedVariable: "+QString::number(writeIsClosedVariable));
//check if all is source and destination is closed
@@ -877,7 +1071,7 @@ void TransferThread::skip()
writeThread.stop();
}
break;
- case Transfer:
+ case TransferStat_Transfer:
needSkip=true;
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] case Transfer, readIsReadyVariable: "+QString::number(readIsReadyVariable)+", readIsClosedVariable: "+QString::number(readIsClosedVariable)+", writeIsReadyVariable: "+QString::number(writeIsReadyVariable)+", writeIsClosedVariable: "+QString::number(writeIsClosedVariable));
if(!checkIfAllIsClosed())
@@ -888,7 +1082,18 @@ void TransferThread::skip()
writeThread.stop();
}
break;
- case PostOperation:
+ case TransferStat_Checksum:
+ needSkip=true;
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"["+QString::number(id)+"] case Transfer, readIsReadyVariable: "+QString::number(readIsReadyVariable)+", readIsClosedVariable: "+QString::number(readIsClosedVariable)+", writeIsReadyVariable: "+QString::number(writeIsReadyVariable)+", writeIsClosedVariable: "+QString::number(writeIsClosedVariable));
+ if(!checkIfAllIsClosed())
+ {
+ if(readIsReadyVariable && !readIsClosedVariable)
+ readThread.stop();
+ if(writeIsReadyVariable && !writeIsClosedVariable)
+ writeThread.stop();
+ }
+ break;
+ case TransferStat_PostOperation:
//do nothing because here is closing...
ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Warning,"["+QString::number(id)+"] is already in post op");
break;
@@ -901,11 +1106,13 @@ void TransferThread::skip()
//return info about the copied size
qint64 TransferThread::copiedSize()
{
- switch(stat)
+ switch(transfer_stat)
{
- case Transfer:
- case PostOperation:
+ case TransferStat_Transfer:
+ case TransferStat_PostOperation:
return readThread.getLastGoodPosition();
+ case TransferStat_Checksum:
+ return transferSize;
default:
return 0;
}
@@ -917,6 +1124,11 @@ void TransferThread::putAtBottom()
emit tryPutAtBottom();
}
+void TransferThread::set_osBufferLimit(unsigned int osBufferLimit)
+{
+ this->osBufferLimit=osBufferLimit;
+}
+
#ifdef ULTRACOPIER_PLUGIN_DEBUG
//to set the id
void TransferThread::setId(int id)
@@ -942,6 +1154,9 @@ QChar TransferThread::readingLetter()
case ReadThread::WaitWritePipe:
return 'W';
break;
+ case ReadThread::Checksum:
+ return 'S';
+ break;
default:
return '?';
}
@@ -963,6 +1178,12 @@ QChar TransferThread::writingLetter()
case WriteThread::Close:
return 'C';
break;
+ case WriteThread::Read:
+ return 'R';
+ break;
+ case WriteThread::Checksum:
+ return 'S';
+ break;
default:
return '?';
}
@@ -975,3 +1196,50 @@ void TransferThread::setMkpathTransfer(QSemaphore *mkpathTransfer)
this->mkpathTransfer=mkpathTransfer;
writeThread.setMkpathTransfer(mkpathTransfer);
}
+
+void TransferThread::set_doChecksum(bool doChecksum)
+{
+ this->doChecksum=doChecksum;
+}
+
+void TransferThread::set_checksumIgnoreIfImpossible(bool checksumIgnoreIfImpossible)
+{
+ this->checksumIgnoreIfImpossible=checksumIgnoreIfImpossible;
+}
+
+void TransferThread::set_checksumOnlyOnError(bool checksumOnlyOnError)
+{
+ this->checksumOnlyOnError=checksumOnlyOnError;
+}
+
+void TransferThread::set_osBuffer(bool osBuffer)
+{
+ this->osBuffer=osBuffer;
+}
+
+void TransferThread::set_osBufferLimited(bool osBufferLimited)
+{
+ this->osBufferLimited=osBufferLimited;
+}
+
+//not copied size, because that's count to the checksum, ...
+quint64 TransferThread::realByteTransfered()
+{
+ switch(transfer_stat)
+ {
+ case TransferStat_Transfer:
+ case TransferStat_PostOperation:
+ case TransferStat_Checksum:
+ return readThread.getLastGoodPosition();
+ ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Warning,"["+QString::number(id)+"] transferSize: "+QString::number(transferSize));
+ return transferSize;
+ default:
+ return 0;
+ }
+}
+
+void TransferThread::setRenamingRules(QString firstRenamingRule,QString otherRenamingRule)
+{
+ this->firstRenamingRule=firstRenamingRule;
+ this->otherRenamingRule=otherRenamingRule;
+}