Simplify lock context managers.

This commit is contained in:
Todd Gamblin 2015-09-17 01:05:19 -07:00
parent ccf311c9c6
commit e17ad6a684
10 changed files with 49 additions and 43 deletions

View file

@ -29,13 +29,15 @@
import time
import socket
# Default timeout for locks.
DEFAULT_TIMEOUT = 60
class _ReadLockContext(object):
"""Context manager that takes and releases a read lock.
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=DEFAULT_TIMEOUT):
self._lock = lock
self._timeout = timeout
@ -46,12 +48,12 @@ def __exit__(self,type,value,traceback):
self._lock.release_read()
class Write_Lock_Instance(object):
"""
A context manager for getting exclusive access to the object lock
class _WriteLockContext(object):
"""Context manager that takes and releases a write lock.
Arguments are lock and timeout (default 5 minutes)
"""
def __init__(self, lock, timeout=300):
def __init__(self, lock, timeout=DEFAULT_TIMEOUT):
self._lock = lock
self._timeout = timeout
@ -72,7 +74,17 @@ def __init__(self, file_path):
self._writes = 0
def acquire_read(self,timeout):
def write_lock(self, timeout=DEFAULT_TIMEOUT):
"""Convenience method that returns a write lock context."""
return _WriteLockContext(self, timeout)
def read_lock(self, timeout=DEFAULT_TIMEOUT):
"""Convenience method that returns a read lock context."""
return _ReadLockContext(self, timeout)
def acquire_read(self, timeout):
"""
Implements recursive lock. If held in both read and write mode,
the write lock will be maintained until all locks are released

View file

@ -28,7 +28,6 @@
import llnl.util.tty as tty
from llnl.util.lang import attr_setdefault
from llnl.util.lock import *
import spack
import spack.spec
@ -125,7 +124,7 @@ def elide_list(line_list, max_num=10):
def disambiguate_spec(spec):
with Read_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.read_lock():
matching_specs = spack.installed_db.get_installed(spec)
if not matching_specs:
tty.die("Spec '%s' matches no installed packages." % spec)

View file

@ -24,7 +24,6 @@
##############################################################################
from external import argparse
import llnl.util.tty as tty
from llnl.util.lock import *
import spack
import spack.cmd
@ -55,7 +54,7 @@ def deactivate(parser, args):
if args.all:
if pkg.extendable:
tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec)
with Read_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.read_lock():
ext_pkgs = spack.installed_db.installed_extensions_for(spec)
for ext_pkg in ext_pkgs:

View file

@ -27,7 +27,6 @@
from external import argparse
import llnl.util.tty as tty
from llnl.util.lock import *
import spack
import spack.cmd
@ -55,7 +54,7 @@ def diy(self, args):
if not args.spec:
tty.die("spack diy requires a package spec argument.")
with Write_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.write_lock():
specs = spack.cmd.parse_specs(args.spec)
if len(specs) > 1:
tty.die("spack diy only takes one spec.")

View file

@ -27,7 +27,6 @@
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
from llnl.util.lock import *
import spack
import spack.cmd
@ -81,7 +80,7 @@ def extensions(parser, args):
colify(ext.name for ext in extensions)
# List specs of installed extensions.
with Read_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.read_lock():
installed = [s.spec for s in spack.installed_db.installed_extensions_for(spec)]
print
if not installed:

View file

@ -32,7 +32,6 @@
from llnl.util.tty.colify import *
from llnl.util.tty.color import *
from llnl.util.lang import *
from llnl.util.lock import *
import spack
import spack.spec
@ -139,11 +138,11 @@ def find(parser, args):
# Get all the specs the user asked for
if not query_specs:
with Read_Lock_Instance(spack.installed_db.lock, 1800):
with spack.installed_db.read_lock():
specs = set(spack.installed_db.installed_package_specs())
else:
with Read_Lock_Instance(spack.installed_db.lock, 1800):
with spack.installed_db.read_lock():
results = [set(spack.installed_db.get_installed(qs)) for qs in query_specs]
specs = set.union(*results)

View file

@ -1,5 +1,5 @@
##############################################################################
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
# Copyright (c) 2013-2015, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
@ -23,21 +23,10 @@
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from external import argparse
from llnl.util.lock import *
import spack
import os
description = "Correct database irregularities"
#Very basic version of spack fsck
# Very basic version of spack fsck
def fsck(parser, args):
with Write_Lock_Instance(spack.installed_db.lock,1800):
#remove database file
if os.path.exists(spack.installed_db._file_path):
os.remove(spack.installed_db._file_path)
#read database
spack.installed_db.read_database()
#write database
spack.installed_db.write()
spack.installed_db.reindex(spack.install_layout)

View file

@ -25,7 +25,6 @@
from external import argparse
import llnl.util.tty as tty
from llnl.util.lock import *
import spack
import spack.cmd
@ -69,7 +68,7 @@ def install(parser, args):
if args.no_checksum:
spack.do_checksum = False # TODO: remove this global.
with Write_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.write_lock():
specs = spack.cmd.parse_specs(args.packages, concretize=True)
for spec in specs:
package = spack.db.get(spec)

View file

@ -27,7 +27,6 @@
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
from llnl.util.lock import *
import spack
import spack.cmd
@ -54,7 +53,7 @@ def uninstall(parser, args):
if not args.packages:
tty.die("uninstall requires at least one package argument.")
with Write_Lock_Instance(spack.installed_db.lock,1800):
with spack.installed_db.write_lock():
specs = spack.cmd.parse_specs(args.packages)
# For each spec provided, make sure it refers to only one package.

View file

@ -24,13 +24,14 @@
##############################################################################
import os
import time
import socket
from external import yaml
from external.yaml.error import MarkedYAMLError, YAMLError
import llnl.util.tty as tty
from llnl.util.filesystem import *
from llnl.util.lock import *
from llnl.util.lock import Lock
import spack.spec
from spack.version import Version
@ -99,6 +100,16 @@ def __init__(self, root):
self._last_write_time = 0
def write_lock(self):
"""Get a write lock context for use in a `with` block."""
return self.lock.write_lock()
def read_lock(self):
"""Get a read lock context for use in a `with` block."""
return self.lock.read_lock()
def _write_to_yaml(self, stream):
"""Write out the databsae to a YAML file."""
# map from per-spec hash code to installation record.
@ -198,13 +209,14 @@ def check(cond, msg):
def reindex(self, directory_layout):
"""Build database index from scratch based from a directory layout."""
with Write_Lock_Instance(self.lock, 60):
with self.write_lock():
data = {}
for spec in directory_layout.all_specs():
path = directory_layout.path_for_spec(spec)
hash_key = spec.dag_hash()
data[hash_key] = InstallRecord(spec, path)
self._data = data
self.write()
@ -264,7 +276,7 @@ def add(self, spec, path):
Write the database back to memory
"""
# Should always already be locked
with Write_Lock_Instance(self.lock, 60):
with self.write_lock():
self.read()
self._data[spec.dag_hash()] = InstallRecord(spec, path)
self.write()
@ -278,7 +290,7 @@ def remove(self, spec):
Writes the database back to memory
"""
# Should always already be locked
with Write_Lock_Instance(self.lock, 60):
with self.write_lock():
self.read()
hash_key = spec.dag_hash()
if hash_key in self._data:
@ -314,7 +326,7 @@ def installed_package_specs(self):
and return their specs
"""
# Should always already be locked
with Read_Lock_Instance(self.lock, 60):
with self.read_lock():
self.read()
return sorted(rec.spec for rec in self._data.values())