123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020 |
- //---------------------------------------------------------------------------
- #include <vcl.h>
- #pragma hdrstop
- #include "Common.h"
- #include "FileOperationProgress.h"
- #include "CoreMain.h"
- //---------------------------------------------------------------------------
- #define TRANSFER_BUF_SIZE 32768
- //---------------------------------------------------------------------------
- TFileOperationStatistics::TFileOperationStatistics()
- {
- memset(this, 0, sizeof(*this));
- }
- //---------------------------------------------------------------------------
- //---------------------------------------------------------------------------
- TFileOperationProgressType::TPersistence::TPersistence()
- {
- FStatistics = NULL;
- Clear(true, true);
- }
- //---------------------------------------------------------------------------
- bool TFileOperationProgressType::IsIndeterminateOperation(TFileOperation Operation)
- {
- return (Operation == foCalculateSize);
- }
- //---------------------------------------------------------------------------
- bool TFileOperationProgressType::IsTransferOperation(TFileOperation Operation)
- {
- return (Operation == foCopy) || (Operation == foMove);
- }
- //---------------------------------------------------------------------------
- void TFileOperationProgressType::TPersistence::Clear(bool Batch, bool Speed)
- {
- if (Batch)
- {
- TotalTransferred = 0;
- StartTime = Now();
- SkipToAll = false;
- BatchOverwrite = boNo;
- CPSLimit = 0;
- CounterSet = false;
- }
- if (Speed)
- {
- Ticks.clear();
- TotalTransferredThen.clear();
- }
- }
- //---------------------------------------------------------------------------
- __fastcall TFileOperationProgressType::TFileOperationProgressType()
- {
- FOnProgress = NULL;
- FOnFinished = NULL;
- FParent = NULL;
- Init();
- Clear();
- }
- //---------------------------------------------------------------------------
- __fastcall TFileOperationProgressType::TFileOperationProgressType(
- TFileOperationProgressEvent AOnProgress, TFileOperationFinished AOnFinished,
- TFileOperationProgressType * Parent)
- {
- FOnProgress = AOnProgress;
- FOnFinished = AOnFinished;
- FParent = Parent;
- FReset = false;
- Init();
- Clear();
- }
- //---------------------------------------------------------------------------
- __fastcall TFileOperationProgressType::~TFileOperationProgressType()
- {
- DebugAssert(!InProgress || FReset);
- DebugAssert(!Suspended || FReset);
- SAFE_DESTROY(FSection);
- SAFE_DESTROY(FUserSelectionsSection);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Init()
- {
- FSection = new TCriticalSection();
- FUserSelectionsSection = new TCriticalSection();
- FRestored = false;
- FPersistence.Side = osCurrent; // = undefined value
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Assign(const TFileOperationProgressType & Other)
- {
- TValueRestorer<TCriticalSection *> SectionRestorer(FSection);
- TValueRestorer<TCriticalSection *> UserSelectionsSectionRestorer(FUserSelectionsSection);
- TGuard Guard(FSection);
- TGuard OtherGuard(Other.FSection);
- *this = Other;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AssignButKeepSuspendState(const TFileOperationProgressType & Other)
- {
- TGuard Guard(FSection);
- TValueRestorer<unsigned int> SuspendTimeRestorer(FSuspendTime);
- TValueRestorer<bool> SuspendedRestorer(FSuspended);
- Assign(Other);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::DoClear(bool Batch, bool Speed)
- {
- FFileName = L"";
- FFullFileName = L"";
- FDirectory = L"";
- FAsciiTransfer = false;
- FCount = -1;
- FFilesFinished = 0;
- FFilesFinishedSuccessfully = 0;
- FSuspended = false;
- FSuspendTime = 0;
- FInProgress = false;
- FDone = false;
- FFileInProgress = false;
- FTotalSkipped = 0;
- FTotalSize = 0;
- FSkippedSize = 0;
- FTotalSizeSet = false;
- FOperation = foNone;
- FTemp = false;
- FPersistence.Clear(Batch, Speed);
- // to bypass check in ClearTransfer()
- FTransferSize = 0;
- ClearTransfer();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Clear()
- {
- DoClear(true, true);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::ClearTransfer()
- {
- if ((TransferSize > 0) && (TransferredSize < TransferSize))
- {
- TGuard Guard(FSection);
- __int64 RemainingSize = (TransferSize - TransferredSize);
- AddSkipped(RemainingSize);
- }
- FLocalSize = 0;
- FTransferSize = 0;
- FLocallyUsed = 0;
- FSkippedSize = 0;
- FTransferredSize = 0;
- FTransferringFile = false;
- FLastSecond = 0;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Start(TFileOperation AOperation,
- TOperationSide ASide, int ACount)
- {
- Start(AOperation, ASide, ACount, false, L"", 0, odoIdle);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Start(TFileOperation AOperation,
- TOperationSide ASide, int ACount, bool ATemp,
- const UnicodeString ADirectory, unsigned long ACPSLimit, TOnceDoneOperation InitialOnceDoneOperation)
- {
- {
- TGuard Guard(FSection); // not really needed, just for consistency
- DoClear(!FRestored, (FPersistence.Side != osCurrent) && (FPersistence.Side != ASide));
- FTotalTransferBase = FPersistence.TotalTransferred;
- FOperation = AOperation;
- FPersistence.Side = ASide;
- FCount = ACount;
- FInProgress = true;
- FCancel = csContinue;
- FDirectory = ADirectory;
- FTemp = ATemp;
- FInitialOnceDoneOperation = InitialOnceDoneOperation;
- FPersistence.CPSLimit = ACPSLimit;
- }
- try
- {
- DoProgress();
- }
- catch (...)
- {
- // connection can be lost during progress callbacks
- ClearTransfer();
- FInProgress = false;
- throw;
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Reset()
- {
- FReset = true;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Stop()
- {
- // added to include remaining bytes to TotalSkipped, in case
- // the progress happens to update before closing
- ClearTransfer();
- FInProgress = false;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetDone()
- {
- FDone = true;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Suspend()
- {
- {
- TGuard Guard(FSection);
- DebugAssert(!Suspended);
- FSuspended = true;
- FSuspendTime = GetTickCount();
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Resume()
- {
- {
- TGuard Guard(FSection);
- DebugAssert(Suspended);
- FSuspended = false;
- // shift timestamps for CPS calculation in advance
- // by the time the progress was suspended
- unsigned long Stopped = (GetTickCount() - FSuspendTime);
- size_t i = 0;
- while (i < FPersistence.Ticks.size())
- {
- FPersistence.Ticks[i] += Stopped;
- ++i;
- }
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- int __fastcall TFileOperationProgressType::OperationProgress() const
- {
- int Result;
- if (FCount > 0)
- {
- Result = (FFilesFinished * 100)/FCount;
- }
- else
- {
- Result = 0;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- int __fastcall TFileOperationProgressType::TransferProgress()
- {
- int Result;
- if (TransferSize)
- {
- Result = (int)((TransferredSize * 100)/TransferSize);
- }
- else
- {
- Result = 0;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- int __fastcall TFileOperationProgressType::TotalTransferProgress() const
- {
- TGuard Guard(FSection);
- DebugAssert(TotalSizeSet);
- int Result;
- if (FTotalSize > 0)
- {
- Result = (int)(((FPersistence.TotalTransferred - FTotalTransferBase + FTotalSkipped) * 100)/FTotalSize);
- }
- else
- {
- Result = 0;
- }
- return Result < 100 ? Result : 100;
- }
- //---------------------------------------------------------------------------
- int __fastcall TFileOperationProgressType::OverallProgress() const
- {
- if (TotalSizeSet)
- {
- DebugAssert(IsTransfer());
- return TotalTransferProgress();
- }
- else
- {
- return OperationProgress();
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Progress()
- {
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::DoProgress()
- {
- SetThreadExecutionState(ES_SYSTEM_REQUIRED);
- FOnProgress(*this);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Finish(UnicodeString FileName,
- bool Success, TOnceDoneOperation & OnceDoneOperation)
- {
- DebugAssert(InProgress);
- // Cancel reader is guarded
- FOnFinished(Operation, Side, Temp, FileName,
- Success && (Cancel == csContinue), OnceDoneOperation);
- FFilesFinished++;
- if (Success)
- {
- FFilesFinishedSuccessfully++;
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Succeeded(int Count)
- {
- if (FPersistence.Statistics != NULL)
- {
- if (IsTransfer())
- {
- __int64 Transferred = FTransferredSize - FSkippedSize;
- if (Side == osLocal)
- {
- FPersistence.Statistics->FilesUploaded += Count;
- FPersistence.Statistics->TotalUploaded += Transferred;
- }
- else
- {
- FPersistence.Statistics->FilesDownloaded += Count;
- FPersistence.Statistics->TotalDownloaded += Transferred;
- }
- }
- else if (Operation == foDelete)
- {
- if (Side == osLocal)
- {
- FPersistence.Statistics->FilesDeletedLocal += Count;
- }
- else
- {
- FPersistence.Statistics->FilesDeletedRemote += Count;
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetFile(UnicodeString AFileName, bool AFileInProgress)
- {
- FFullFileName = AFileName;
- if (Side == osRemote)
- {
- // historically set were passing filename-only for remote site operations,
- // now we need to collect a full paths, so we pass in full path,
- // but still want to have filename-only in FileName
- AFileName = UnixExtractFileName(AFileName);
- }
- FFileName = AFileName;
- FFileInProgress = AFileInProgress;
- ClearTransfer();
- FFileStartTime = Now();
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetFileInProgress()
- {
- DebugAssert(!FileInProgress);
- FFileInProgress = true;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetLocalSize(__int64 ASize)
- {
- FLocalSize = ASize;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddLocallyUsed(__int64 ASize)
- {
- FLocallyUsed += ASize;
- if (LocallyUsed > LocalSize)
- {
- FLocalSize = LocallyUsed;
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- bool __fastcall TFileOperationProgressType::IsLocallyDone()
- {
- DebugAssert(LocallyUsed <= LocalSize);
- return (LocallyUsed == LocalSize);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetSpeedCounters()
- {
- if ((CPSLimit > 0) && !FPersistence.CounterSet)
- {
- FPersistence.CounterSet = true;
- Configuration->Usage->Inc(L"SpeedLimitUses");
- }
- }
- //---------------------------------------------------------------------------
- // Used in WebDAV and S3 protocols
- void __fastcall TFileOperationProgressType::ThrottleToCPSLimit(
- unsigned long Size)
- {
- unsigned long Remaining = Size;
- while (Remaining > 0)
- {
- Remaining -= AdjustToCPSLimit(Remaining);
- }
- }
- //---------------------------------------------------------------------------
- unsigned long __fastcall TFileOperationProgressType::AdjustToCPSLimit(
- unsigned long Size)
- {
- SetSpeedCounters();
- // CPSLimit reader is guarded, we cannot block whole method as it can last long.
- if (CPSLimit > 0)
- {
- // we must not return 0, hence, if we reach zero,
- // we wait until the next second
- do
- {
- unsigned int Second = (GetTickCount() / MSecsPerSec);
- if (Second != FLastSecond)
- {
- FRemainingCPS = CPSLimit;
- FLastSecond = Second;
- }
- if (FRemainingCPS == 0)
- {
- SleepEx(100, true);
- DoProgress();
- }
- }
- while ((CPSLimit > 0) && (FRemainingCPS == 0));
- // CPSLimit may have been dropped in DoProgress
- if (CPSLimit > 0)
- {
- if (FRemainingCPS < Size)
- {
- Size = FRemainingCPS;
- }
- FRemainingCPS -= Size;
- }
- }
- return Size;
- }
- //---------------------------------------------------------------------------
- // Use in SCP protocol only
- unsigned long __fastcall TFileOperationProgressType::LocalBlockSize()
- {
- unsigned long Result = TRANSFER_BUF_SIZE;
- if (LocallyUsed + Result > LocalSize)
- {
- Result = (unsigned long)(LocalSize - LocallyUsed);
- }
- Result = AdjustToCPSLimit(Result);
- return Result;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetTotalSize(__int64 ASize)
- {
- TGuard Guard(FSection); // not really needed, just for consistency
- FTotalSize = ASize;
- FTotalSizeSet = true;
- // parent has its own totals
- if (FParent != NULL)
- {
- DebugAssert(FParent->TotalSizeSet);
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetTransferSize(__int64 ASize)
- {
- FTransferSize = ASize;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetTransferringFile(bool ATransferringFile)
- {
- FTransferringFile = ATransferringFile;
- }
- //---------------------------------------------------------------------------
- bool __fastcall TFileOperationProgressType::PassCancelToParent(TCancelStatus ACancel)
- {
- bool Result;
- if (ACancel < csCancel)
- {
- // do not propagate csCancelFile,
- // though it's not supported for queue atm, so we do not expect it here
- DebugFail();
- Result = false;
- }
- else if (ACancel == csCancel)
- {
- Result = true;
- }
- else
- {
- // csCancelTransfer and csRemoteAbort are used with SCP only, which does not use parallel transfers
- DebugFail();
- Result = false;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetCancel(TCancelStatus ACancel)
- {
- TGuard Guard(FSection);
- FCancel = ACancel;
- if ((FParent != NULL) && PassCancelToParent(ACancel))
- {
- FParent->SetCancel(ACancel);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetCancelAtLeast(TCancelStatus ACancel)
- {
- TGuard Guard(FSection);
- if (FCancel < ACancel)
- {
- FCancel = ACancel;
- }
- if ((FParent != NULL) && PassCancelToParent(ACancel))
- {
- FParent->SetCancelAtLeast(ACancel);
- }
- }
- //---------------------------------------------------------------------------
- TCancelStatus __fastcall TFileOperationProgressType::GetCancel()
- {
- TCancelStatus Result = FCancel;
- if (FParent != NULL)
- {
- TGuard Guard(FSection);
- TCancelStatus ParentCancel = FParent->Cancel;
- if (ParentCancel > Result)
- {
- Result = ParentCancel;
- }
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- bool __fastcall TFileOperationProgressType::ClearCancelFile()
- {
- TGuard Guard(FSection);
- // Not propagated to parent, as this is local flag, see also PassCancelToParent
- bool Result = (Cancel == csCancelFile);
- if (Result)
- {
- FCancel = csContinue;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- unsigned long __fastcall TFileOperationProgressType::GetCPSLimit()
- {
- unsigned int Result;
- if (FParent != NULL)
- {
- Result = FParent->CPSLimit;
- }
- else
- {
- TGuard Guard(FSection);
- Result = FPersistence.CPSLimit;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetCPSLimit(unsigned long ACPSLimit)
- {
- if (FParent != NULL)
- {
- FParent->SetCPSLimit(ACPSLimit);
- }
- else
- {
- TGuard Guard(FSection);
- FPersistence.CPSLimit = ACPSLimit;
- }
- }
- //---------------------------------------------------------------------------
- TBatchOverwrite __fastcall TFileOperationProgressType::GetBatchOverwrite()
- {
- TBatchOverwrite Result;
- if (FParent != NULL)
- {
- Result = FParent->BatchOverwrite;
- }
- else
- {
- TGuard Guard(FSection); // not really needed
- Result = FPersistence.BatchOverwrite;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetBatchOverwrite(TBatchOverwrite ABatchOverwrite)
- {
- if (FParent != NULL)
- {
- FParent->SetBatchOverwrite(ABatchOverwrite);
- }
- else
- {
- TGuard Guard(FSection); // not really needed
- FPersistence.BatchOverwrite = ABatchOverwrite;;
- }
- }
- //---------------------------------------------------------------------------
- bool __fastcall TFileOperationProgressType::GetSkipToAll()
- {
- bool Result;
- if (FParent != NULL)
- {
- Result = FParent->SkipToAll;
- }
- else
- {
- TGuard Guard(FSection); // not really needed
- Result = FPersistence.SkipToAll;
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetSkipToAll()
- {
- if (FParent != NULL)
- {
- FParent->SetSkipToAll();
- }
- else
- {
- TGuard Guard(FSection); // not really needed
- FPersistence.SkipToAll = true;
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::ChangeTransferSize(__int64 ASize)
- {
- // reflect change on file size (due to text transfer mode conversion particulary)
- // on total transfer size
- if (TotalSizeSet)
- {
- AddTotalSize(ASize - TransferSize);
- }
- FTransferSize = ASize;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::RollbackTransferFromTotals(__int64 ATransferredSize, __int64 ASkippedSize)
- {
- TGuard Guard(FSection);
- DebugAssert(ATransferredSize <= FPersistence.TotalTransferred - FTotalTransferBase);
- DebugAssert(ASkippedSize <= FTotalSkipped);
- FPersistence.TotalTransferred -= ATransferredSize;
- FPersistence.Ticks.clear();
- FPersistence.TotalTransferredThen.clear();
- FTotalSkipped -= ASkippedSize;
- if (FParent != NULL)
- {
- FParent->RollbackTransferFromTotals(ATransferredSize, ASkippedSize);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::RollbackTransfer()
- {
- FTransferredSize -= FSkippedSize;
- RollbackTransferFromTotals(FTransferredSize, FSkippedSize);
- FSkippedSize = 0;
- FTransferredSize = 0;
- FTransferSize = 0;
- FLocallyUsed = 0;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddTransferredToTotals(__int64 ASize)
- {
- TGuard Guard(FSection);
- FPersistence.TotalTransferred += ASize;
- if (ASize >= 0)
- {
- unsigned long Ticks = GetTickCount();
- if (FPersistence.Ticks.empty() ||
- (FPersistence.Ticks.back() > Ticks) || // ticks wrap after 49.7 days
- ((Ticks - FPersistence.Ticks.back()) >= MSecsPerSec))
- {
- FPersistence.Ticks.push_back(Ticks);
- FPersistence.TotalTransferredThen.push_back(FPersistence.TotalTransferred);
- }
- if (FPersistence.Ticks.size() > 10)
- {
- FPersistence.Ticks.erase(FPersistence.Ticks.begin());
- FPersistence.TotalTransferredThen.erase(FPersistence.TotalTransferredThen.begin());
- }
- }
- else
- {
- FPersistence.Ticks.clear();
- }
- if (FParent != NULL)
- {
- FParent->AddTransferredToTotals(ASize);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddTotalSize(__int64 ASize)
- {
- if (ASize != 0)
- {
- TGuard Guard(FSection);
- FTotalSize += ASize;
- if (FParent != NULL)
- {
- FParent->AddTotalSize(ASize);
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddTransferred(__int64 ASize,
- bool AddToTotals)
- {
- FTransferredSize += ASize;
- if (TransferredSize > TransferSize)
- {
- // this can happen with SFTP when downloading file that
- // grows while being downloaded
- if (TotalSizeSet)
- {
- // we should probably guard this with AddToTotals
- AddTotalSize(TransferredSize - TransferSize);
- }
- FTransferSize = TransferredSize;
- }
- if (AddToTotals)
- {
- AddTransferredToTotals(ASize);
- }
- DoProgress();
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddSkipped(__int64 ASize)
- {
- TGuard Guard(FSection);
- FTotalSkipped += ASize;
- if (FParent != NULL)
- {
- FParent->AddSkipped(ASize);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddResumed(__int64 ASize)
- {
- AddSkipped(ASize);
- FSkippedSize += ASize;
- AddTransferred(ASize, false);
- AddLocallyUsed(ASize);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::AddSkippedFileSize(__int64 ASize)
- {
- AddSkipped(ASize);
- DoProgress();
- }
- //---------------------------------------------------------------------------
- // Use in SCP protocol only
- unsigned long __fastcall TFileOperationProgressType::TransferBlockSize()
- {
- unsigned long Result = TRANSFER_BUF_SIZE;
- if (TransferredSize + Result > TransferSize)
- {
- Result = (unsigned long)(TransferSize - TransferredSize);
- }
- Result = AdjustToCPSLimit(Result);
- return Result;
- }
- //---------------------------------------------------------------------------
- unsigned long __fastcall TFileOperationProgressType::StaticBlockSize()
- {
- return TRANSFER_BUF_SIZE;
- }
- //---------------------------------------------------------------------------
- bool TFileOperationProgressType::IsTransferDoneChecked()
- {
- DebugAssert(TransferredSize <= TransferSize);
- return IsTransferDone();
- }
- //---------------------------------------------------------------------------
- // Note that this does not work correctly, if the file is larger than expected (at least with the FTP protocol)
- bool TFileOperationProgressType::IsTransferDone()
- {
- return (TransferredSize == TransferSize);
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::SetAsciiTransfer(bool AAsciiTransfer)
- {
- FAsciiTransfer = AAsciiTransfer;
- DoProgress();
- }
- //---------------------------------------------------------------------------
- TDateTime __fastcall TFileOperationProgressType::TimeElapsed()
- {
- return Now() - StartTime;
- }
- //---------------------------------------------------------------------------
- unsigned int __fastcall TFileOperationProgressType::CPS()
- {
- TGuard Guard(FSection);
- return GetCPS();
- }
- //---------------------------------------------------------------------------
- inline static unsigned int CalculateCPS(__int64 Transferred, unsigned int MSecElapsed)
- {
- unsigned int Result;
- if (MSecElapsed == 0)
- {
- Result = 0;
- }
- else
- {
- Result = (unsigned int)(Transferred * MSecsPerSec / MSecElapsed);
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- // Has to be called from a guarded method
- unsigned int __fastcall TFileOperationProgressType::GetCPS()
- {
- unsigned int Result;
- if (FPersistence.Ticks.empty())
- {
- Result = 0;
- }
- else
- {
- unsigned long Ticks = (Suspended ? FSuspendTime : GetTickCount());
- unsigned long TimeSpan;
- if (Ticks < FPersistence.Ticks.front())
- {
- // clocks has wrapped, guess 10 seconds difference
- TimeSpan = 10000;
- }
- else
- {
- TimeSpan = (Ticks - FPersistence.Ticks.front());
- }
- __int64 Transferred = (FPersistence.TotalTransferred - FPersistence.TotalTransferredThen.front());
- Result = CalculateCPS(Transferred, TimeSpan);
- }
- return Result;
- }
- //---------------------------------------------------------------------------
- TDateTime __fastcall TFileOperationProgressType::TimeExpected()
- {
- unsigned int CurCps = CPS();
- if (CurCps)
- {
- return TDateTime((double)(((double)(TransferSize - TransferredSize)) / CurCps) / SecsPerDay);
- }
- else
- {
- return 0;
- }
- }
- //---------------------------------------------------------------------------
- TDateTime __fastcall TFileOperationProgressType::TotalTimeLeft()
- {
- TGuard Guard(FSection);
- DebugAssert(FTotalSizeSet);
- unsigned int CurCps = GetCPS();
- // sanity check
- __int64 Processed = FTotalSkipped + FPersistence.TotalTransferred - FTotalTransferBase;
- if ((CurCps > 0) && (FTotalSize > Processed))
- {
- return TDateTime((double)((double)(FTotalSize - Processed) / CurCps) / SecsPerDay);
- }
- else
- {
- return 0;
- }
- }
- //---------------------------------------------------------------------------
- __int64 __fastcall TFileOperationProgressType::GetTotalTransferred()
- {
- TGuard Guard(FSection);
- return FPersistence.TotalTransferred;
- }
- //---------------------------------------------------------------------------
- __int64 __fastcall TFileOperationProgressType::GetOperationTransferred() const
- {
- TGuard Guard(FSection);
- return FPersistence.TotalTransferred - FTotalTransferBase + FTotalSkipped;
- }
- //---------------------------------------------------------------------------
- __int64 __fastcall TFileOperationProgressType::GetTotalSize()
- {
- TGuard Guard(FSection);
- return FTotalSize;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::LockUserSelections()
- {
- if (FParent != NULL)
- {
- FParent->LockUserSelections();
- }
- else
- {
- FUserSelectionsSection->Enter();
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::UnlockUserSelections()
- {
- if (FParent != NULL)
- {
- FParent->UnlockUserSelections();
- }
- else
- {
- FUserSelectionsSection->Leave();
- }
- }
- //---------------------------------------------------------------------------
- UnicodeString __fastcall TFileOperationProgressType::GetLogStr(bool Done)
- {
- UnicodeString Transferred = FormatSize(TotalTransferred);
- TDateTime Time;
- UnicodeString TimeLabel;
- if (!Done && TotalSizeSet)
- {
- Time = TotalTimeLeft();
- TimeLabel = L"Left";
- }
- else
- {
- Time = TimeElapsed();
- TimeLabel = L"Elapsed";
- }
- UnicodeString TimeStr = FormatDateTimeSpan(Configuration->TimeFormat, Time);
- unsigned int ACPS;
- if (!Done)
- {
- ACPS = CPS();
- }
- else
- {
- unsigned int Elapsed = TimeToMSec(TimeElapsed());
- ACPS = CalculateCPS(TotalTransferred, Elapsed);
- }
- UnicodeString CPSStr = FormatSize(ACPS);
- return FORMAT(L"Transferred: %s, %s: %s, CPS: %s/s", (Transferred, TimeLabel, TimeStr, CPSStr));
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Store(TPersistence & Persistence)
- {
- // in this current use, we do not need this to be guarded actually, as it's used only for a single-threaded synchronization
- TGuard Guard(FSection);
- Persistence = FPersistence;
- }
- //---------------------------------------------------------------------------
- void __fastcall TFileOperationProgressType::Restore(TPersistence & Persistence)
- {
- TGuard Guard(FSection);
- FPersistence = Persistence;
- FRestored = true;
- }
- //---------------------------------------------------------------------------
- bool TFileOperationProgressType::IsIndeterminate() const
- {
- return
- IsIndeterminateOperation(FOperation) ||
- (!TotalSizeSet && (FCount == 1));
- }
- //---------------------------------------------------------------------------
- bool TFileOperationProgressType::IsTransfer() const
- {
- return IsTransferOperation(Operation);
- }
|