Commit dee9727e authored by Jim Fulton's avatar Jim Fulton

Removed the ZODB.lock_file module. Now depend on zc.lockfile instead.

parent e6b642a6
......@@ -267,6 +267,7 @@ setup(name="ZODB3",
'ZConfig',
'zdaemon',
'transaction',
'zc.lockfile',
],
zip_safe = False,
entry_points = """
......
......@@ -71,6 +71,8 @@ New Features
- Removed the ThreadedAsync module.
- Now depend on zc.lockfile
Bugs Fixed
----------
......
......@@ -40,7 +40,7 @@ from ZEO.auth import get_module
from ZEO.zrpc.client import ConnectionManager
import ZODB.interfaces
import ZODB.lock_file
import zc.lockfile
import ZODB.BaseStorage
from ZODB import POSException
from ZODB import utils
......@@ -931,8 +931,8 @@ class ClientStorage(object):
lockfilename = blob_filename+'.lock'
try:
lock = ZODB.lock_file.LockFile(lockfilename)
except ZODB.lock_file.LockError:
lock = zc.lockfile.LockFile(lockfilename)
except zc.lockfile.LockError:
# Someone is already downloading the Blob. Wait for the
# lock to be freed. How long should we be willing to wait?
......@@ -941,8 +941,8 @@ class ClientStorage(object):
while 1:
time.sleep(0.1)
try:
lock = ZODB.lock_file.LockFile(lockfilename)
except ZODB.lock_file.LockError:
lock = zc.lockfile.LockFile(lockfilename)
except zc.lockfile.LockError:
pass
else:
# We have the lock. We should be able to get the file now.
......
......@@ -34,7 +34,7 @@ import threading
import time
import ZODB.fsIndex
import ZODB.lock_file
import zc.lockfile
from ZODB.utils import p64, u64, z64
logger = logging.getLogger("ZEO.cache")
......@@ -181,7 +181,7 @@ class ClientCache(object):
# (and it sets self.f).
if path:
self._lock_file = ZODB.lock_file.LockFile(path + '.lock')
self._lock_file = zc.lockfile.LockFile(path + '.lock')
if path and os.path.exists(path):
# Reuse an existing file. scan() will open & read it.
......
......@@ -34,7 +34,7 @@ import ZODB.interfaces
from ZODB import BaseStorage, ConflictResolution, POSException
from ZODB.POSException import UndoError, POSKeyError, MultipleUndoErrors
from persistent.TimeStamp import TimeStamp
from ZODB.lock_file import LockFile
from zc.lockfile import LockFile
from ZODB.utils import p64, u64, cp, z64
from ZODB.FileStorage.fspack import FileStoragePacker
from ZODB.FileStorage.format import FileStorageFormatter, DataHeader
......
##############################################################################
#
# 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 lock a file
"""
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
# This is a better interface to use than the lockfile.lock_file() interface.
# Creating the instance acquires the lock. The file remains open. Calling
# close both closes and unlocks the lock file.
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()
if not pid:
pid = 'UNKNOWN'
logger.exception("Error locking file %s; pid=%s", 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
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 ZODB.lock_file
>>> lock = ZODB.lock_file.LockFile('lock')
If we try to lock the same name, we'll get a lock error and it will be logged:
>>> import ZODB.tests.loggingsupport
>>> handler = ZODB.tests.loggingsupport.InstalledHandler('ZODB.lock_file')
>>> try:
... ZODB.lock_file.LockFile('lock')
... except ZODB.lock_file.LockError:
... print "Can't lock file"
Can't lock file
>>> for record in handler.records:
... print record.levelname, record.getMessage()
ERROR Error locking file lock; pid=UNKNOWN
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 = ZODB.lock_file.LockFile('lock')
>>> lock.close()
##############################################################################
#
# 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 ZODB.lock_file, time, threading
def inc():
while 1:
try:
lock = ZODB.lock_file.LockFile('f.lock')
except ZODB.lock_file.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(os.path.join('..', 'lock_file.txt')))
suite.addTest(doctest.DocTestSuite())
return suite
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment