views:

1542

answers:

5

Here's the thing: I have two applications, written in C++ and running on two machines with different OS (one Linux and one Windows). One of this process is in charge of updating an XML file on a NAS (Network Attached Storage) while the other one reads this file.

Is it possible to synchronize these two processes in order to avoid reading of the file at the same time it's being modified?

+4  A: 

You could create a lock file on the server that is created before you do a write, wait then write and delete on completion., Have the read process check for the token before reading the file.

Edit: To address the comments, you can implement a double-checked locking type pattern. Have both reader and writer have a locking file and double check before you do work, something like:

Reader: Check for write lock file, create read lock file, check for write lock file, if exists delete read file and abort.

Writer: Check for read lock file, create write lock file, check for read lock file, if exists delete write lock file and abort.

This will stop your processes trampling on each other but a potential race condition may occur in that the you could potentially have both processes check, create then recheck simultaneously though this will not cause the data to be read in an inconsistent state but will cause both read and write processes to abort for your specified delay

Wolfwyrd
+1, that's how I tend to do it.
Shane MacLaughlin
Well that's the simple solution we were using, but how can you assure that both processes won't check for file existence at the same time, then happily lock and start writing/reading together?
Luc Touraille
Double checked locking, have a lock file for read and for write, check for no file, create file, check for no file then take action like: http://en.wikipedia.org/wiki/Double-checked_locking
Wolfwyrd
@Wolfwyd. No. There is functionality already built into *nix file systems for this: Do a 'man 2 flock()'. Provides advisory file locks in both shared and exclusive mode.
Martin York
+1  A: 

If the files reside on an NFS share you can use fcntl(2) to lock the file. Check question D10 in the Linux NFS FAQ. I have very little experience with windows APIs but from what I've heard they have good POSIX support so you should be able to use fcntl as long as they support POSIX.1-2001.

If you are accessing the files using different protocols (i.e. AFS or SMB) maybe you could set up a simple synchronization server that manages locks via an IPC interface?

David Holm
+1  A: 

Would it be possible to switch from files to a database?

This type of concurency is something that DBMSs manage very well. It need no be expensive or difficult to install. MySql, Postgress or JavaDB would all handle this elegantly at little or no cost.

Failing the database option I would have the writing process write to a "hidden" file name like ".updateinprogress.xml" and rename the file when the update is complete. On most systems "mv" or "ren" is an atomic operation so the reading process either picks up hte old file or the newer file but never a half written one.

James Anderson
+2  A: 

OK you need some form of locking mechanism to control accesses.

Most *nix File systems provide this. I suspect it is also available on Windows File System (as this mechanism is used by perl) but it may have another name.

Take a look at the flock().
This is a file locking mechanism. It is an advisory lock so it does not actually lock the file and prevent usage but it provides a mechanism for marking the file. If both applications use the mechanism then you can control accesses to the file.

flock() provides both shared locks (or READ Lock) and exclusive locks (or WRITE Lock). flock will block your thread (in a non busy way) until the file has been unlocked by the user (it also provides NON blocking checks so you can do other things while waiting).

Check out flock in section 2 of the man pages.

int     flock(int fd, int operation);

Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd.  A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB.  To unlock an
existing lock operation should be LOCK_UN.
Martin York
flock isn't guaranteed to have the expected behavious on NFS shares with older versions of Linux.
David Holm
+1  A: 

Thank you all for your answers.

At last we managed to resolve our problem, not by using locking commands of the OS (because we were not sure they would propagate correctly to the OS of the NAS head), but by creating lock directories instead of lock files. Directory creation is an atomic operation, and returns an error value if the folder already exists. Therefore, we don't have to check the lock existence before acquiring it, both operations are made in a single step.

Luc Touraille