views:

71

answers:

2

I have a directory that contains lots of files in a complex tree of sub-directories.

If I try to move that directory into a another directory on the same partition, that operation could theoretically take constant time - a rename operation, basically. - as long as none of the files in the source directory are in use and there are no security issues, right?

If so, how can I tell programmatically if it's possible to move directory A to B?

Is there any locking related API that can help me with this?

I'm using C# on NTFS partitions.

+2  A: 

These kind of "could this work" APIs don't exist on a multi-tasking operating system. They are inherently unreliable, like checking if a file is locked. Such a test could return "not locked", then your thread could be pre-empted and another thread in another process could lock the file. When your thread regains the CPU, you'll find out that the file is locked, even though the test said it wasn't.

The only way to do this is to actually perform the operation, then look for an error to indicate it wasn't possible. An exception in C#, use the try statement to catch the IOException. Not that easy to deal with, but at least NTFS allows you to rename or move a file that is locked.

Hans Passant
That would only work if the move operation was guaranteed to be atomic. I don't see anything in the API's docs that would suggest that the function always throws immediately if it cannot move a directory by "rename"...
Assaf Lavie
It can be, you'd have to P/Invoke MoveFileTransacted(), available on Vista and up. But otherwise, no, partial failure is something you'd have to deal with.
Hans Passant
The same functionality exists in Windows XP. I just doubt that there's no way to tap into it programmatically. Windows XP implements move by rename when it can, and falls back to recursive moving if it fails. I need to be able to do the same on XP myself.
Assaf Lavie
+2  A: 

There are so many things that will let your move operation fail:

  • A file in the directory is locked
  • You don't have write permission on B
  • You don't have write permission on A (copy works but not move)
  • You have write permission on A but not on every file inside
  • data corruption (broken hdd)
  • Someone already moved that folder

And possibly many more you won't think of until it happens in production.

Anyway, NTFS supports Transactions since Vista/2008, so you could possibly wrap your task in a TransactionScope:

Here is an article about that: http://msdn.microsoft.com/en-us/magazine/cc163388.aspx

And a great tutorial here: community.bartdesmet.net

SchlaWiener
also you might not have enough free space in rare instances to accomodate the new bigger $index buffer.
Dominik Weber