I have been using SQLite for quite some time and have had the "fortune" of dealing with some locking issues. I am pretty certain that SQLite uses byte-range locks on Unix filesystems by default.
To be more precise, it contains code for a few alternative locking methods (e.g using flock()
and dotlock-style whole-file locks). When compiled with the SQLITE_ENABLE_LOCKING_STYLE
option it attempts to auto-detect the proper locking method for the underlying filesystem.
The auto-detection code contains some hard-coded cases (e.g. "ufs", "nfs" and "smbfs"), none of which is AFS. If no hard-coded case matches, SQLite attempts to acquire a byte-range lock on a file using fcntl()
. It then assumes that if the fcntl()
call succeeds, then byte-range locks are available.
Here is where OpenAFS comes in to make things interesting. Apparently ([1], [2], [3]) OpenAFS has a long history of lying to the userspace applications about byte-range locks. From the openafs-1.4.14
source code:
/* next line makes byte range locks always succeed,
* even when they should block */
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
DoLockWarning();
afs_PutFakeStat(&fakestate);
return 0;
}
In one word: Ouch!
It allows byte-range locks to succeed no matter what. On Linux, it is conceivably even worse: it uses the kernel infrastructure to provide byte-range locks among the processes of the same system. That means that an application cannot just fork a new process and test the locking mechanism - byte-range locks will appear to be working fine, while failing horribly to protect a file from remote processes.
In short: you cannot use an unmodified SQLite reliably with OpenAFS. Most other network filesystems have issues as well, hence the recommendation to avoid network filesystems completely.
A few possible work-arounds in no particular order:
Use a proper DBMS, such as PostgreSQL. If it is possible to do this, you'll be better off in the long run.
Implement your own server for your application, if a full-blown DBMS is overkill.
Modify the SQLite source code to default to flock()
on OpenAFS. I am not sure if this will work properly, since OpenAFS has a long history ([1], [2]) of locking issues even with plain-old flock()
, but you won't know until you test it.
Implement your own OpenAFS VFS for SQLite, using the OpenAFS userspace, rather than going through the kernel.
Try your luck with another network filesystem.
Whatever you do, you will have to perform extensive testing if in any way it involves SQLite3 and a shared database file.
EDIT:
A commenter suggested using the dotlock file mechanism. I didn't delve into the OpenAFS source code too much, but at first glance it appears to support the open(O_CREAT|O_EXCL)
method of creating dotlock files that SQLite uses. If that works as it is supposed to, then SQLite might indeed be usable with OpenAFS if you force it to use the dotlock method.
That said, dotlocks are enough of a problem on regular local filesystems, without introducing the intricacies of a network filesystem into the mix - which is why I did not suggest it in the first place.