diff options
Diffstat (limited to 'plugins/CopyEngine/Ultracopier-Spec/ListThread.cpp')
-rwxr-xr-x | plugins/CopyEngine/Ultracopier-Spec/ListThread.cpp | 1235 |
1 files changed, 1235 insertions, 0 deletions
diff --git a/plugins/CopyEngine/Ultracopier-Spec/ListThread.cpp b/plugins/CopyEngine/Ultracopier-Spec/ListThread.cpp new file mode 100755 index 0000000..9c5e8f8 --- /dev/null +++ b/plugins/CopyEngine/Ultracopier-Spec/ListThread.cpp @@ -0,0 +1,1235 @@ +#include "ListThread.h" +#include <QStorageInfo> +#include <QtGlobal> +#include "../../../cpp11addition.h" + +#include "async/TransferThreadAsync.h" +#ifdef Q_OS_LINUX +#include <sys/sysinfo.h> +#endif +#ifdef Q_OS_WIN32 +#include <sysinfoapi.h> +#endif + +ListThread::ListThread(FacilityInterface * facilityInterface) : + numberOfInodeOperation(0), + sourceDriveMultiple(false), + destinationDriveMultiple(false), + destinationFolderMultiple(false), + stopIt(false), + numberOfTransferIntoToDoList(0), + bytesToTransfer(0), + bytesTransfered(0), + #ifdef ULTRACOPIER_PLUGIN_RSYNC + rsync(false), + #endif + idIncrementNumber(1), + actualRealByteTransfered(0), + checkDestinationFolderExists(false), + parallelizeIfSmallerThan(1024), + moveTheWholeFolder(false), + deletePartiallyTransferredFiles(true), + inodeThreads(1), + renameTheOriginalDestination(false), + checkDiskSpace(true), + buffer(false), + followTheStrictOrder(true), + mode(Ultracopier::CopyMode::Copy), + forcedMode(false), + actionToDoListTransfer_count(0), + actionToDoListInode_count(0), + doTransfer(false), + doInode(false), + oversize(0), + currentProgression(0), + copiedSize(0), + totalSize(0), + localOverSize(0), + doRightTransfer(false), + keepDate(false), + os_spec_flags(true), + native_copy(false), + mkFullPath(false), + alwaysDoThisActionForFileExists(FileExists_NotSet), + speedLimitation(0), + returnBoolToCopyEngine(true) +{ + moveToThread(this); + start(HighPriority); + this->facilityInterface=facilityInterface; + #ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT + clockForTheCopySpeed = NULL; + multiForBigSpeed = 0; + blockSize = 65536; + blockSizeAfterSpeedLimitation = blockSize; + #endif + putInPause = false; + autoStart=true; + + //can't be static into WriteThread, linked by instance then by ListThread + writeFileList=new QMultiHash<QString,WriteThread *>(); + writeFileListMutex=new QMutex(); + + #ifdef ULTRACOPIER_PLUGIN_DEBUG_WINDOW + if(!connect(&timerUpdateDebugDialog,&QTimer::timeout,this,&ListThread::timedUpdateDebugDialog)) + abort(); + timerUpdateDebugDialog.start(ULTRACOPIER_PLUGIN_DEBUG_WINDOW_TIMER); + #endif + if(!connect(this, &ListThread::tryCancel, this,&ListThread::cancel, Qt::QueuedConnection)) + abort(); + if(!connect(this, &ListThread::askNewTransferThread, this,&ListThread::createTransferThread, Qt::QueuedConnection)) + abort(); + if(!connect(&mkPathQueue, &MkPath::firstFolderFinish, this,&ListThread::mkPathFirstFolderFinish, Qt::QueuedConnection)) + abort(); + if(!connect(&mkPathQueue, &MkPath::errorOnFolder, this,&ListThread::mkPathErrorOnFolder, Qt::QueuedConnection)) + abort(); + if(!connect(this, &ListThread::send_syncTransferList, this,&ListThread::syncTransferList_internal, Qt::QueuedConnection)) + abort(); + if(!connect(this, &ListThread::exportTransferListSend, this,&ListThread::exportTransferListInternal, Qt::QueuedConnection)) + abort(); + if(!connect(this, &ListThread::importTransferListSend, this,&ListThread::importTransferListInternal, Qt::QueuedConnection)) + abort(); + #ifdef ULTRACOPIER_PLUGIN_DEBUG + if(!connect(&mkPathQueue, &MkPath::debugInformation, this,&ListThread::debugInformation, Qt::QueuedConnection)) + abort(); + if(!connect(&driveManagement,&DriveManagement::debugInformation, this,&ListThread::debugInformation, Qt::QueuedConnection)) + abort(); + #endif // ULTRACOPIER_PLUGIN_DEBUG + + emit askNewTransferThread(); + mkpathTransfer.release(); + + int64_t MBMem=100; + #ifdef Q_OS_WIN32 + MEMORYSTATUSEX memoryStatus; + if(GlobalMemoryStatusEx(&memoryStatus)) + MBMem=memoryStatus.ullTotalPhys/1024; + #endif + #ifdef Q_OS_LINUX + struct sysinfo info; + if(sysinfo(&info)==0) + MBMem=info.totalhigh*info.mem_unit/1024/1024; + #endif + if(MBMem<1024) + WriteThread::numberOfBlock=4+MBMem*0.12; + else + WriteThread::numberOfBlock=ULTRACOPIER_PLUGIN_DEFAULT_PARALLEL_NUMBER_OF_BLOCK; +} + +ListThread::~ListThread() +{ + emit tryCancel(); + waitCancel.acquire(); + quit(); + wait(); +} + +//transfer is finished +void ListThread::transferInodeIsClosed() +{ + if(stopIt) + { + checkIfReadyToCancel(); + return; + } + numberOfInodeOperation--; + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfInodeOperation: "+std::to_string(numberOfInodeOperation)); + #endif + TransferThreadAsync *temp_transfer_thread=qobject_cast<TransferThreadAsync *>(QObject::sender()); + if(temp_transfer_thread==NULL) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"transfer thread not located!"); + return; + } + if(overCheckUsedThread.find(temp_transfer_thread)==overCheckUsedThread.cend()) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"transfer thread not located in overcheck"); + else + overCheckUsedThread.erase(temp_transfer_thread); + if(putAtBottomAfterError.find(temp_transfer_thread)!=putAtBottomAfterError.cend()) + { + doNewActions_inode_manipulation(); + doNewActions_start_transfer(); + return; + } + bool isFound=false; + #ifdef ULTRACOPIER_PLUGIN_DEBUG + int countLocalParse=0; + #endif + if(temp_transfer_thread->getStat()!=TransferStat_Idle) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"transfer thread not idle!"); + return; + } + unsigned int int_for_internal_loop=0; + while(int_for_internal_loop<actionToDoListTransfer.size()) + { + if(actionToDoListTransfer.at(int_for_internal_loop).id==temp_transfer_thread->transferId) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("[%1] have finish, put at idle; for id: %2").arg(int_for_internal_loop).arg(temp_transfer_thread->transferId).toStdString()); + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type=Ultracopier::RemoveItem; + newAction.userAction.moveAt=0; + newAction.addAction=actionToDoTransferToItemOfCopyList(actionToDoListTransfer.at(int_for_internal_loop)); + newAction.userAction.position=int_for_internal_loop; + actionDone.push_back(newAction); + /// \todo check if item is at the right thread + const int64_t transferTime=temp_transfer_thread->transferTime(); + if(transferTime>=0 && temp_transfer_thread->haveStartTime) + { + timeToTransfer.push_back(std::pair<uint64_t,uint32_t>(temp_transfer_thread->transferSize,transferTime)); + temp_transfer_thread->haveStartTime=false; + } + actionToDoListTransfer.erase(actionToDoListTransfer.cbegin()+int_for_internal_loop); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("actionToDoListTransfer.size(): %1, actionToDoListInode: %2, actionToDoListInode_afterTheTransfer: %3").arg(actionToDoListTransfer.size()).arg(actionToDoListInode.size()).arg(actionToDoListInode_afterTheTransfer.size()).toStdString()); + if(actionToDoListTransfer.empty() && actionToDoListInode.empty() && actionToDoListInode_afterTheTransfer.empty()) + updateTheStatus(); + + //add the current size of file, to general size because it's finish + copiedSize=temp_transfer_thread->copiedSize(); + if(copiedSize>(qint64)temp_transfer_thread->transferSize) + { + oversize=copiedSize-temp_transfer_thread->transferSize; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"add oversize of: "+std::to_string(oversize)); + bytesToTransfer+=oversize; + bytesTransfered+=oversize; + } + bytesTransfered+=temp_transfer_thread->transferSize; + + temp_transfer_thread->transferId=0; + temp_transfer_thread->transferSize=0; + #ifdef ULTRACOPIER_PLUGIN_DEBUG + countLocalParse++; + #endif + isFound=true; + if(actionToDoListTransfer.empty()) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"actionToDoListTransfer==0"); + actionToDoListInode.insert(actionToDoListInode.cbegin(),actionToDoListInode_afterTheTransfer.cbegin(),actionToDoListInode_afterTheTransfer.cend()); + actionToDoListInode_afterTheTransfer.clear(); + doNewActions_inode_manipulation(); + doNewActions_start_transfer(); + } + break; + } + int_for_internal_loop++; + } + if(isFound) + deleteTransferThread(); + else + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,QStringLiteral("unable to found item into the todo list, id: %1, index: %2").arg(temp_transfer_thread->transferId).arg(int_for_internal_loop).toStdString()); + temp_transfer_thread->transferId=0; + temp_transfer_thread->transferSize=0; + } + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("countLocalParse: %1, actionToDoList.size(): %2").arg(countLocalParse).arg(actionToDoListTransfer.size()).toStdString()); + #ifdef ULTRACOPIER_PLUGIN_DEBUG + if(countLocalParse!=1) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"countLocalParse != 1"); + #endif + doNewActions_inode_manipulation(); + doNewActions_start_transfer(); +} + +/** \brief put the current file at bottom in case of error +\note ONLY IN CASE OF ERROR + +transferInodeIsClosed() will be call after, then will do: + +BUT + +this function call transfer->skip(); +not put at bottom, remove from to do list +*/ +void ListThread::transferPutAtBottom() +{ + TransferThreadAsync *transfer=qobject_cast<TransferThreadAsync *>(QObject::sender()); + if(transfer==NULL) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"transfer thread not located!"); + return; + } + bool isFound=false; + #ifdef ULTRACOPIER_PLUGIN_DEBUG + int countLocalParse=0; + #endif + unsigned int indexAction=0; + while(indexAction<actionToDoListTransfer.size()) + { + if(actionToDoListTransfer.at(indexAction).id==transfer->transferId) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"Put at the end: "+std::to_string(transfer->transferId)); + //push for interface at the end + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type=Ultracopier::MoveItem; + newAction.addAction.id=transfer->transferId; + newAction.userAction.position=0; + newAction.userAction.moveAt=actionToDoListTransfer.size()-1; + actionDone.push_back(newAction); + //do the wait stat + actionToDoListTransfer[indexAction].isRunning=false; + //move at the end + actionToDoListTransfer.push_back(actionToDoListTransfer.at(indexAction)); + actionToDoListTransfer.erase(actionToDoListTransfer.cbegin()+indexAction); + transfer->transferId=0; + transfer->transferSize=0; + #ifdef ULTRACOPIER_PLUGIN_DEBUG + countLocalParse++; + #endif + isFound=true; + putAtBottomAfterError.insert(transfer); + break; + } + indexAction++; + } + if(!isFound) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,QStringLiteral("unable to found item into the todo list, id: %1, index: %2").arg(transfer->transferId).toStdString()); + transfer->transferId=0; + transfer->transferSize=0; + putAtBottomAfterError.insert(transfer); + } + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"countLocalParse: "+std::to_string(countLocalParse)); + #ifdef ULTRACOPIER_PLUGIN_DEBUG + if(countLocalParse!=1) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"countLocalParse != 1"); + #endif + transfer->skip(); +} + +void ListThread::fileTransfer(const INTERNALTYPEPATH &sourceFileInfo,const INTERNALTYPEPATH &destinationFileInfo,const Ultracopier::CopyMode &mode) +{ + if(stopIt) + return; + addToTransfer(sourceFileInfo,destinationFileInfo,mode); +} + +void ListThread::fileTransferWithInode(const INTERNALTYPEPATH &sourceFileInfo,const INTERNALTYPEPATH &destinationFileInfo, + const Ultracopier::CopyMode &mode,const TransferThread::dirent_uc &inode) +{ + if(stopIt) + return; + #ifdef Q_OS_WIN32 + addToTransfer(sourceFileInfo,destinationFileInfo,mode,inode.size); + #else + (void)inode; + addToTransfer(sourceFileInfo,destinationFileInfo,mode); + #endif +} + +void ListThread::autoStartAndCheckSpace() +{ + if(needMoreSpace()) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"Need more space"); + return; + } + autoStartIfNeeded(); +} + +void ListThread::autoStartIfNeeded() +{ + if(autoStart) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"Auto start the copy"); + startGeneralTransfer(); + } + else + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"Put the copy engine in pause"); + putInPause=true; + emit isInPause(true); + } +} + +//set auto start +void ListThread::setAutoStart(const bool autoStart) +{ + this->autoStart=autoStart; +} + +void ListThread::startGeneralTransfer() +{ + doNewActions_inode_manipulation(); +} + +/** \brief to sync the transfer list + * Used when the interface is changed, useful to minimize the memory size */ +void ListThread::syncTransferList() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + emit send_syncTransferList(); +} + +bool ListThread::getReturnBoolToCopyEngine() const +{ + return returnBoolToCopyEngine; +} + +std::pair<quint64, quint64> ListThread::getReturnPairQuint64ToCopyEngine() const +{ + return returnPairQuint64ToCopyEngine; +} + +Ultracopier::ItemOfCopyList ListThread::getReturnItemOfCopyListToCopyEngine() const +{ + return returnItemOfCopyListToCopyEngine; +} + +void ListThread::realByteTransfered() +{ + quint64 totalRealByteTransfered=0; + int index=0; + int loop_sub_size_transfer_thread_search=transferThreadList.size(); + while(index<loop_sub_size_transfer_thread_search) + { + const TransferThreadAsync * thread=transferThreadList.at(index); + totalRealByteTransfered+=thread->realByteTransfered(); + index++; + } + emit send_realBytesTransfered(totalRealByteTransfered); +} + +void ListThread::checkIfReadyToCancel() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + if(!stopIt) + return; + int index=0; + int loop_size=transferThreadList.size(); + while(index<loop_size) + { + if(transferThreadList.at(index)!=NULL) + { + if(transferThreadList.at(index)->transferId!=0) + return; + //need wait a clean stop (and then destination remove) + if(transferThreadList.at(index)->getStat()!=TransferStat_Idle) + return; + delete transferThreadList.at(index);//->deleteLayer(); + transferThreadList[index]=NULL; + transferThreadList.erase(transferThreadList.cbegin()+index); + loop_size=transferThreadList.size(); + index--; + } + index++; + } + actionToDoListTransfer.clear(); + actionToDoListInode.clear(); + actionToDoListInode_afterTheTransfer.clear(); + actionDone.clear(); + progressionList.clear(); + returnListItemOfCopyListToCopyEngine.clear(); + quit(); + waitCancel.release(); + emit canBeDeleted(); +} + +void ListThread::updateTheStatus() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + sendActionDone(); + bool updateTheStatus_listing=scanFileOrFolderThreadsPool.size()>0; + bool updateTheStatus_copying=actionToDoListTransfer.size()>0 || actionToDoListInode.size()>0 || actionToDoListInode_afterTheTransfer.size()>0; + Ultracopier::EngineActionInProgress updateTheStatus_action_in_progress; + if(updateTheStatus_copying && updateTheStatus_listing) + updateTheStatus_action_in_progress=Ultracopier::CopyingAndListing; + else if(updateTheStatus_listing) + updateTheStatus_action_in_progress=Ultracopier::Listing; + else if(updateTheStatus_copying) + updateTheStatus_action_in_progress=Ultracopier::Copying; + else + updateTheStatus_action_in_progress=Ultracopier::Idle; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"emit actionInProgess("+std::to_string(updateTheStatus_action_in_progress)+")"); + emit actionInProgess(updateTheStatus_action_in_progress); +} + +//mk path to do +uint64_t ListThread::addToMkPath(const INTERNALTYPEPATH& source,const INTERNALTYPEPATH& destination, const int& inode) +{ + if(stopIt) + return 0; + if(inode!=0 && (!keepDate && !doRightTransfer)) + return 0; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"source: "+TransferThread::internalStringTostring(source)+ + ", destination: "+TransferThread::internalStringTostring(destination)); + ActionToDoInode temp; + temp.type = ActionType_MkPath; + temp.id = generateIdNumber(); + temp.source = source; + temp.destination= destination; + temp.isRunning = false; + actionToDoListInode.push_back(temp); + return temp.id; +} + +//add path to do +void ListThread::addToMovePath(const INTERNALTYPEPATH &source, const INTERNALTYPEPATH &destination, const int& inodeToRemove) +{ + if(stopIt) + return; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"source: "+TransferThread::internalStringTostring(source)+ + ", destination: "+TransferThread::internalStringTostring(destination)+", inodeToRemove: "+std::to_string(inodeToRemove)); + ActionToDoInode temp; + temp.type = ActionType_MovePath; + temp.id = generateIdNumber(); + temp.size = inodeToRemove; + temp.source = source; + temp.destination= destination; + temp.isRunning = false; + actionToDoListInode.push_back(temp); +} + +void ListThread::addToKeepAttributePath(const INTERNALTYPEPATH &source, const INTERNALTYPEPATH &destination, const int& inodeToRemove) +{ + if(stopIt) + return; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"source: "+TransferThread::internalStringTostring(source)+ + ", destination: "+TransferThread::internalStringTostring(destination)+", inodeToRemove: "+std::to_string(inodeToRemove)); + ActionToDoInode temp; + temp.type = ActionType_SyncDate; + temp.id = generateIdNumber(); + temp.size = inodeToRemove; + temp.source = source; + temp.destination= destination; + temp.isRunning = false; + actionToDoListInode.push_back(temp); +} + +void ListThread::addToRealMove(const INTERNALTYPEPATH& source,const INTERNALTYPEPATH& destination) +{ + if(stopIt) + return; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"source: "+TransferThread::internalStringTostring(source)+ + ", destination: "+TransferThread::internalStringTostring(destination)); + ActionToDoInode temp; + temp.type = ActionType_RealMove; + temp.id = generateIdNumber(); + temp.size = 0; + temp.source = source; + temp.destination= destination; + temp.isRunning = false; + actionToDoListInode.push_back(temp); +} + +#ifdef ULTRACOPIER_PLUGIN_RSYNC +//rsync rm +void ListThread::addToRmForRsync(const std::string& destination) +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"inode: "+destination); + ActionToDoInode temp; + temp.type = ActionType_RmSync; + temp.id = generateIdNumber(); + temp.destination= destination; + temp.isRunning = false; + actionToDoListInode.push_back(temp); +} +#endif + +//send the progression, after full reset of the interface (then all is empty) +void ListThread::syncTransferList_internal() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + emit syncReady(); + actionDone.clear(); + //do list operation + TransferThreadAsync *transferThread; + const int &loop_size=actionToDoListTransfer.size(); + int loop_sub_size=transferThreadList.size(); + //this loop to have at max inodeThreads*inodeThreads, not inodeThreads*transferThreadList.size() + int int_for_internal_loop; + for(int int_for_loop=0; int_for_loop<loop_size; ++int_for_loop) { + const ActionToDoTransfer &item=actionToDoListTransfer.at(int_for_loop); + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type = Ultracopier::PreOperation; + newAction.addAction.id = item.id; + const size_t sourceIndex=item.source.rfind('/'); + if(sourceIndex == std::string::npos) + { + newAction.addAction.sourceFullPath = '/'; + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(item.source); + } + else + { + newAction.addAction.sourceFullPath = TransferThread::internalStringTostring(item.source); + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(item.source.substr(sourceIndex+1)); + } + const size_t destinationIndex=item.destination.rfind('/'); + if(destinationIndex == std::string::npos) + { + newAction.addAction.destinationFullPath = '/'; + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(item.destination); + } + else + { + newAction.addAction.destinationFullPath = TransferThread::internalStringTostring(item.destination); + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(item.destination.substr(destinationIndex+1)); + } + newAction.addAction.size = item.size; + newAction.addAction.mode = item.mode; + actionDone.push_back(newAction); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"id: "+std::to_string(item.id)+", size: "+std::to_string(item.size)+ + ", name: "+TransferThread::internalStringTostring(item.source)+", size2: "+std::to_string(newAction.addAction.size)); + if(item.isRunning) + { + for(int_for_internal_loop=0; int_for_internal_loop<loop_sub_size; ++int_for_internal_loop) { + transferThread=transferThreadList.at(int_for_internal_loop); + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type = Ultracopier::PreOperation; + newAction.addAction.id = item.id; + const size_t sourceIndex=item.source.rfind('/'); + if(sourceIndex == std::string::npos) + { + newAction.addAction.sourceFullPath = TransferThread::internalStringTostring(item.source); + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(item.source); + } + else + { + newAction.addAction.sourceFullPath = TransferThread::internalStringTostring(item.source); + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(item.source.substr(sourceIndex+1)); + } + const size_t destinationIndex=item.destination.rfind('/'); + if(destinationIndex == std::string::npos) + { + newAction.addAction.destinationFullPath = TransferThread::internalStringTostring(item.destination); + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(item.destination); + } + else + { + newAction.addAction.destinationFullPath = TransferThread::internalStringTostring(item.destination); + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(item.destination.substr(destinationIndex+1)); + } + newAction.addAction.size = item.size; + newAction.addAction.mode = item.mode; + actionDone.push_back(newAction); + if(transferThread->getStat()!=TransferStat_PreOperation) + { + Ultracopier::ReturnActionOnCopyList newAction; + switch(transferThread->getStat()) + { + case TransferStat_Transfer: + newAction.type=Ultracopier::Transfer; + break; + /*case TransferStat_PostTransfer: + newAction.type=Ultracopier::PostOperation; + break;*/ + case TransferStat_PostOperation: + newAction.type=Ultracopier::PostOperation; + break; + default: + break; + } + newAction.addAction.id = item.id; + actionDone.push_back(newAction); + } + } + } + } +} + +//add file transfer to do +uint64_t ListThread::addToTransfer(const INTERNALTYPEPATH &source, const INTERNALTYPEPATH &destination, const Ultracopier::CopyMode& mode, const int64_t sendedsize) +{ + if(stopIt) + return 0; + //add to transfer list + numberOfTransferIntoToDoList++; + uint64_t size=0; + if(sendedsize>=0) + size=sendedsize; + else + { + const int64_t tempSize=TransferThread::file_stat_size(source); + if(tempSize>=0) + size=tempSize; + } + const std::string &drive=driveManagement.getDrive(TransferThread::internalStringTostring(destination)); + if(!drive.empty())//can be a network drive + if(mode!=Ultracopier::Move || drive!=driveManagement.getDrive(TransferThread::internalStringTostring(source))) + { + if(requiredSpace.find(drive)!=requiredSpace.cend()) + { + requiredSpace[drive]+=size; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("space needed add: %1, space needed: %2, on: %3").arg(size).arg(requiredSpace.at(drive)).arg(QString::fromStdString(drive)).toStdString()); + } + else + { + requiredSpace[drive]=size; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("set space %1 needed, on: %2").arg(size).arg(QString::fromStdString(drive)).toStdString()); + } + } + bytesToTransfer+= size; + ActionToDoTransfer temp; + temp.id = generateIdNumber(); + temp.size = size; + temp.source = source; + temp.destination= destination; + temp.mode = mode; + temp.isRunning = false; + actionToDoListTransfer.push_back(temp); + //push the new transfer to interface + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type = Ultracopier::AddingItem; + newAction.addAction=actionToDoTransferToItemOfCopyList(temp); + actionDone.push_back(newAction); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"source: "+TransferThread::internalStringTostring(source)+ + ", destination: "+TransferThread::internalStringTostring(destination)+", add entry: "+std::to_string(temp.id)+", size: "+ + std::to_string(temp.size)+", size2: "+std::to_string(size)+", isSymLink: "+std::to_string(TransferThread::is_symlink(source))); + return temp.id; +} + +Ultracopier::ItemOfCopyList ListThread::actionToDoTransferToItemOfCopyList(const ListThread::ActionToDoTransfer &actionToDoTransfer) +{ + Ultracopier::ItemOfCopyList itemOfCopyList; + itemOfCopyList.id = actionToDoTransfer.id; + const size_t sourceIndex=actionToDoTransfer.source.rfind('/'); + if(sourceIndex == std::string::npos) + { + itemOfCopyList.sourceFullPath = TransferThread::internalStringTostring(actionToDoTransfer.source); + itemOfCopyList.sourceFileName = TransferThread::internalStringTostring(actionToDoTransfer.source); + } + else + { + itemOfCopyList.sourceFullPath = TransferThread::internalStringTostring(actionToDoTransfer.source); + itemOfCopyList.sourceFileName = TransferThread::internalStringTostring(actionToDoTransfer.source.substr(sourceIndex+1)); + } + const size_t destinationIndex=actionToDoTransfer.destination.rfind('/'); + if(destinationIndex == std::string::npos) + { + itemOfCopyList.destinationFullPath = TransferThread::internalStringTostring(actionToDoTransfer.destination); + itemOfCopyList.destinationFileName = TransferThread::internalStringTostring(actionToDoTransfer.destination); + } + else + { + itemOfCopyList.destinationFullPath = TransferThread::internalStringTostring(actionToDoTransfer.destination); + itemOfCopyList.destinationFileName = TransferThread::internalStringTostring(actionToDoTransfer.destination.substr(destinationIndex+1)); + } + itemOfCopyList.size = actionToDoTransfer.size; + itemOfCopyList.mode = actionToDoTransfer.mode; + return itemOfCopyList; +} + +//generate id number +uint64_t ListThread::generateIdNumber() +{ + idIncrementNumber++; + if(idIncrementNumber>(((quint64)1024*1024)*1024*1024*2)) + idIncrementNumber=0; + return idIncrementNumber; +} + +//do new actions +void ListThread::doNewActions_start_transfer() +{ + /*ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("actionToDoListTransfer.size(): %1, numberOfTranferRuning: %2") + .arg(actionToDoListTransfer.size()).arg(getNumberOfTranferRuning()).toStdString());*/ + if(stopIt || putInPause) + return; + int numberOfTranferRuning=getNumberOfTranferRuning(); + const int &loop_size=transferThreadList.size(); + //lunch the transfer in WaitForTheTransfer + //high priority + int int_for_loop=0; + while(int_for_loop<loop_size) + { + TransferThreadAsync *transferThread=transferThreadList.at(int_for_loop); + if(transferThread->getStat()==TransferStat_WaitForTheTransfer/*ready to start the transfer*/ && transferThread->transferId!=0) + { + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + if(transferThread->transferSize>=parallelizeIfSmallerThan) + { + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + if(numberOfTranferRuning<ULTRACOPIER_PLUGIN_MAXPARALLELTRANFER) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + transferThread->startTheTransfer(); + numberOfTranferRuning++; + } + } + else + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)+ + ", start in parallele beacuase size is "+std::to_string(transferThread->transferSize)); + transferThread->startTheTransfer(); + numberOfTranferRuning++; + } + } + int_for_loop++; + } + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + + //low priority + int_for_loop=0; + while(int_for_loop<loop_size) + { + TransferThreadAsync *transferThread=transferThreadList.at(int_for_loop); + if(transferThread->getStat()==TransferStat_PreOperation/*wait user dialog action*/) + { + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + if(transferThread->transferSize>=parallelizeIfSmallerThan) + { + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + if(numberOfTranferRuning<ULTRACOPIER_PLUGIN_MAXPARALLELTRANFER) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + transferThread->startTheTransfer(); + numberOfTranferRuning++; + } + } + else + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); + transferThread->startTheTransfer(); + numberOfTranferRuning++; + } + } + int_for_loop++; + } + //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfTranferRuning: "+std::to_string(numberOfTranferRuning)); +} + +/** \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 ListThread::doNewActions_inode_manipulation() +{ + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"actionToDoList.size(): "+std::to_string(actionToDoListTransfer.size())); + #endif + if(stopIt) + checkIfReadyToCancel(); + if(stopIt || putInPause) + return; + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + #endif + //lunch the pre-op or inode op + TransferThreadAsync *currentTransferThread; + int int_for_loop=0; + int int_for_internal_loop=0; + int int_for_transfer_thread_search=0; + actionToDoListTransfer_count=actionToDoListTransfer.size(); + actionToDoListInode_count=actionToDoListInode.size(); + int loop_sub_size_transfer_thread_search=transferThreadList.size(); + //search the next transfer action to do + while(int_for_loop<actionToDoListTransfer_count) + { + ActionToDoTransfer& currentActionToDoTransfer=actionToDoListTransfer[int_for_loop]; + if(!currentActionToDoTransfer.isRunning) + { + //search the next inode action to do + while(int_for_internal_loop<actionToDoListInode_count) + { + if(!actionToDoListInode.at(int_for_internal_loop).isRunning) + { + if(currentActionToDoTransfer.id<actionToDoListInode.at(int_for_internal_loop).id) + { + //do the tranfer action in the next code + break; + } + else + { + //do the inode action + #include "ListThread_InodeAction.cpp" + } + } + int_for_internal_loop++; + } + //do the tranfer action + while(int_for_transfer_thread_search<loop_sub_size_transfer_thread_search) + { + /** + transferThreadList.at(int_for_transfer_thread_search)->transferId==0) /!\ important! + Because the other thread can have call doNewAction before than this thread have the finish event parsed! + I this case it lose all data + */ + currentTransferThread=transferThreadList.at(int_for_transfer_thread_search); + if(currentTransferThread->getStat()==TransferStat_Idle && currentTransferThread->transferId==0 && + overCheckUsedThread.find(currentTransferThread)==overCheckUsedThread.cend()) // /!\ important! + { + overCheckUsedThread.insert(currentTransferThread); + + std::string drive=driveManagement.getDrive(TransferThread::internalStringTostring(currentActionToDoTransfer.destination)); + if(requiredSpace.find(drive)!=requiredSpace.cend() && + (currentActionToDoTransfer.mode!=Ultracopier::Move || + drive!=driveManagement.getDrive(TransferThread::internalStringTostring(currentActionToDoTransfer.source)))) + { + requiredSpace[drive]-=currentActionToDoTransfer.size; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("space needed removed: %1, space needed: %2, on: %3").arg( + currentActionToDoTransfer.size).arg(requiredSpace.at(drive)).arg(QString::fromStdString(drive)).toStdString()); + } + currentTransferThread->transferId=currentActionToDoTransfer.id; + currentTransferThread->transferSize=currentActionToDoTransfer.size; + putAtBottomAfterError.erase(currentTransferThread); + if(!currentTransferThread->setFiles( + currentActionToDoTransfer.source, + currentActionToDoTransfer.size, + currentActionToDoTransfer.destination, + currentActionToDoTransfer.mode + )) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(int_for_loop)+"] id: "+ + std::to_string(currentTransferThread->transferId)+ + " is idle, but seam busy at set name: "+TransferThread::internalStringTostring(currentActionToDoTransfer.destination) + ); + break; + } + currentActionToDoTransfer.isRunning=true; + + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(int_for_loop)+"] id: "+ + std::to_string(currentTransferThread->transferId)+ + " is idle, use it for "+TransferThread::internalStringTostring(currentActionToDoTransfer.destination) + ); + + /// \note wrong position? Else write why it's here + Ultracopier::ReturnActionOnCopyList newAction; + newAction.type = Ultracopier::PreOperation; + newAction.addAction.id = currentActionToDoTransfer.id; + const size_t sourceIndex=currentActionToDoTransfer.source.rfind('/'); + if(sourceIndex == std::string::npos) + { + newAction.addAction.sourceFullPath = '/'; + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(currentActionToDoTransfer.source); + } + else + { + newAction.addAction.sourceFullPath = TransferThread::internalStringTostring(currentActionToDoTransfer.source); + newAction.addAction.sourceFileName = TransferThread::internalStringTostring(currentActionToDoTransfer.source.substr(sourceIndex+1)); + } + const size_t destinationIndex=currentActionToDoTransfer.destination.rfind('/'); + if(destinationIndex == std::string::npos) + { + newAction.addAction.destinationFullPath = '/'; + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(currentActionToDoTransfer.destination); + } + else + { + newAction.addAction.destinationFullPath = TransferThread::internalStringTostring(currentActionToDoTransfer.destination); + newAction.addAction.destinationFileName = TransferThread::internalStringTostring(currentActionToDoTransfer.destination.substr(destinationIndex+1)); + } + newAction.addAction.size = currentActionToDoTransfer.size; + newAction.addAction.mode = currentActionToDoTransfer.mode; + actionDone.push_back(newAction); + int_for_transfer_thread_search++; + numberOfInodeOperation++; + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfInodeOperation: "+std::to_string(numberOfInodeOperation)); + #endif + break; + } + int_for_transfer_thread_search++; + } + if(int_for_internal_loop==loop_sub_size_transfer_thread_search) + { + /// \note Can be normal when all thread is not initialized + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"unable to found free thread to do the transfer"); + #endif + break; + } + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfInodeOperation: "+std::to_string(numberOfInodeOperation)); + #endif + if(numberOfInodeOperation>=inodeThreads) + break; + if(followTheStrictOrder) + break; + } + int_for_loop++; + } + //search the next inode action to do + int_for_internal_loop=0; + while(int_for_internal_loop<actionToDoListInode_count) + { + if(!actionToDoListInode.at(int_for_internal_loop).isRunning) + { + //do the inode action + #include "ListThread_InodeAction.cpp" + } + int_for_internal_loop++; + } + //error checking + if(actionToDoListInode_count>inodeThreads) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,QStringLiteral("The index have been detected as out of max range: %1>%2").arg(actionToDoListInode_count).arg(inodeThreads).toStdString()); + return; + } +} + +//restart transfer if it can +void ListThread::restartTransferIfItCan() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + TransferThreadAsync *transfer=qobject_cast<TransferThreadAsync *>(QObject::sender()); + if(transfer==NULL) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"transfer thread not located!"); + return; + } + int numberOfTranferRuning=getNumberOfTranferRuning(); + if(numberOfTranferRuning<ULTRACOPIER_PLUGIN_MAXPARALLELTRANFER && transfer->getStat()==TransferStat_WaitForTheTransfer) + transfer->startTheTransfer(); + doNewActions_start_transfer(); +} + + +void ListThread::set_setFilters(const std::vector<Filters_rules> &include,const std::vector<Filters_rules> &exclude) +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("include.size(): %1, exclude.size(): %2").arg(include.size()).arg(exclude.size()).toStdString()); + this->include=include; + this->exclude=exclude; + unsigned int index=0; + while(index<scanFileOrFolderThreadsPool.size()) + { + scanFileOrFolderThreadsPool.at(index)->setFilters(include,exclude); + index++; + } +} + +void ListThread::set_sendNewRenamingRules(const std::string &firstRenamingRule,const std::string &otherRenamingRule) +{ + this->firstRenamingRule=firstRenamingRule; + this->otherRenamingRule=otherRenamingRule; + emit send_sendNewRenamingRules(firstRenamingRule,otherRenamingRule); +} + +void ListThread::set_updateMount() +{ + driveManagement.tryUpdate(); + emit send_updateMount(); +} + +void ListThread::mkPathFirstFolderFinish() +{ + int int_for_loop=0; + const int &loop_size=actionToDoListInode.size(); + while(int_for_loop<loop_size) + { + const ActionToDoInode &actionToDoInode=actionToDoListInode.at(int_for_loop); + if(actionToDoInode.isRunning) + { + if(actionToDoInode.type==ActionType_MkPath || actionToDoInode.type==ActionType_SyncDate) + { + //to send to the log + emit mkPath(TransferThread::internalStringTostring(actionToDoInode.destination)); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"stop mkpath: "+TransferThread::internalStringTostring(actionToDoInode.destination)); + actionToDoListInode.erase(actionToDoListInode.cbegin()+int_for_loop); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("actionToDoListTransfer.size(): %1, actionToDoListInode: %2, actionToDoListInode_afterTheTransfer: %3").arg(actionToDoListTransfer.size()).arg(actionToDoListInode.size()).arg(actionToDoListInode_afterTheTransfer.size()).toStdString()); + if(actionToDoListTransfer.empty() && actionToDoListInode.empty() && actionToDoListInode_afterTheTransfer.empty()) + updateTheStatus(); + numberOfInodeOperation--; + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfInodeOperation: "+std::to_string(numberOfInodeOperation)); + #endif + doNewActions_inode_manipulation(); + return; + } + if(actionToDoInode.type==ActionType_MovePath || actionToDoInode.type==ActionType_RealMove + #ifdef ULTRACOPIER_PLUGIN_RSYNC + || actionToDoInode.type==ActionType_RmSync + #endif + ) + { + //to send to the log + #ifdef ULTRACOPIER_PLUGIN_RSYNC + if(actionToDoInode.type!=ActionType_RmSync) + emit mkPath(actionToDoInode.destination); + #else + emit mkPath(TransferThread::internalStringTostring(actionToDoInode.destination)); + #endif + emit rmPath(TransferThread::internalStringTostring(actionToDoInode.source)); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"stop mkpath: "+TransferThread::internalStringTostring(actionToDoInode.destination)); + actionToDoListInode.erase(actionToDoListInode.cbegin()+int_for_loop); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("actionToDoListTransfer.size(): %1, actionToDoListInode: %2, actionToDoListInode_afterTheTransfer: %3").arg(actionToDoListTransfer.size()).arg(actionToDoListInode.size()).arg(actionToDoListInode_afterTheTransfer.size()).toStdString()); + if(actionToDoListTransfer.empty() && actionToDoListInode.empty() && actionToDoListInode_afterTheTransfer.empty()) + updateTheStatus(); + numberOfInodeOperation--; + #ifdef ULTRACOPIER_PLUGIN_DEBUG_SCHEDULER + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"numberOfInodeOperation: "+std::to_string(numberOfInodeOperation)); + #endif + doNewActions_inode_manipulation(); + return; + } + + } + int_for_loop++; + } + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"unable to found item into the todo list"); +} + +/// \note Can be call without queue because all call will be serialized +void ListThread::fileAlreadyExists(const INTERNALTYPEPATH &source,const INTERNALTYPEPATH &destination,const bool &isSame) +{ + emit send_fileAlreadyExists(source,destination,isSame,qobject_cast<TransferThreadAsync *>(sender())); +} + +/// \note Can be call without queue because all call will be serialized +void ListThread::errorOnFile(const INTERNALTYPEPATH &fileInfo, const std::string &errorString, const ErrorType &errorType) +{ + TransferThreadAsync * transferThread=qobject_cast<TransferThreadAsync *>(sender()); + if(transferThread==NULL) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"Thread locating error"); + return; + } + ErrorLogEntry errorLogEntry; + errorLogEntry.source=TransferThread::internalStringTostring(transferThread->getSourcePath()); + errorLogEntry.destination=TransferThread::internalStringTostring(transferThread->getDestinationPath()); + errorLogEntry.mode=transferThread->getMode(); + errorLogEntry.error=errorString; + errorLog.push_back(errorLogEntry); + emit errorToRetry(TransferThread::internalStringTostring(transferThread->getSourcePath()), + TransferThread::internalStringTostring(transferThread->getDestinationPath()), + errorString); + emit send_errorOnFile(fileInfo,errorString,transferThread,errorType); +} + +/// \note Can be call without queue because all call will be serialized +void ListThread::folderAlreadyExists(const INTERNALTYPEPATH &source,const INTERNALTYPEPATH &destination,const bool &isSame) +{ + emit send_folderAlreadyExists(source,destination,isSame,qobject_cast<ScanFileOrFolder *>(sender())); +} + +/// \note Can be call without queue because all call will be serialized +/// \todo all this part +void ListThread::errorOnFolder(const INTERNALTYPEPATH &fileInfo,const std::string &errorString,const ErrorType &errorType) +{ + emit send_errorOnFolder(fileInfo,errorString,qobject_cast<ScanFileOrFolder *>(sender()),errorType); +} + +//to run the thread +void ListThread::run() +{ + #ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT + clockForTheCopySpeed=new QTimer(); + #endif + exec(); +} + +void ListThread::getNeedPutAtBottom(const INTERNALTYPEPATH &fileInfo, const std::string &errorString, TransferThreadAsync *thread, + const ErrorType &errorType) +{ + (void)fileInfo; + (void)errorString; + (void)errorType; + thread->putAtBottom(); +} + +/// \to create transfer thread +void ListThread::createTransferThread() +{ + if(stopIt) + return; + if(transferThreadList.size()>=(unsigned int)inodeThreads) + return; + transferThreadList.push_back(new TransferThreadAsync()); + TransferThreadAsync * last=transferThreadList.back(); + last->transferId=0; + last->transferSize=0; + last->setRightTransfer(doRightTransfer); + last->setKeepDate(keepDate); + last->setOsSpecFlags(os_spec_flags); + last->setNativeCopy(native_copy); + last->setAlwaysFileExistsAction(alwaysDoThisActionForFileExists); + #ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT + if(!last->setBlockSize(blockSizeAfterSpeedLimitation)) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"unable to set the block size: "+std::to_string(blockSizeAfterSpeedLimitation)); + #endif + last->setDeletePartiallyTransferredFiles(deletePartiallyTransferredFiles); + last->setBuffer(buffer); + #ifdef ULTRACOPIER_PLUGIN_RSYNC + last->setRsync(rsync); + #endif + + last->writeThread.writeFileList=new QMultiHash<QString,WriteThread *>(); + last->writeThread.writeFileListMutex=new QMutex(); + + #ifdef ULTRACOPIER_PLUGIN_DEBUG + if(!connect(last,&TransferThread::debugInformation, this,&ListThread::debugInformation, Qt::QueuedConnection)) + abort(); + #endif // ULTRACOPIER_PLUGIN_DEBUG + if(!connect(last,&TransferThread::errorOnFile, this,&ListThread::errorOnFile, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::fileAlreadyExists, this,&ListThread::fileAlreadyExists, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::tryPutAtBottom, this,&ListThread::transferPutAtBottom, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::readStopped, this,&ListThread::doNewActions_start_transfer, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::preOperationStopped, this,&ListThread::doNewActions_start_transfer, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::postOperationStopped, this,&ListThread::transferInodeIsClosed, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::checkIfItCanBeResumed, this,&ListThread::restartTransferIfItCan, Qt::QueuedConnection)) + abort(); + if(!connect(last,&TransferThread::pushStat, this,&ListThread::newTransferStat, Qt::QueuedConnection)) + abort(); + + if(!connect(this,&ListThread::send_sendNewRenamingRules, last,&TransferThread::setRenamingRules, Qt::QueuedConnection)) + abort(); + + if(!connect(this,&ListThread::send_updateMount, last,&TransferThread::set_updateMount, Qt::QueuedConnection)) + abort(); + #ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT + last->setMultiForBigSpeed(multiForBigSpeed); + //speed limitation + connect(clockForTheCopySpeed, &QTimer::timeout, last, &TransferThreadAsync::timeOfTheBlockCopyFinished, Qt::QueuedConnection); + #endif + + last->setObjectName(QStringLiteral("transfer %1").arg(transferThreadList.size()-1)); + last->readThread.setObjectName(QStringLiteral("read %1").arg(transferThreadList.size()-1)); + last->writeThread.setObjectName(QStringLiteral("write %1").arg(transferThreadList.size()-1)); + last->setRenamingRules(firstRenamingRule,otherRenamingRule); + #ifdef ULTRACOPIER_PLUGIN_DEBUG + last->setId(transferThreadList.size()-1); + #endif + if(transferThreadList.size()>=(unsigned int)inodeThreads) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"create the last of the "+std::to_string(inodeThreads)+" transferThread"); + return; + } + if(stopIt) + return; + doNewActions_inode_manipulation(); + emit askNewTransferThread(); +} + +void ListThread::deleteTransferThread() +{ + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); + int loop_size=transferThreadList.size(); + if(loop_size>inodeThreads) + { + int index=0; + while(index<loop_size && loop_size>inodeThreads) + { + if(transferThreadList.at(index)->getStat()==TransferStat_Idle && transferThreadList.at(index)->transferId==0) + { + transferThreadList.at(index)->stop(); + delete transferThreadList.at(index);//->deleteLayer(); + transferThreadList[index]=NULL; + transferThreadList.erase(transferThreadList.cbegin()+index); + loop_size--; + } + else + index++; + } + if(loop_size==inodeThreads) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"inodeThreads is lowered to the right value: "+std::to_string(inodeThreads)); + } +} + +void ListThread::setMkFullPath(const bool mkFullPath) +{ + this->mkFullPath=mkFullPath; + mkPathQueue.setMkFullPath(mkFullPath); + unsigned int index=0; + while(index<transferThreadList.size()) + { + transferThreadList.at(index)->setMkFullPath(mkFullPath); + index++; + } +} |