summaryrefslogtreecommitdiff
path: root/lib/spack/llnl/util
diff options
context:
space:
mode:
authorHarmen Stoppels <harmenstoppels@gmail.com>2022-10-24 11:54:49 +0200
committerGitHub <noreply@github.com>2022-10-24 11:54:49 +0200
commitd67b12eb7934637f119ed7ad6f80f3d5f574895b (patch)
tree1af6dba5eb03d60780ca923308fac9365eaabd6f /lib/spack/llnl/util
parent7d99fbcafd4720babe2a0d325df099ed9056f5e1 (diff)
downloadspack-d67b12eb7934637f119ed7ad6f80f3d5f574895b.tar.gz
spack-d67b12eb7934637f119ed7ad6f80f3d5f574895b.tar.bz2
spack-d67b12eb7934637f119ed7ad6f80f3d5f574895b.tar.xz
spack-d67b12eb7934637f119ed7ad6f80f3d5f574895b.zip
locks: improved errors (#33477)
Instead of showing ``` ==> Error: Timed out waiting for a write lock. ``` show ``` ==> Error: Timed out waiting for a write lock after 1.200ms and 4 attempts on file: /some/file ``` s.t. we actually get to see where acquiring a lock failed even when not running in debug mode. And use pretty time units everywhere, so we don't get 1.45e-9 seconds but 1.450ns etc.
Diffstat (limited to 'lib/spack/llnl/util')
-rw-r--r--lib/spack/llnl/util/lang.py20
-rw-r--r--lib/spack/llnl/util/lock.py22
2 files changed, 38 insertions, 4 deletions
diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py
index 76b161cbbe..f1a0b7ba31 100644
--- a/lib/spack/llnl/util/lang.py
+++ b/lib/spack/llnl/util/lang.py
@@ -749,6 +749,26 @@ def pretty_string_to_date(date_str, now=None):
raise ValueError(msg)
+def pretty_seconds(seconds):
+ """Seconds to string with appropriate units
+
+ Arguments:
+ seconds (float): Number of seconds
+
+ Returns:
+ str: Time string with units
+ """
+ if seconds >= 1:
+ value, unit = seconds, "s"
+ elif seconds >= 1e-3:
+ value, unit = seconds * 1e3, "ms"
+ elif seconds >= 1e-6:
+ value, unit = seconds * 1e6, "us"
+ else:
+ value, unit = seconds * 1e9, "ns"
+ return "%.3f%s" % (value, unit)
+
+
class RequiredAttributeError(ValueError):
def __init__(self, message):
super(RequiredAttributeError, self).__init__(message)
diff --git a/lib/spack/llnl/util/lock.py b/lib/spack/llnl/util/lock.py
index 6dfba50abb..9c3bcd7a91 100644
--- a/lib/spack/llnl/util/lock.py
+++ b/lib/spack/llnl/util/lock.py
@@ -12,6 +12,7 @@ from datetime import datetime
from typing import Dict, Tuple # novm
import llnl.util.tty as tty
+from llnl.util.lang import pretty_seconds
import spack.util.string
@@ -166,7 +167,7 @@ def _attempts_str(wait_time, nattempts):
return ""
attempts = spack.util.string.plural(nattempts, "attempt")
- return " after {0:0.2f}s and {1}".format(wait_time, attempts)
+ return " after {} and {}".format(pretty_seconds(wait_time), attempts)
class LockType(object):
@@ -318,8 +319,8 @@ class Lock(object):
raise LockROFileError(self.path)
self._log_debug(
- "{0} locking [{1}:{2}]: timeout {3} sec".format(
- op_str.lower(), self._start, self._length, timeout
+ "{} locking [{}:{}]: timeout {}".format(
+ op_str.lower(), self._start, self._length, pretty_seconds(timeout or 0)
)
)
@@ -340,7 +341,8 @@ class Lock(object):
total_wait_time = time.time() - start_time
return total_wait_time, num_attempts
- raise LockTimeoutError("Timed out waiting for a {0} lock.".format(op_str.lower()))
+ total_wait_time = time.time() - start_time
+ raise LockTimeoutError(op_str.lower(), self.path, total_wait_time, num_attempts)
def _poll_lock(self, op):
"""Attempt to acquire the lock in a non-blocking manner. Return whether
@@ -780,6 +782,18 @@ class LockLimitError(LockError):
class LockTimeoutError(LockError):
"""Raised when an attempt to acquire a lock times out."""
+ def __init__(self, lock_type, path, time, attempts):
+ fmt = "Timed out waiting for a {} lock after {}.\n Made {} {} on file: {}"
+ super(LockTimeoutError, self).__init__(
+ fmt.format(
+ lock_type,
+ pretty_seconds(time),
+ attempts,
+ "attempt" if attempts == 1 else "attempts",
+ path,
+ )
+ )
+
class LockUpgradeError(LockError):
"""Raised when unable to upgrade from a read to a write lock."""