Several changes to DB implementation.

1. Database stores a file version, so we can add to it in the future.
2. Database indexed by hashes and not numerical indexes.
3. Specs built by database have consistent hashes and it's checked.
4. minor naming and whitespace changes.
This commit is contained in:
Todd Gamblin
2015-09-17 00:16:12 -07:00
parent cd23d2eaa2
commit ccf311c9c6
6 changed files with 220 additions and 139 deletions

View File

@@ -222,7 +222,7 @@ def working_dir(dirname, **kwargs):
def touch(path):
"""Creates an empty file at the specified path."""
with closing(open(path, 'a')) as file:
with open(path, 'a') as file:
os.utime(path, None)

View File

@@ -22,6 +22,7 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
"""Lock implementation for shared filesystems."""
import os
import fcntl
import errno
@@ -34,11 +35,13 @@ class Read_Lock_Instance(object):
A context manager for getting shared access to the object lock
Arguments are lock and timeout (default 5 minutes)
"""
def __init__(self,lock,timeout = 300):
def __init__(self, lock, timeout=300):
self._lock = lock
self._timeout = timeout
def __enter__(self):
self._lock.acquire_read(self._timeout)
def __exit__(self,type,value,traceback):
self._lock.release_read()
@@ -48,17 +51,21 @@ class Write_Lock_Instance(object):
A context manager for getting exclusive access to the object lock
Arguments are lock and timeout (default 5 minutes)
"""
def __init__(self,lock,timeout = 300):
def __init__(self, lock, timeout=300):
self._lock = lock
self._timeout = timeout
def __enter__(self):
self._lock.acquire_write(self._timeout)
def __exit__(self,type,value,traceback):
self._lock.release_write()
class Lock(object):
def __init__(self,file_path):
"""Distributed file-based lock using ``flock``."""
def __init__(self, file_path):
self._file_path = file_path
self._fd = os.open(file_path,os.O_RDWR)
self._reads = 0
@@ -71,20 +78,20 @@ def acquire_read(self,timeout):
the write lock will be maintained until all locks are released
"""
if self._reads == 0 and self._writes == 0:
self._lock(fcntl.LOCK_SH,timeout)
self._lock(fcntl.LOCK_SH, timeout)
self._reads += 1
def acquire_write(self,timeout):
def acquire_write(self, timeout):
"""
Implements recursive lock
"""
if self._writes == 0:
self._lock(fcntl.LOCK_EX,timeout)
self._lock(fcntl.LOCK_EX, timeout)
self._writes += 1
def _lock(self,op,timeout):
def _lock(self, op, timeout):
"""
The timeout is implemented using nonblocking flock()
to avoid using signals for timing
@@ -96,8 +103,8 @@ def _lock(self,op,timeout):
try:
fcntl.flock(self._fd, op | fcntl.LOCK_NB)
if op == fcntl.LOCK_EX:
with open(self._file_path,'w') as f:
f.write("pid = "+str(os.getpid())+", host = "+socket.getfqdn())
with open(self._file_path, 'w') as f:
f.write("pid = " + str(os.getpid()) + ", host = " + socket.getfqdn())
return
except IOError as error:
if error.errno == errno.EAGAIN or error.errno == EACCES:
@@ -133,4 +140,4 @@ def _unlock(self):
Releases the lock regardless of mode. Note that read locks may be
masquerading as write locks at times, but this removes either.
"""
fcntl.flock(self._fd,fcntl.LOCK_UN)
fcntl.flock(self._fd, fcntl.LOCK_UN)