From 9c8e46dc228e096a83a892e5f53424bb3446d8f6 Mon Sep 17 00:00:00 2001 From: Gregory Becker Date: Thu, 3 Sep 2015 09:21:19 -0700 Subject: Added conservative locking to the spack commands that access the database at _index --- lib/spack/spack/cmd/__init__.py | 22 +++++++------- lib/spack/spack/cmd/deactivate.py | 12 ++++---- lib/spack/spack/cmd/diy.py | 60 ++++++++++++++++++++------------------- lib/spack/spack/cmd/extensions.py | 4 ++- lib/spack/spack/cmd/find.py | 7 +++-- lib/spack/spack/cmd/install.py | 22 +++++++------- lib/spack/spack/cmd/uninstall.py | 52 +++++++++++++++++---------------- lib/spack/spack/database.py | 11 ++++--- 8 files changed, 104 insertions(+), 86 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py index fd3ef3ed27..c62d22979a 100644 --- a/lib/spack/spack/cmd/__init__.py +++ b/lib/spack/spack/cmd/__init__.py @@ -28,6 +28,7 @@ import sys import llnl.util.tty as tty from llnl.util.lang import attr_setdefault +from llnl.util.lock import * import spack import spack.spec @@ -124,15 +125,16 @@ def elide_list(line_list, max_num=10): def disambiguate_spec(spec): - matching_specs = spack.installed_db.get_installed(spec) - if not matching_specs: - tty.die("Spec '%s' matches no installed packages." % spec) - - elif len(matching_specs) > 1: - args = ["%s matches multiple packages." % spec, - "Matching packages:"] - args += [" " + str(s) for s in matching_specs] - args += ["Use a more specific spec."] - tty.die(*args) + with Read_Lock_Instance(spack.installed_db.lock,1800): + matching_specs = spack.installed_db.get_installed(spec) + if not matching_specs: + tty.die("Spec '%s' matches no installed packages." % spec) + + elif len(matching_specs) > 1: + args = ["%s matches multiple packages." % spec, + "Matching packages:"] + args += [" " + str(s) for s in matching_specs] + args += ["Use a more specific spec."] + tty.die(*args) return matching_specs[0] diff --git a/lib/spack/spack/cmd/deactivate.py b/lib/spack/spack/cmd/deactivate.py index 1f0e303cdf..015809345a 100644 --- a/lib/spack/spack/cmd/deactivate.py +++ b/lib/spack/spack/cmd/deactivate.py @@ -24,6 +24,7 @@ ############################################################################## from external import argparse import llnl.util.tty as tty +from llnl.util.lock import * import spack import spack.cmd @@ -54,12 +55,13 @@ def deactivate(parser, args): if args.all: if pkg.extendable: tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec) - ext_pkgs = spack.installed_db.installed_extensions_for(spec) + with Read_Lock_Instance(spack.installed_db.lock,1800): + ext_pkgs = spack.installed_db.installed_extensions_for(spec) - for ext_pkg in ext_pkgs: - ext_pkg.spec.normalize() - if ext_pkg.activated: - ext_pkg.do_deactivate(force=True) + for ext_pkg in ext_pkgs: + ext_pkg.spec.normalize() + if ext_pkg.activated: + ext_pkg.do_deactivate(force=True) elif pkg.is_extension: if not args.force and not spec.package.activated: diff --git a/lib/spack/spack/cmd/diy.py b/lib/spack/spack/cmd/diy.py index 6e7f10fba6..7403b9e3e8 100644 --- a/lib/spack/spack/cmd/diy.py +++ b/lib/spack/spack/cmd/diy.py @@ -27,6 +27,7 @@ import os from external import argparse import llnl.util.tty as tty +from llnl.util.lock import * import spack import spack.cmd @@ -54,40 +55,41 @@ def diy(self, args): if not args.spec: tty.die("spack diy requires a package spec argument.") - specs = spack.cmd.parse_specs(args.spec) - if len(specs) > 1: - tty.die("spack diy only takes one spec.") + with Write_Lock_Instance(spack.installed_db.lock,1800): + specs = spack.cmd.parse_specs(args.spec) + if len(specs) > 1: + tty.die("spack diy only takes one spec.") - spec = specs[0] - if not spack.db.exists(spec.name): - tty.warn("No such package: %s" % spec.name) - create = tty.get_yes_or_no("Create this package?", default=False) - if not create: - tty.msg("Exiting without creating.") - sys.exit(1) - else: - tty.msg("Running 'spack edit -f %s'" % spec.name) - edit_package(spec.name, True) - return + spec = specs[0] + if not spack.db.exists(spec.name): + tty.warn("No such package: %s" % spec.name) + create = tty.get_yes_or_no("Create this package?", default=False) + if not create: + tty.msg("Exiting without creating.") + sys.exit(1) + else: + tty.msg("Running 'spack edit -f %s'" % spec.name) + edit_package(spec.name, True) + return - if not spec.version.concrete: - tty.die("spack diy spec must have a single, concrete version.") + if not spec.version.concrete: + tty.die("spack diy spec must have a single, concrete version.") - spec.concretize() - package = spack.db.get(spec) + spec.concretize() + package = spack.db.get(spec) - if package.installed: - tty.error("Already installed in %s" % package.prefix) - tty.msg("Uninstall or try adding a version suffix for this DIY build.") - sys.exit(1) + if package.installed: + tty.error("Already installed in %s" % package.prefix) + tty.msg("Uninstall or try adding a version suffix for this DIY build.") + sys.exit(1) - # Forces the build to run out of the current directory. - package.stage = DIYStage(os.getcwd()) + # Forces the build to run out of the current directory. + package.stage = DIYStage(os.getcwd()) # TODO: make this an argument, not a global. - spack.do_checksum = False + spack.do_checksum = False - package.do_install( - keep_prefix=args.keep_prefix, - ignore_deps=args.ignore_deps, - keep_stage=True) # don't remove source dir for DIY. + package.do_install( + keep_prefix=args.keep_prefix, + ignore_deps=args.ignore_deps, + keep_stage=True) # don't remove source dir for DIY. diff --git a/lib/spack/spack/cmd/extensions.py b/lib/spack/spack/cmd/extensions.py index e919b1c4fb..66211e29a9 100644 --- a/lib/spack/spack/cmd/extensions.py +++ b/lib/spack/spack/cmd/extensions.py @@ -27,6 +27,7 @@ from external import argparse import llnl.util.tty as tty from llnl.util.tty.colify import colify +from llnl.util.lock import * import spack import spack.cmd @@ -80,7 +81,8 @@ def extensions(parser, args): colify(ext.name for ext in extensions) # List specs of installed extensions. - installed = [s.spec for s in spack.installed_db.installed_extensions_for(spec)] + with Read_Lock_Instance(spack.installed_db.lock,1800): + installed = [s.spec for s in spack.installed_db.installed_extensions_for(spec)] print if not installed: tty.msg("None installed.") diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index 6f9072e311..f7fa409ebb 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -32,6 +32,7 @@ import llnl.util.tty as tty 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 @@ -138,9 +139,11 @@ def find(parser, args): # Get all the specs the user asked for if not query_specs: - specs = set(spack.installed_db.installed_package_specs()) + with Read_Lock_Instance(spack.installed_db.lock,1800): + specs = set(spack.installed_db.installed_package_specs()) else: - results = [set(spack.installed_db.get_installed(qs)) for qs in query_specs] + with Read_Lock_Instance(spack.installed_db.lock,1800): + results = [set(spack.installed_db.get_installed(qs)) for qs in query_specs] specs = set.union(*results) if not args.mode: diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py index acb688a092..330774b8d9 100644 --- a/lib/spack/spack/cmd/install.py +++ b/lib/spack/spack/cmd/install.py @@ -25,6 +25,7 @@ from external import argparse import llnl.util.tty as tty +from llnl.util.lock import * import spack import spack.cmd @@ -68,13 +69,14 @@ def install(parser, args): if args.no_checksum: spack.do_checksum = False # TODO: remove this global. - specs = spack.cmd.parse_specs(args.packages, concretize=True) - for spec in specs: - package = spack.db.get(spec) - package.do_install( - keep_prefix=args.keep_prefix, - keep_stage=args.keep_stage, - ignore_deps=args.ignore_deps, - make_jobs=args.jobs, - verbose=args.verbose, - fake=args.fake) + with Write_Lock_Instance(spack.installed_db.lock,1800): + specs = spack.cmd.parse_specs(args.packages, concretize=True) + for spec in specs: + package = spack.db.get(spec) + package.do_install( + keep_prefix=args.keep_prefix, + keep_stage=args.keep_stage, + ignore_deps=args.ignore_deps, + make_jobs=args.jobs, + verbose=args.verbose, + fake=args.fake) diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py index 4870712eb6..4b0267dac2 100644 --- a/lib/spack/spack/cmd/uninstall.py +++ b/lib/spack/spack/cmd/uninstall.py @@ -27,6 +27,7 @@ from external import argparse import llnl.util.tty as tty from llnl.util.tty.colify import colify +from llnl.util.lock import * import spack import spack.cmd @@ -53,35 +54,36 @@ def uninstall(parser, args): if not args.packages: tty.die("uninstall requires at least one package argument.") - specs = spack.cmd.parse_specs(args.packages) + with Write_Lock_Instance(spack.installed_db.lock,1800): + specs = spack.cmd.parse_specs(args.packages) - # For each spec provided, make sure it refers to only one package. - # Fail and ask user to be unambiguous if it doesn't - pkgs = [] - for spec in specs: - matching_specs = spack.installed_db.get_installed(spec) - if not args.all and len(matching_specs) > 1: - tty.error("%s matches multiple packages:" % spec) - print - display_specs(matching_specs, long=True) - print - print "You can either:" - print " a) Use a more specific spec, or" - print " b) use spack uninstall -a to uninstall ALL matching specs." - sys.exit(1) + # For each spec provided, make sure it refers to only one package. + # Fail and ask user to be unambiguous if it doesn't + pkgs = [] + for spec in specs: + matching_specs = spack.installed_db.get_installed(spec) + if not args.all and len(matching_specs) > 1: + tty.error("%s matches multiple packages:" % spec) + print + display_specs(matching_specs, long=True) + print + print "You can either:" + print " a) Use a more specific spec, or" + print " b) use spack uninstall -a to uninstall ALL matching specs." + sys.exit(1) - if len(matching_specs) == 0: - if args.force: continue - tty.die("%s does not match any installed packages." % spec) + if len(matching_specs) == 0: + if args.force: continue + tty.die("%s does not match any installed packages." % spec) - for s in matching_specs: - try: - # should work if package is known to spack - pkgs.append(s.package) + for s in matching_specs: + try: + # should work if package is known to spack + pkgs.append(s.package) - except spack.packages.UnknownPackageError, e: - # The package.py file has gone away -- but still want to uninstall. - spack.Package(s).do_uninstall(force=True) + except spack.packages.UnknownPackageError, e: + # The package.py file has gone away -- but still want to uninstall. + spack.Package(s).do_uninstall(force=True) # Sort packages to be uninstalled by the number of installed dependents # This ensures we do things in the right order diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py index 6a429b68a9..9b759827d3 100644 --- a/lib/spack/spack/database.py +++ b/lib/spack/spack/database.py @@ -158,12 +158,12 @@ class Database(object): within the same lock, so there is no need to refresh the database within write() """ - temp_name = os.getpid() + socket.getfqdn() + ".temp" - temp_file = path.join(self._root,temp_name) - with open(self.temp_path,'w') as f: + temp_name = str(os.getpid()) + socket.getfqdn() + ".temp" + temp_file = join_path(self._root,temp_name) + with open(temp_file,'w') as f: self._last_write_time = int(time.time()) self._write_database_to_yaml(f) - os.rename(temp_name,self._file_path) + os.rename(temp_file,self._file_path) def is_dirty(self): """ @@ -184,6 +184,7 @@ class Database(object): sph['path']=path sph['hash']=spec.dag_hash() + #Should always already be locked with Write_Lock_Instance(self.lock,60): self.read_database() self._data.append(sph) @@ -197,6 +198,7 @@ class Database(object): Searches for and removes the specified spec Writes the database back to memory """ + #Should always already be locked with Write_Lock_Instance(self.lock,60): self.read_database() @@ -237,6 +239,7 @@ class Database(object): Read installed package names from the database and return their specs """ + #Should always already be locked with Read_Lock_Instance(self.lock,60): self.read_database() -- cgit v1.2.3-70-g09d2