Channels ▼

Bil Lewis

Dr. Dobb's Bloggers

The Right Way to Do File Locking

February 09, 2009

I was previously complaining that there wasn't a good way to lock the
use of a file across a network. Java has a recommended way of doing
it, but unfortunately it isn't implemented on all networks! So it's
useless in an unrestricted environment.

No... it's worst than useless, because it fools you into thinking
you're getting exclusive access when you're not.

But it really isn't a very good interface anyway. Wait... I better go
look again... I'm too harsh. It's almost right.

Let me tell you what is completely right.

(Is that a little pushy of me? Asserting I'm correct? But in this case
I *am* correct! And you will agree.)

The question is "What functionality do I need to do what I want with a
file?"

I wish to be able to declare to the world that I should have exclusive
access to some file (which may or may not actually exist
yet). Obviously I wish to be able to release the lock and let everyone
who's waiting for it know. I also wish to be able to declare a failure
in case I was writing to the file and I crashed. And a failure
recovery mechanism.

That's what I want. I can build anything else I desire from those
features.

Should the filesystem enforce my exclusive access? That is an very
interesting question, but I'm not going to touch it today. I'm happy
trusting cooperating processes to play nice.

Here's what my interface should look like:

interface FileLock {

  public FileLock(String pathname);
  public LockState lock();
  public unlock();
  public LockState trylock();
  public LockState lockForReadingOnly();
  public LockState trylockForReadingOnly();
  public boolean reset();

}

It's basically a standard readers/writer lock ala Posix or Java, with
a LockState object that indicates if the lock was last released
normally or if the owning process died, leaving it in an unknown
state. The state is either Valid or Invalid.

All the methods are very simple and do pretty much what Posix and Java
do, the lock just happens to be on a network.

The two interesting bits are that there doesn't have to be a file by
the given name at all. The lock is really in a completely separate
namespace that's exclusively controlled by the server. The objective
is that I will often want to create an index file for some existing
data file, and I want to be able to do that atomically. So
"physically" the lock has nothing to do with an actual file, other
than it may share a name.

The other interesting bit is the possibility of a lock being in an
Invalid state. 

It's easy to implement the required functionality. The server just has
to be able to poll its lock owners every now and then to make sure
they're alive. Of course it has to get a reliable answer and that can
be tricky...

When it asks a machine if an owner process is running, as long as it
gets an answer, all is well. It can mark the lock accordingly. If it
*doesn't* get an answer, then all bets are off.

[This is too complicated to get into here. I'm assuming prompt
answers. (What would you do?)]

If I ask for a lock and I get Invalid, what do I do?

There's no uniform answer.

I was building indexes for a Fasta file when all this started, so for
me that answer is simple: Clear the file and rebuild the index.

The reset() method sets the lock to Valid and locks it. Atomically, of
course. (It has to work like this. If it just cleared the lock and left
it unlocked, then other process might try to recover it also. Right?)

If the file was being used as a general database, then the programmer
has a lot of work to do. There's no easy way around this. The
filesystem *cannot* know the state of the data inside the file. (If you
tried to implement something like that, you would go crazy.)

This, of course, is the Two-Phase Commit problem again.

And while I would really like to see a good interface for supporting
TPC, it doesn't belong at this level.

Remember all that messy code I wrote for the FastaReader?

Here's what it should look like:




public void readIndex(String pathname) {
  File file = new File(pathname);
  FileLock lock = new FileLock(pathname);
  FileStatus status = lock.lock();
  if (status == Invalid) {
    boolean gotOwnership = lock.reset();
    if (gotOwnership) {
      file.delete();
    } 
  }
  if (!file.exists())
    createIndexFor(pathname);
  readIndexFor(pathname);
  lock.unlock();
}




Isn't that beautiful?



And that's why I'm right.

-Bil

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video