dlras2
dlras2

Reputation: 8496

Atomically locking multiple files

What is the best way to atomically lock multiple files? One possibility I've thought of is a simple .lock file in the directory (I'm only protected from other instances of my program; I'm not necessarily trying to thwart other programs from disrespecting the lock.) However, everything I've learned about thread-safety screams "bad idea!" Would this be a safe way to go? Is trying to create a file atomic, so if I succeed in creating it, I know I have the lock? How should I go about this?

I'm writing my own bug tracker (mostly as an exercise, I know I could find good solutions out there,) which stores bugs in files on the network. I envision it kind of like SVN - a single directory gets taken over by the program, and used to hold bugs, revisions, screenshots, etc, all managed by the tracker. I'm assuming SVN has a way to ensure multiple clients don't make commits at the exact same time, etc.

Upvotes: 1

Views: 319

Answers (5)

ChrisW
ChrisW

Reputation: 56123

I want multiple users submitting bugs from various places on the network.

Use a database engine.

Perhaps you're right, but then I'm curious how SVN works. It appears to me that there are no servers, all the clients simply access a standard structure of files in your SVN directory.

http://www.pushok.com/soft_svn_vscvs.php says that SVN is based on a BerkleyDB.

Upvotes: 0

Ray Henry
Ray Henry

Reputation: 905

Open each file exclusively, if you find one that can't be opened, then unlock the ones you've already locked. Always lock in alphabetical order to avoid deadlocks.

    private List<FileStream> OpenExclusive(List<string> filenames)
    {
        var streams = new List<FileStream>(filenames.Count);

        try
        {
            filenames.Sort();
            foreach (var name in filenames)
            {
                streams.Add(File.Open(name, 
                  FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None));
            }
            return streams;
        }
        catch (Exception)
        {
            CloseAll(streams);
            return null;
        }
    }

    private void CloseAll(List<FileStream> streams)
    {
        if (streams == null) return;
        foreach (var stream in streams)
        {
            stream.Close();
        }
    }

Upvotes: 1

jthg
jthg

Reputation: 2850

One simple and reliable option is to have your application rename the directory containing those files before it starts using them. It can rename the directory to a random name before it starts and rename it back when it finishes. If the rename is successful, there's no possibility of a conflict.

One disadvantage is that if an application instance fails to rename the directory back, others will be locked out forever. You might be able to come up with some scheme in which the renamed directory name encodes the time it was renamed. If other instances see that a timeout period has passed, they can take control of it.

Have you looked into existing libraries so that you won't have to come up with your own solution and deal with all the edge cases? I unfortunately don't know of any off the top of my head.

Upvotes: 0

Steven Sudit
Steven Sudit

Reputation: 19640

If you open a file for exclusive access, it will remain locked in that anyone else attempting to open it will fail.

Upvotes: 0

Andrey
Andrey

Reputation: 60115

i recommend Mutex, named mutex is operation system wide.

Upvotes: 0

Related Questions