diff options
Diffstat (limited to 'plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp')
-rw-r--r-- | plugins/CopyEngine/Ultracopier-0.3/TransferThread.cpp | 422 |
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; +} |