X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/chopwood/blobdiff_plain/82d4f64b774253438506cec05eacad5af158ccac..b91d3f0725ba4cda985ba91fb2fd41b7e3a3d54d:/backend.py diff --git a/backend.py b/backend.py index 7c6645a..fda32e0 100644 --- a/backend.py +++ b/backend.py @@ -25,6 +25,8 @@ from __future__ import with_statement +from auto import HOME +import errno as E import itertools as I import os as OS; ENV = OS.environ @@ -37,7 +39,7 @@ import util as U CONF.DEFAULTS.update( ## A directory in which we can create lockfiles. - LOCKDIR = OS.path.join(ENV['HOME'], 'var', 'lock', 'chpwd')) + LOCKDIR = OS.path.join(HOME, 'lock')) ###-------------------------------------------------------------------------- ### Utilities. @@ -206,10 +208,13 @@ class FlatFileBackend (object): specified by the DELIM constructor argument. The file is updated by writing a new version alongside, as `FILE.new', and - renaming it over the old version. If a LOCK file is named then an - exclusive fcntl(2)-style lock is taken out on `LOCKDIR/LOCK' (creating the - file if necessary) during the update operation. Use of a lockfile is - strongly recommended. + renaming it over the old version. If a LOCK is provided then this is done + while holding a lock. By default, an exclusive fcntl(2)-style lock is + taken out on `LOCKDIR/LOCK' (creating the file if necessary) during the + update operation, but subclasses can override the `dolocked' method to + provide alternative locking behaviour; the LOCK parameter is not + interpreted by any other methods. Use of a lockfile is strongly + recommended. The DELIM constructor argument specifies the delimiter character used when splitting lines into fields. The USER and PASSWD arguments give the field @@ -255,7 +260,7 @@ class FlatFileBackend (object): for k, i in me._fmap.iteritems() if k.startswith('f_')], user, passwd, args) - r = FlatFileRecord(':'.join(f), me._delim, me._fmap, backend = me) + r = FlatFileRecord(me._delim.join(f), me._delim, me._fmap, backend = me) me._rewrite('create', r) def _rewrite(me, op, rec): @@ -329,11 +334,21 @@ class FlatFileBackend (object): ## If there's a lockfile, then acquire it around the meat of this ## function; otherwise just do the job. - if me._lock is None: - doit() - else: - with U.lockfile(OS.path.join(CFG.LOCKDIR, me._lock), 5): - doit() + if me._lock is None: doit() + else: me.dolocked(me._lock, doit) + + def dolocked(me, lock, func): + """ + Call FUNC with the LOCK held. + + Subclasses can override this method in order to provide alternative + locking functionality. + """ + try: OS.mkdir(CFG.LOCKDIR) + except OSError, e: + if e.errno != E.EEXIST: raise + with U.lockfile(OS.path.join(CFG.LOCKDIR, lock), 5): + func() def _parse(me, line): """Convenience function for constructing a record."""