On Mon, 2 Aug 2004, Tito Ciuro wrote:

Hello Ara,

On 2 ago 2004, at 9:59, Ara.T.Howard wrote:

the simplest way to do this is to create a file for each db, say db.lock,
and to apply a blocking read/write to this file depending on the intent of
your operation.  the contents of this file are not important - it is merely
used as a mutex that processes can coordinate access
to the database with.  the key is to ask for the locks in a blocking
fashion - this should ensure that only one process is accessing the
database at a given moment and prevent sqlite from ever needing to return
'database is locked'.

A word of caution to Mac OS X SQLiters. The following statement applies to Jaguar (Mac OS X 10.2) and earlier. I'm not sure it it's still the case with Panther (10.3) and Tiger (10.4) though:

Creating a file is not an atomic operation and may produce a race condition
if two or more processes attempt to create such lock file at the same time,
on the same place. The solution in this case is to create a directory
instead. Using this route, there won't be race conditions.

There is a small performance hit, but considering that a file lock may cause
you trouble, I would think that it's better to bite the bullet and go for
the safest solution.

Again, I'm not sure this applies to Panther or Tiger.

Regards,

-- Tito

hello tito-

i'm speaking of using a pre-existing file and appying an fcntl based lock to
this file, not creating a lockfile, so it does not matter that the creation is
not atomic, for example:

  ~ > sqlite db 'create table foo(bar)'
  ~ > touch lock

now in code you will do either

  blocking request for fcntl read lock on 'lock'
    access db in usual way
  release fcntl lock

or

  blocking fcntl request for write lock on 'lock'
    access db in usual way
  release fcntl lock

the lock requests must use the F_SETLKW flag - so they are blocking
procedures.  if all processes accessing the db using this protocol then you
can be guarenteed to never get a 'database is locked' error because you'll
only access the database (which applies it's own fcntl locks to the db in
non-blocking fashion) after getting a valid lock.  it's critical to use fcntl
based locks because only they work on NFS and it's critical to use another
file because a blocking lock applied to the db would be superceeded by the
first fcntl lock the sqlite api requested.

regarding atomic creation of lockfiles: this can be done using link(2).   i
have a library and command line tool for doing so, but have never tested it on
a mac.  it can be found at

  http://raa.ruby-lang.org/project/lockfile/

cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it. | --Dogen
===============================================================================

Reply via email to