"spack commands --update-completion"

This commit is contained in:
John Parent
2022-01-24 14:35:44 -05:00
committed by Peter Scheibel
parent e4d4a5193f
commit cf1349ba35
105 changed files with 691 additions and 1065 deletions

View File

@@ -4,9 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import errno
import fcntl
import os
import socket
import sys
import time
from datetime import datetime
from typing import Dict, Tuple # novm
@@ -15,6 +15,10 @@
import spack.util.string
if sys.platform != 'win32':
import fcntl
__all__ = [
'Lock',
'LockDowngradeError',
@@ -29,8 +33,6 @@
'CantCreateLockError'
]
#: Mapping of supported locks to description
lock_type = {fcntl.LOCK_SH: 'read', fcntl.LOCK_EX: 'write'}
#: A useful replacement for functions that should return True when not provided
#: for example.
@@ -166,6 +168,29 @@ def _attempts_str(wait_time, nattempts):
return ' after {0:0.2f}s and {1}'.format(wait_time, attempts)
class LockType(object):
READ = 0
WRITE = 1
@staticmethod
def to_str(tid):
ret = "READ"
if tid == LockType.WRITE:
ret = "WRITE"
return ret
@staticmethod
def to_module(tid):
lock = fcntl.LOCK_SH
if tid == LockType.WRITE:
lock = fcntl.LOCK_EX
return lock
@staticmethod
def is_valid(op):
return op == LockType.READ \
or op == LockType.WRITE
class Lock(object):
"""This is an implementation of a filesystem lock using Python's lockf.
@@ -276,9 +301,10 @@ def _lock(self, op, timeout=None):
successfully acquired, the total wait time and the number of attempts
is returned.
"""
assert op in lock_type
assert LockType.is_valid(op)
op_str = LockType.to_str(op)
self._log_acquiring('{0} LOCK'.format(lock_type[op].upper()))
self._log_acquiring('{0} LOCK'.format(op_str))
timeout = timeout or self.default_timeout
# Create file and parent directories if they don't exist.
@@ -286,13 +312,13 @@ def _lock(self, op, timeout=None):
self._ensure_parent_directory()
self._file = file_tracker.get_fh(self.path)
if op == fcntl.LOCK_EX and self._file.mode == 'r':
if LockType.to_module(op) == fcntl.LOCK_EX and self._file.mode == 'r':
# Attempt to upgrade to write lock w/a read-only file.
# If the file were writable, we'd have opened it 'r+'
raise LockROFileError(self.path)
self._log_debug("{0} locking [{1}:{2}]: timeout {3} sec"
.format(lock_type[op], self._start, self._length,
.format(op_str.lower(), self._start, self._length,
timeout))
poll_intervals = iter(Lock._poll_interval_generator())
@@ -313,17 +339,16 @@ def _lock(self, op, timeout=None):
return total_wait_time, num_attempts
raise LockTimeoutError("Timed out waiting for a {0} lock."
.format(lock_type[op]))
.format(op_str.lower()))
def _poll_lock(self, op):
"""Attempt to acquire the lock in a non-blocking manner. Return whether
the locking attempt succeeds
"""
assert op in lock_type
module_op = LockType.to_module(op)
try:
# Try to get the lock (will raise if not available.)
fcntl.lockf(self._file, op | fcntl.LOCK_NB,
fcntl.lockf(self._file, module_op | fcntl.LOCK_NB,
self._length, self._start, os.SEEK_SET)
# help for debugging distributed locking
@@ -331,11 +356,11 @@ def _poll_lock(self, op):
# All locks read the owner PID and host
self._read_log_debug_data()
self._log_debug('{0} locked {1} [{2}:{3}] (owner={4})'
.format(lock_type[op], self.path,
.format(LockType.to_str(op), self.path,
self._start, self._length, self.pid))
# Exclusive locks write their PID/host
if op == fcntl.LOCK_EX:
if module_op == fcntl.LOCK_EX:
self._write_log_debug_data()
return True
@@ -420,7 +445,7 @@ def acquire_read(self, timeout=None):
if self._reads == 0 and self._writes == 0:
# can raise LockError.
wait_time, nattempts = self._lock(fcntl.LOCK_SH, timeout=timeout)
wait_time, nattempts = self._lock(LockType.READ, timeout=timeout)
self._reads += 1
# Log if acquired, which includes counts when verbose
self._log_acquired('READ LOCK', wait_time, nattempts)
@@ -445,7 +470,7 @@ def acquire_write(self, timeout=None):
if self._writes == 0:
# can raise LockError.
wait_time, nattempts = self._lock(fcntl.LOCK_EX, timeout=timeout)
wait_time, nattempts = self._lock(LockType.WRITE, timeout=timeout)
self._writes += 1
# Log if acquired, which includes counts when verbose
self._log_acquired('WRITE LOCK', wait_time, nattempts)
@@ -489,7 +514,7 @@ def downgrade_write_to_read(self, timeout=None):
if self._writes == 1 and self._reads == 0:
self._log_downgrading()
# can raise LockError.
wait_time, nattempts = self._lock(fcntl.LOCK_SH, timeout=timeout)
wait_time, nattempts = self._lock(LockType.READ, timeout=timeout)
self._reads = 1
self._writes = 0
self._log_downgraded(wait_time, nattempts)
@@ -508,7 +533,7 @@ def upgrade_read_to_write(self, timeout=None):
if self._reads == 1 and self._writes == 0:
self._log_upgrading()
# can raise LockError.
wait_time, nattempts = self._lock(fcntl.LOCK_EX, timeout=timeout)
wait_time, nattempts = self._lock(LockType.WRITE, timeout=timeout)
self._reads = 0
self._writes = 1
self._log_upgraded(wait_time, nattempts)