instant.locking

Package instant :: Module locking |
[hide private]
[frames] | no frames]

# Source Code for Module instant.locking

     1  """File locking for the cache system, to avoid problems
     2  when multiple processes work with the same module.
     3  Only works on UNIX systems."""
     4
     5  import os.path
     6  from output import instant_error, instant_assert, instant_debug
     7  from paths import validate_cache_dir
     8
     9  try:
    10      import fcntl
    11  except:
    12      fcntl = None
    13
    14  # Keeping an overview of locks currently held,
    15  # to avoid deadlocks within a single process.
    16  _lock_names = {} # lock.fileno() -> lockname
    17  _lock_files = {} # lockname -> lock
    18  _lock_count = {} # lockname -> number of times this lock has been aquired and not yet released
    19
    20  if fcntl:
    21 -    def get_lock(cache_dir, module_name):
    22          "Get a new file lock."
    23          global _lock_names, _lock_files, _lock_count
    24
    25          lockname = module_name + ".lock"
    26          count = _lock_count.get(lockname, 0)
    27
    28          instant_debug("Acquiring lock %s, count is %d." % (lockname, count))
    29
    30          if count == 0:
    31              cache_dir = validate_cache_dir(cache_dir)
    32              lock = open(os.path.join(cache_dir, lockname), "w")
    33              fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
    34              _lock_names[lock.fileno()] = lockname
    35              _lock_files[lockname] = lock
    36          else:
    37              lock = _lock_files[lockname]
    38
    39          _lock_count[lockname] = count + 1
    40          return lock
    41
    42 -    def release_lock(lock):
    43          "Release a lock currently held by Instant."
    44          global _lock_names, _lock_files, _lock_count
    45
    46          lockname = _lock_names[lock.fileno()]
    47          count = _lock_count[lockname]
    48
    49          instant_debug("Releasing lock %s, count is %d." % (lockname, count))
    50
    51          instant_assert(count > 0, "Releasing lock that Instant is supposedly not holding.")
    52          instant_assert(lock is _lock_files[lockname], "Lock mismatch, might be something wrong in locking logic.")
    53
    54          del _lock_files[lockname]
    55          del _lock_names[lock.fileno()]
    56          _lock_count[lockname] = count - 1
    57
    58          fcntl.flock(lock.fileno(), fcntl.LOCK_UN)
    59          lock.close()
    60
    61 -    def release_all_locks():
    62          "Release all locks currently held by Instant."
    63          locks = _lock_files.values()
    64          for lock in locks:
    65              release_lock(lock)
    66          instant_assert(all(_lock_count[lockname] == 0 for lockname in _lock_count), "Lock counts not zero after releasing all locks.")
    67
    68  else:
    69      # Windows systems have no fcntl, implement these otherwise if locking is needed on windows
    70 -    def get_lock(cache_dir, module_name):
    71          return None
    72
    73 -    def release_lock(lock):
    74          pass
    75