If a client crashes while holding a lock, that lock is held forever and the whole system deadlocks. Real distributed locks are leases: they come with a TTL and expire on their own. A crashed holder's lock quietly frees itself.
With an injected clock, a lock is free when nobody holds it or the current holder's lease has expired.
acquire(name, client_id, ttl): acquire if free or the existing lease has expired; the new lease lasts ttl seconds.is_locked(name): is the lock currently held by a live (non-expired) lease?import time
class LockManager:
def __init__(self, clock=time.time):
self.clock = clock
self._locks = {} # name -> (client_id, expiry)
def acquire(self, name, client_id, ttl):
"""Acquire if free or the current lease has expired."""
now = self.clock()
cur = self._locks.get(name)
# TODO: cur holds the current (client_id, expiry) pair, or None when free.
# Take the lock when there is no holder, or when the stored expiry has
# already reached now, saving client_id with an expiry ttl seconds past
# now and answering True. A still live lease answers False untouched.
pass
def release(self, name, client_id):
cur = self._locks.get(name)
if cur and cur[0] == client_id:
del self._locks[name]
return True
return False
def is_locked(self, name):
"""True only if a live (non-expired) lease holds the lock."""
# TODO: fetch the self._locks entry for name and answer True only when
# one exists and its stored expiry is still strictly ahead of the
# current clock reading. Missing or expired both answer False.
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
If a client crashes while holding a lock, that lock is held forever and the whole system deadlocks. Real distributed locks are leases: they come with a TTL and expire on their own. A crashed holder's lock quietly frees itself.
With an injected clock, a lock is free when nobody holds it or the current holder's lease has expired.
acquire(name, client_id, ttl): acquire if free or the existing lease has expired; the new lease lasts ttl seconds.is_locked(name): is the lock currently held by a live (non-expired) lease?Press Run Tests or ββ© to check your solution.