Browse Source

Ongoing local delete operation can be moved to a background queue (only on a remote tab, as local tabs do not have a queue)

Primarily to allow Issue 2318

Source commit: 6145552c9ea62fcf0b13f5d414c9a0b38fbf2f41
Martin Prikryl 11 months ago
parent
commit
fb3489c2ec
4 changed files with 128 additions and 61 deletions
  1. 37 10
      source/core/Queue.cpp
  2. 16 4
      source/core/Queue.h
  3. 1 0
      source/core/Terminal.cpp
  4. 74 47
      source/forms/CustomScpExplorer.cpp

+ 37 - 10
source/core/Queue.cpp

@@ -1786,6 +1786,11 @@ TQueueItem * __fastcall TQueueItem::CreateParallelOperation()
   return NULL;
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TQueueItem::StartupDirectory() const
+{
+  return EmptyStr;
+}
+//---------------------------------------------------------------------------
 // TQueueItemProxy
 //---------------------------------------------------------------------------
 __fastcall TQueueItemProxy::TQueueItemProxy(TTerminalQueue * Queue,
@@ -2093,11 +2098,6 @@ void __fastcall TBootstrapQueueItem::DoExecute(TTerminal * DebugUsedArg(Terminal
   // noop
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TBootstrapQueueItem::StartupDirectory() const
-{
-  return UnicodeString();
-}
-//---------------------------------------------------------------------------
 bool __fastcall TBootstrapQueueItem::Complete()
 {
   TQueueItem::Complete();
@@ -2274,6 +2274,13 @@ bool __fastcall TTransferQueueItem::UpdateFileList(TQueueFileList * FileList)
 //---------------------------------------------------------------------------
 // TUploadQueueItem
 //---------------------------------------------------------------------------
+static void ExtractLocalSourcePath(TStrings * Files, UnicodeString & Path)
+{
+  ExtractCommonPath(Files, Path);
+  // this way the trailing backslash is preserved for root directories like D:\\
+  Path = ExtractFileDir(IncludeTrailingBackslash(Path));
+}
+//---------------------------------------------------------------------------
 __fastcall TUploadQueueItem::TUploadQueueItem(TTerminal * Terminal,
   TStrings * FilesToCopy, const UnicodeString & TargetDir,
   const TCopyParamType * CopyParam, int Params, bool SingleFile, bool Parallel) :
@@ -2288,9 +2295,7 @@ __fastcall TUploadQueueItem::TUploadQueueItem(TTerminal * Terminal,
     }
     else
     {
-      ExtractCommonPath(FilesToCopy, FInfo->Source);
-      // this way the trailing backslash is preserved for root directories like D:\\
-      FInfo->Source = ExtractFileDir(IncludeTrailingBackslash(FInfo->Source));
+      ExtractLocalSourcePath(FilesToCopy, FInfo->Source);
       FInfo->ModifiedLocal = FLAGCLEAR(Params, cpDelete) ? UnicodeString() :
         IncludeTrailingBackslash(FInfo->Source);
     }
@@ -2434,7 +2439,7 @@ void __fastcall TDownloadQueueItem::DoTransferExecute(TTerminal * Terminal, TPar
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-TDeleteQueueItem::TDeleteQueueItem(TTerminal * Terminal, TStrings * FilesToDelete, int Params) :
+TRemoteDeleteQueueItem::TRemoteDeleteQueueItem(TTerminal * Terminal, TStrings * FilesToDelete, int Params) :
   TLocatedQueueItem(Terminal)
 {
   FInfo->Operation = foDelete;
@@ -2449,7 +2454,7 @@ TDeleteQueueItem::TDeleteQueueItem(TTerminal * Terminal, TStrings * FilesToDelet
   FParams = Params;
 }
 //---------------------------------------------------------------------------
-void __fastcall TDeleteQueueItem::DoExecute(TTerminal * Terminal)
+void __fastcall TRemoteDeleteQueueItem::DoExecute(TTerminal * Terminal)
 {
   TLocatedQueueItem::DoExecute(Terminal);
 
@@ -2457,6 +2462,28 @@ void __fastcall TDeleteQueueItem::DoExecute(TTerminal * Terminal)
   Terminal->DeleteFiles(FFilesToDelete.get(), FParams);
 }
 //---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+TLocalDeleteQueueItem::TLocalDeleteQueueItem(TStrings * FilesToDelete, int Params) :
+  TQueueItem()
+{
+  FInfo->Operation = foDelete;
+  FInfo->Side = osLocal;
+
+  DebugAssert(FilesToDelete != NULL);
+  FFilesToDelete.reset(CloneStrings(FilesToDelete));
+  ExtractLocalSourcePath(FilesToDelete, FInfo->Source);
+
+  FInfo->ModifiedLocal = FInfo->Source;
+
+  FParams = Params;
+}
+//---------------------------------------------------------------------------
+void __fastcall TLocalDeleteQueueItem::DoExecute(TTerminal * Terminal)
+{
+  DebugAssert(Terminal != NULL);
+  Terminal->DeleteLocalFiles(FFilesToDelete.get(), FParams);
+}
+//---------------------------------------------------------------------------
 // TTerminalThread
 //---------------------------------------------------------------------------
 __fastcall TTerminalThread::TTerminalThread(TTerminal * Terminal) :

+ 16 - 4
source/core/Queue.h

@@ -208,7 +208,7 @@ protected:
   void __fastcall SetCPSLimit(unsigned long CPSLimit);
   unsigned long __fastcall GetCPSLimit();
   virtual unsigned long __fastcall DefaultCPSLimit();
-  virtual UnicodeString __fastcall StartupDirectory() const = 0;
+  virtual UnicodeString __fastcall StartupDirectory() const;
   virtual void __fastcall ProgressUpdated();
   virtual TQueueItem * __fastcall CreateParallelOperation();
   virtual bool __fastcall Complete();
@@ -312,7 +312,6 @@ public:
 
 protected:
   virtual void __fastcall DoExecute(TTerminal * Terminal);
-  virtual UnicodeString __fastcall StartupDirectory() const;
   virtual bool __fastcall Complete();
 };
 //---------------------------------------------------------------------------
@@ -377,10 +376,23 @@ protected:
   virtual void __fastcall DoTransferExecute(TTerminal * Terminal, TParallelOperation * ParallelOperation);
 };
 //---------------------------------------------------------------------------
-class TDeleteQueueItem : public TLocatedQueueItem
+class TRemoteDeleteQueueItem : public TLocatedQueueItem
+{
+public:
+  TRemoteDeleteQueueItem(TTerminal * Terminal, TStrings * FilesToDelete, int Params);
+
+protected:
+  virtual void __fastcall DoExecute(TTerminal * Terminal);
+
+private:
+  std::unique_ptr<TStrings> FFilesToDelete;
+  int FParams;
+};
+//---------------------------------------------------------------------------
+class TLocalDeleteQueueItem : public TQueueItem
 {
 public:
-  TDeleteQueueItem(TTerminal * Terminal, TStrings * FilesToDelete, int Params);
+  TLocalDeleteQueueItem(TStrings * FilesToDelete, int Params);
 
 protected:
   virtual void __fastcall DoExecute(TTerminal * Terminal);

+ 1 - 0
source/core/Terminal.cpp

@@ -4357,6 +4357,7 @@ void __fastcall TTerminal::DeleteLocalFile(UnicodeString FileName,
   {
     OnDeleteLocalFile(FileName, FLAGSET(*((int*)Params), dfAlternative), Deleted);
   }
+  AppLogFmt(L"Deleted local file \"%s\"", (FileName));
   if (DebugAlwaysTrue((OperationProgress != NULL) && (OperationProgress->Operation == foDelete)))
   {
     OperationProgress->Succeeded(Deleted);

+ 74 - 47
source/forms/CustomScpExplorer.cpp

@@ -4376,75 +4376,102 @@ void __fastcall TCustomScpExplorerForm::DeleteFiles(TOperationSide Side,
 
   try
   {
-    if (!IsSideLocalBrowser(Side))
+    int Params = FLAGMASK(Alternative, dfAlternative);
+    bool Remote = !IsSideLocalBrowser(Side);
+    std::unique_ptr<TStringList> DeletedFiles;
+    std::unique_ptr<TStrings> PermanentFileList;
+    bool AllowMoveToQueue = (Terminal != NULL);
+    if (AllowMoveToQueue)
     {
-      DebugAssert(Terminal != NULL);
-
-      // Clone the file list as it may refer to current directory files, which get destroyed, when the directory is reloaded after the operation
-      std::unique_ptr<TStrings> PermanentFileList(TRemoteFileList::CloneStrings(FileList));
-      std::unique_ptr<TStringList> DeletedFiles(new TStringList());
-      DeletedFiles->CaseSensitive = DebugAlwaysTrue(!IsSideLocalBrowser(Side));
-      int Params = FLAGMASK(Alternative, dfAlternative);
+      DeletedFiles.reset(new TStringList());
+      DeletedFiles->CaseSensitive = Remote;
+    }
 
-      try
+    try
+    {
+      DebugAssert(FDeletedFiles == NULL);
+      TValueRestorer<TStrings *> DeletedFilesRestorer(FDeletedFiles, DeletedFiles.get());
+      TValueRestorer<TFileOperationFinishedEvent> OnFileOperationFinishedRestorer(FOnFileOperationFinished);
+      if (AllowMoveToQueue)
       {
-        DebugAssert(FDeletedFiles == NULL);
-        TValueRestorer<TStrings *> DeletedFilesRestorer(FDeletedFiles, DeletedFiles.get());
-        TValueRestorer<TFileOperationFinishedEvent> OnFileOperationFinishedRestorer(FOnFileOperationFinished);
         FOnFileOperationFinished = FileDeleted;
+      }
 
-        FMoveToQueue = false;
+      FMoveToQueue = false;
 
-        Terminal->DeleteFiles(FileList, Params);
+      if (Remote)
+      {
+        DebugAssert(AllowMoveToQueue);
+        // Clone the file list as it may refer to current directory files, which get destroyed, when the directory is reloaded after the operation
+        PermanentFileList.reset(TRemoteFileList::CloneStrings(FileList));
+        DebugAssert(Terminal != NULL);
 
-        // Probably not needed for deleting, just for consistency with transfer code
-        if (FMoveToQueue)
+        Terminal->DeleteFiles(FileList, Params);
+      }
+      else
+      {
+        if (AllowMoveToQueue) // optimization)
         {
-          Abort();
+          PermanentFileList.reset(CloneStrings(FileList));
+        }
+        if (IsLocalBrowserMode())
+        {
+          Configuration->Usage->Inc(L"LocalLocalDeletes");
+        }
+        TValueRestorer<TOperationSide> ProgressSideRestorer(FProgressSide, FCurrentSide);
+        try
+        {
+          TTerminalManager::Instance()->LocalTerminal->DeleteLocalFiles(FileList, Params);
+        }
+        __finally
+        {
+          ReloadLocalDirectory();
         }
       }
-      catch (EAbort &)
+
+      // Probably not needed for deleting, just for consistency with transfer code
+      if (FMoveToQueue)
       {
-        if (FMoveToQueue)
+        Abort();
+      }
+    }
+    catch (EAbort &)
+    {
+      if (FMoveToQueue && DebugAlwaysTrue(AllowMoveToQueue) && DebugAlwaysTrue(Terminal != NULL))
+      {
+        FMoveToQueue = false;
+
+        DeletedFiles->Sorted = true;
+        for (int Index = 0; Index < PermanentFileList->Count; Index++)
         {
-          DeletedFiles->Sorted = true;
-          for (int Index = 0; Index < PermanentFileList->Count; Index++)
+          if (DeletedFiles->IndexOf(PermanentFileList->Strings[Index]) >= 0)
           {
-            if (DeletedFiles->IndexOf(PermanentFileList->Strings[Index]) >= 0)
-            {
-              // We should always be deleting the first item => what can be used to optimize this code, if needed
-              DebugAssert(Index == 0);
-              PermanentFileList->Delete(Index);
-              Index--;
-            }
+            // We should always be deleting the first item => what can be used to optimize this code, if needed
+            DebugAssert(Index == 0);
+            PermanentFileList->Delete(Index);
+            Index--;
           }
+        }
 
-          FMoveToQueue = false;
+        if (Remote)
+        {
           Configuration->Usage->Inc("MovesToBackgroundDelete");
 
-          TQueueItem * QueueItem = new TDeleteQueueItem(Terminal, PermanentFileList.get(), Params);
+          TQueueItem * QueueItem = new TRemoteDeleteQueueItem(Terminal, PermanentFileList.get(), Params);
           AddQueueItem(Queue, QueueItem, Terminal);
+        }
+        else
+        {
+          Configuration->Usage->Inc("MovesToBackgroundDeleteLocal");
 
-          ClearOperationSelection(osRemote);
+          TQueueItem * QueueItem = new TLocalDeleteQueueItem(PermanentFileList.get(), Params);
+          AddQueueItem(Queue, QueueItem, Terminal);
         }
+
+        ClearOperationSelection(Side);
       }
     }
-    else
-    {
-      if (IsLocalBrowserMode())
-      {
-        Configuration->Usage->Inc(L"LocalLocalDeletes");
-      }
-      TValueRestorer<TOperationSide> ProgressSideRestorer(FProgressSide, FCurrentSide);
-      try
-      {
-        TTerminalManager::Instance()->LocalTerminal->DeleteLocalFiles(FileList, FLAGMASK(Alternative, dfAlternative));
-      }
-      __finally
-      {
-        ReloadLocalDirectory();
-      }
-    }
+
     FAlternativeDelete = false;
   }
   catch(...)