From e32b221f0be6c37d2a4e6c9dce616e1eb11fdc6d Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 22 Dec 2014 20:32:58 +0000 Subject: [PATCH] backend.py: Introduce protocol for alternative locking schemes. It sounds fancier than it is. There's now a method for FlatFileBackend subclasses to override if they want to apply different locking semantics. --- backend.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/backend.py b/backend.py index 576486c..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 @@ -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 @@ -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.""" -- 2.11.0