Detecting that recursion has finished

I’m essentially using the recursive file deletion function from the LR to delete files and folders.

The only difference is that the code I’ve written deletes files and folders from within a subset of folders within a base folder. It does not delete the base folder or the subset of folders inside the base folder in which it’s working.

It does delete the files and folders inside the subfolders of the base folder.

File and folder deletion is based on creation dates.

I’m struggling to find the best way (or any way, for that matter) to detect that the function has finished?

Could I get input?

Thanks.

[code]Function Purge(theFolder as FolderItem, continueIfErrors as Boolean = false) As Integer

If Job_Purge = True then

// Setup date variables for building file names.
Dim todayDate as New Date
Dim theDateTotalSeconds as Double
Dim numberSecondsForDelete as Double
Dim dayFolderNameString as String

// Update Status column with downloading.
wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 2) = "Purging"

// 86400 seconds = 24 hours
theDateTotalSeconds = todayDate.TotalSeconds
numberSecondsForDelete = 86400 * Download_Day_Count

// Returns an error code if it fails or zero if the folder was deleted successfully
Dim returnCode, lastErr, itemCount as Integer
Dim files(), dirs() as FolderItem

If theFolder = nil or not theFolder.Exists then
  Return 0
End If

// Collect the folder‘s contents.
itemCount = theFolder.Count
For i as Integer = 1 to itemCount
  
  Dim f as FolderItem
  f = theFolder.TrueItem(i)
  
  If f <> nil then
    If f.Directory then
      dirs.Append f
    Else
      files.Append f
    End If
  End If
  
Next

// Delete the files.
For each f as FolderItem in files
  
  If theDateTotalSeconds >= f.CreationDate.TotalSeconds + numberSecondsForDelete then
    wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 1) = f.Name
    f.Delete
  End If
  
  lastErr = f.LastErrorCode
  
  If lastErr <> 0 then
    If continueIfErrors then
      If returnCode = 0 then returnCode = lastErr
    Else
      // Return the error code if any. This will cancel the deletion.
      Return lastErr
    End If
  End If
  
Next

// Free the memory used by the files array before we enter recursion
Redim files(-1)

// Now delete the directories
For each f as FolderItem in dirs
  lastErr = Purge( f, continueIfErrors )
  If lastErr <> 0 then
    If continueIfErrors then
      If returnCode = 0 then returnCode = lastErr
    Else
      // Return the error code if any. This will cancel the deletion.
      Return lastErr
    End If
  End If
Next

dayFolderNameString = "1_Sunday,2_Monday,3_Tuesday,4_Wednesday,5_Thursday,6_Friday,7_Saturday"

If returnCode = 0 then
  // Done without error, so the folder should be empty and we can delete it.
  If InStr(dayFolderNameString, theFolder.Name) = 0 then
    wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 1) = theFolder.Name
    theFolder.Delete
    returnCode = theFolder.LastErrorCode
  End If
End If

End If

wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 2) = “Purge”
'wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 1) = “Purge done”

'Unzip

'Return returnCode
End Function
[/code]

a recursive function is usually called from two places…

once outside the actual function… and then inside the function as required (hence the recursive part… self calling self)

The recursion completes when control passes back to the line after the outside call.

When any function is called then after its completion the program execution should continue at the next line of code from where this function was called.

What Dave said. Note that there is code in there that shouldn’t be part of the recursion, namely the code that updates the listbox. And probably the code that tests the Job_Purge flag. You should move that into its own top-level method that sets up before the recursion and then cleans up after. Otherwise, as you have seen, you can’t tell from within the file manipulation code where you are in the recursive process. Nor should you care.

This code

    If returnCode = 0 then
      // Done without error, so the folder should be empty and we can delete it.
      If InStr(dayFolderNameString, theFolder.Name) = 0 then
        wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 1) = theFolder.Name
        theFolder.Delete
        returnCode = theFolder.LastErrorCode
      End If
    End If

is probably not valid, since you’re not deleting ALL the files anymore, just the ones that match your criteria.

What are files and dirs? I don’t see them dimmed in the code. They should be local arrays.

I assumed this as well, however the original caller is returned to several times.

The Run event of this thread is called from a method within an HTTP socket.

This function is running in a thread.
The function is called from the Run event of this thread.

It is returning multiple times all the way back to the HTTP socket.

Call from method in HTTP socket:
Processing_Thread_Clone.Run

Processing_Thread_Clone Run:
Dim errorCode as Integer
errorCode = Purge(Base_Folder)

[quote=94330:@Michael Brogdon]This function is running in a thread.
The function is called from the Run event of this thread.[/quote]
That could be the problem. What event of the socket is it called from?

It is impossible for it to “return multiple times all the way back to the HTTP socket” since you’re not calling it from the socket. The thread is completely independent of the socket.

I found that the end of the recursion can be detected by placing code at the very end of the code in the method of the HTTP socket that calls the thread’s Run event.

What’s the task you want to accomplish?
Receive a remote command (via socket) to delete some folders (going deeper, thus the recursion)?
Then you want to know when it finished?

Why? Because it’s updating the GUI?

[quote=94326:@Tim Hare]This code

If returnCode = 0 then
  // Done without error, so the folder should be empty and we can delete it.
  If InStr(dayFolderNameString, theFolder.Name) = 0 then
    wnMain.ProgressListBox1.Listbox1.Cell(Job_Row, wnMain.ProgressListBox1.PB_Column - 1) = theFolder.Name
    theFolder.Delete
    returnCode = theFolder.LastErrorCode
  End If
End If

is probably not valid, since you’re not deleting ALL the files anymore, just the ones that match your criteria.[/quote]

It does seem to work as expected.

It’s there. “Dim files(), dirs() as FolderItem”

It’s being called from a method I created inside the HTTP socket.

But it is…

I created a integer variable and set it to 1 within the HTTP method and added it to itself and placed the resulting number in a cell of the listbox. Message box test also confirmed it was returning.

[quote=94342:@Michael Brogdon]Why? Because it’s updating the GUI?
[/quote]
No, because that setup only needs to happen one time, not every time through the recursion.

[quote]It does seem to work as expected.
[/quote]
Strange. If it’s in a thread, you should be getting an exception.

[quote]It’s there. “Dim files(), dirs() as FolderItem”
[/quote]
I see it now. (That’s why I dislike dimming variables in the middle of code.) So this line

    // Free the memory used by the files array before we enter recursion
    Redim files(-1)

isn’t really necessary. Doesn’t hurt, but it’s really overkill.

[quote]It’s being called from a method I created inside the HTTP socket.
[/quote]
And where is that method being called from?

[quote]But it is…

I created a integer variable and set it to 1 within the HTTP method and added it to itself and placed the resulting number in a cell of the listbox. Message box test also confirmed it was returning.[/quote]
All that means is the method is being called multiple times. Not returned to.

No. The HTTP socket code that calls the thread’s run event does not stop executing while the thread runs. That’s the core of your problem. The HTTP socket code will start the thread and then continue executing while the thread is also executing. By starting a thread, you have divorced the purge code from the HTTP code. There is no way for the HTTP code to know that the thread, and therefore the purge, has finished, unless it sits in a loop and waits for the thread’s state to go to NotRunning. But that defeats the purpose of using a thread.

You could create a class like “Purger” with events. Those events could update the UI using timers. You should have a a parameter like “DeleteFolders as Boolean = True” and in your first call it should be false (to maintain the first level of dirs as you specified). All inter recursion level messages must be passed as parameters, never as external flags. When exiting the method with DeleteFolders=False (first Level) you could emit an Event like “PurgeEnded”