4

This is similar with this question but with one more requirement:

Since the deletion of files can fail for whatever reasons. So I want the operation to be "transacted" which mean the whole operation either success in total, or fail and do not change anything at all.

In general this will be very very hard and I can't see any possibility to recover when the physical hard drive suddenly broken. So a weakened clause would be: if it success, we finished. Otherwise if fail, restore everything to the original state when possible.

Some kind of errors I could think of would be:

  1. Access violation. You simply don't allowed to delete some files or folders. This is the case that I wanted to handle the most.

  2. File/folder was used by somebody else and so it is "locked". In Linux this is not a problem but in Windows it is. This is also to be handled.

  3. If it is a network folder there could be network issues. The recover can be hard or impossible. I would not expect this kind of error to be properly handled.

  4. Hardware failure. I don't think any recover can happen here.

Scenario

You have a software that can export its internal data. The result is in a folder and with sub-folder names timestamped.

Now if the user specified a folder that is not empty (probably a previous output folder), the software will create new sub-folders on top of it, which is a mass. So you want to ensure the folder is empty before performing the export.

You can easily detect the folder emptiness and alert the user if not. But if the user say "go ahead and do it" you should do something then. Now, what if you were deleted some of the files and failed on others?

Going ahead in this case is just creating worse mass. At the same time the user would not expect a damaged folder without getting anything working. So it is better to either give them a fully working output or does not change the previous output at all.

Community
  • 1
  • 1
Earth Engine
  • 10,048
  • 5
  • 48
  • 78
  • 2
    More context would be helpful. Why are you deleting these files? Could you simply rename the folder (atomic) then retry deletion at your leisure? – Blorgbeard May 08 '15 at 01:21
  • The software was specified a folder to output its data. To avoid confusion that folder is required to be empty. However if we cannot safely remove everything there we are expected to fail and keep everything existing. – Earth Engine May 08 '15 at 01:24
  • 1
    Should the title have the word "Transactionally" rather than "Transitionally"? – Enigmativity May 08 '15 at 01:40
  • 3
    For your need, can you rename the folder. Then delete the content of the folder and the folder itself. In that case, the original folder is gone in a single call. – David Thielen May 08 '15 at 01:40
  • @Blorgbeard is right, can't you cache them to a subfolder or alternative location, try your deletes and it fails move the files back again? – Jane S May 08 '15 at 01:42
  • @JaneS I think this is what I need. Can you try to write an answer based on this idea? – Earth Engine May 08 '15 at 01:45
  • @EarthEngine now that an idea for a solution is clarified, what have *you* tried? – Jimmy May 08 '15 at 01:48
  • I have not attempted yet. But I started. – Earth Engine May 08 '15 at 01:51
  • @EarthEngine I'll write pseudo code if that is sufficient for you to follow. I don't have time to write the C# code right now. – Jane S May 08 '15 at 01:53

2 Answers2

2

As per comments, I'll give you the pseudocode for the process you can follow writing the code:

Clear contents of cache folder if any files exist (they shouldn't)
Copy contents of destination folder to cache folder
Try
    While files exist, iterate
        Delete file
    End While
Catch
    While files exist in cache, iterate
        If file does not exist in destination folder
            Move file from cache to destination
        else
            Delete file from cache
        end If
    End While
End Try
Jane S
  • 1,417
  • 16
  • 21
0

By following the guidelines given in the comments, I came up with this solution.

The following code will attempt to move everything to a temporary folder inside the given folder. If success, it returns True. If failed, the catch block will then try to move everything back and return a False. In either case, the finally block will remove the temporary folder recursively.

public static bool EmptyFolderTransactionaly(string folder)
{
    var directoryInfo = new DirectoryInfo(folder);
    var tmpDir = Directory.CreateDirectory(Path.Combine(folder, Path.GetFileName(Path.GetTempFileName())));
    try
    {
        foreach (var e in directoryInfo.EnumerateFiles())
        {
            e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
        }
        foreach (var e in directoryInfo.EnumerateDirectories().Where(e => e.Name!=tmpDir.Name))
        {
            e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
        }
        return true;
    }
    catch
    {
        foreach (var e in tmpDir.EnumerateDirectories())
        {
            e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
        }
        foreach (var e in tmpDir.EnumerateFiles())
        {
            e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
        }
        return false;
    }
    finally
    {
        tmpDir.Delete(true);
    }
}

Let me know if you see any risks in the code.

Earth Engine
  • 10,048
  • 5
  • 48
  • 78
  • 1
    Well for one thing, what happens if there is an error while moving the files back during the `catch`? – Matt Johnson-Pint May 08 '15 at 03:12
  • I said "restore when possible", so if there is an error when moving back, that is a case that restoring is impossible, I consider. – Earth Engine May 08 '15 at 03:14
  • FYI - There was this thing called [TxF](https://msdn.microsoft.com/en-us/library/windows/desktop/bb968806.aspx) designed for transactional file system. There's a wrapper for it [here](http://alphafs.alphaleonis.com/). It's *not* recommended any more though. You might also look at [this library](https://transactionalfilemgr.codeplex.com/), which claims to support transactional file operations without TxF. Not sure how well it works though. But in general, what you are describing is not a trivial thing to do. The approach you showed may work, but it will only get you so far. – Matt Johnson-Pint May 08 '15 at 03:18