[Checkins] SVN: zc.lockfile/trunk/ Split locking code out of ZODB.
Jim Fulton
jim at zope.com
Wed Jul 18 07:24:03 EDT 2007
Log message for revision 78102:
Split locking code out of ZODB.
Changed:
A zc.lockfile/trunk/README.txt
A zc.lockfile/trunk/buildout.cfg
A zc.lockfile/trunk/setup.py
A zc.lockfile/trunk/src/
A zc.lockfile/trunk/src/zc/
A zc.lockfile/trunk/src/zc/__init__.py
A zc.lockfile/trunk/src/zc/lockfile/
A zc.lockfile/trunk/src/zc/lockfile/README.txt
A zc.lockfile/trunk/src/zc/lockfile/__init__.py
A zc.lockfile/trunk/src/zc/lockfile/tests.py
-=-
Added: zc.lockfile/trunk/README.txt
===================================================================
--- zc.lockfile/trunk/README.txt (rev 0)
+++ zc.lockfile/trunk/README.txt 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,14 @@
+*************************
+Basic inter-process locks
+*************************
+
+The zc.lockfile package provides a basic portable implementation of
+interprocess locks using lock files. The purpose if not specifically
+yo lock files, but to simply provide locks with an implementation
+based on file-locking primitives. Of course, these locks could be
+used to mediate access to *other* files. For example, the ZODB file
+storage implementation uses file locks to mediate access to
+file-storage database files. The database files and lock file files
+are separate files.
+
+.. contents::
Property changes on: zc.lockfile/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.lockfile/trunk/buildout.cfg
===================================================================
--- zc.lockfile/trunk/buildout.cfg (rev 0)
+++ zc.lockfile/trunk/buildout.cfg 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,7 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.lockfile
Property changes on: zc.lockfile/trunk/buildout.cfg
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.lockfile/trunk/setup.py
===================================================================
--- zc.lockfile/trunk/setup.py (rev 0)
+++ zc.lockfile/trunk/setup.py 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,47 @@
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+long_description=(
+ read('README.txt')
+ + '\n' +
+ 'Detailed Documentation\n'
+ '**********************\n'
+ + '\n' +
+ read('src', 'zc', 'lockfile', 'README.txt')
+ + '\n' +
+ 'Download\n'
+ '**********************\n'
+ )
+
+open('doc.txt', 'w').write(long_description)
+
+name = "zc.lockfile"
+setup(
+ name = name,
+ version = "1.0.0b1",
+ author = "Jim Fulton",
+ author_email = "jim at zope.com",
+ description = "Basic inter-process locks",
+ long_description=long_description,
+ license = "ZPL 2.1",
+ keywords = "lock",
+ url='http://www.python.org/pypi/'+name,
+
+ packages = find_packages('src'),
+ package_dir = {'': 'src'},
+ namespace_packages = ['zc'],
+ install_requires = 'setuptools',
+ include_package_data = True,
+ zip_safe=False,
+ classifiers = [
+ 'Programming Language :: Python',
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ ],
+ )
Property changes on: zc.lockfile/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.lockfile/trunk/src/zc/__init__.py
===================================================================
--- zc.lockfile/trunk/src/zc/__init__.py (rev 0)
+++ zc.lockfile/trunk/src/zc/__init__.py 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zc.lockfile/trunk/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Copied: zc.lockfile/trunk/src/zc/lockfile/README.txt (from rev 78057, ZODB/trunk/src/ZODB/lock_file.txt)
===================================================================
--- zc.lockfile/trunk/src/zc/lockfile/README.txt (rev 0)
+++ zc.lockfile/trunk/src/zc/lockfile/README.txt 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,33 @@
+Lock file support
+=================
+
+The ZODB lock_file module provides support for creating file system
+locks. These are locks that are implemented with lock files and
+OS-provided locking facilities. To create a lock, instantiate a
+LockFile object with a file name:
+
+ >>> import zc.lockfile
+ >>> lock = zc.lockfile.LockFile('lock')
+
+If we try to lock the same name, we'll get a lock error:
+
+ >>> try:
+ ... zc.lockfile.LockFile('lock')
+ ... except zc.lockfile.LockError:
+ ... print "Can't lock"
+ Can't lock
+
+To release the lock, use it's close method:
+
+ >>> lock.close()
+
+The lock file is not removed. It is left behind:
+
+ >>> import os
+ >>> os.path.exists('lock')
+ True
+
+Of course, now that we've released the lock, we can created it again:
+
+ >>> lock = zc.lockfile.LockFile('lock')
+ >>> lock.close()
Copied: zc.lockfile/trunk/src/zc/lockfile/__init__.py (from rev 78057, ZODB/trunk/src/ZODB/lock_file.py)
===================================================================
--- zc.lockfile/trunk/src/zc/lockfile/__init__.py (rev 0)
+++ zc.lockfile/trunk/src/zc/lockfile/__init__.py 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,93 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import os
+import errno
+import logging
+logger = logging.getLogger("ZODB.lock_file")
+
+class LockError(Exception):
+ """Couldn't get a lock
+ """
+
+try:
+ import fcntl
+except ImportError:
+ try:
+ import msvcrt
+ except ImportError:
+ def _lock_file(file):
+ raise TypeError('No file-locking support on this platform')
+ def _unlock_file(file):
+ raise TypeError('No file-locking support on this platform')
+
+ else:
+ # Windows
+ def _lock_file(file):
+ # Lock just the first byte
+ try:
+ msvcrt.locking(file.fileno(), msvcrt.LK_NBLCK, 1)
+ except IOError:
+ raise LockError("Couldn't lock %r" % file.name)
+
+ def _unlock_file(file):
+ try:
+ file.seek(0)
+ msvcrt.locking(file.fileno(), msvcrt.LK_UNLCK, 1)
+ except IOError:
+ raise LockError("Couldn't unlock %r" % file.name)
+
+else:
+ # Unix
+ _flags = fcntl.LOCK_EX | fcntl.LOCK_NB
+
+ def _lock_file(file):
+ try:
+ fcntl.flock(file.fileno(), _flags)
+ except IOError:
+ raise LockError("Couldn't lock %r" % file.name)
+
+
+ def _unlock_file(file):
+ # File is automatically unlocked on close
+ pass
+
+
+class LockFile:
+
+ _fp = None
+
+ def __init__(self, path):
+ self._path = path
+ fp = open(path, 'w+')
+
+ try:
+ _lock_file(fp)
+ except:
+ fp.seek(1)
+ pid = fp.read().strip()[:20]
+ fp.close()
+ logger.exception("Error locking file", path, pid)
+ raise
+
+ self._fp = fp
+ fp.write(" %s\n" % os.getpid())
+ fp.truncate()
+ fp.flush()
+
+ def close(self):
+ if self._fp is not None:
+ _unlock_file(self._fp)
+ self._fp.close()
+ self._fp = None
Copied: zc.lockfile/trunk/src/zc/lockfile/tests.py (from rev 78057, ZODB/trunk/src/ZODB/tests/test_lock_file.py)
===================================================================
--- zc.lockfile/trunk/src/zc/lockfile/tests.py (rev 0)
+++ zc.lockfile/trunk/src/zc/lockfile/tests.py 2007-07-18 11:24:02 UTC (rev 78102)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import os, sys, unittest
+from zope.testing import doctest
+
+import zc.lockfile, time, threading
+
+
+def inc():
+ while 1:
+ try:
+ lock = zc.lockfile.LockFile('f.lock')
+ except zc.lockfile.LockError:
+ continue
+ else:
+ break
+ f = open('f', 'r+b')
+ v = int(f.readline().strip())
+ time.sleep(0.01)
+ v += 1
+ f.seek(0)
+ f.write('%d\n' % v)
+ f.close()
+ lock.close()
+
+def many_threads_read_and_write():
+ r"""
+ >>> open('f', 'w+b').write('0\n')
+ >>> open('f.lock', 'w+b').write('0\n')
+
+ >>> n = 50
+ >>> threads = [threading.Thread(target=inc) for i in range(n)]
+ >>> _ = [thread.start() for thread in threads]
+ >>> _ = [thread.join() for thread in threads]
+ >>> saved = int(open('f', 'rb').readline().strip())
+ >>> saved == n
+ True
+
+ >>> os.remove('f')
+ >>> os.remove('f.lock')
+ """
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(doctest.DocFileSuite('README.txt'))
+ suite.addTest(doctest.DocTestSuite())
+ return suite
More information about the Checkins
mailing list