class MasterLock::Registry

When MasterLock acquires a lock, it registers it with a global registry. MasterLock will periodically renew all locks that are registered as long as the thread that acquired the lock is still alive and has not explicitly released the lock yet. If there is a failure to renew the lock, MasterLock identifies the lock as having already been released.

Constants

Registration

Attributes

locks[R]

@return [Array<Registration>] currently registered locks

Public Class Methods

new() click to toggle source
# File lib/master_lock/registry.rb, line 20
def initialize
  @locks = []
  @locks_mutex = Mutex.new
end

Public Instance Methods

extend_locks() click to toggle source

Extend all currently registered locks that have been held longer than the extend_interval since they were last acquired/extended. If any locks have expired (should not happen), it will release them.

# File lib/master_lock/registry.rb, line 58
def extend_locks
  # Make a local copy of the locks array to avoid accessing it outside of the mutex.
  locks_copy = @locks_mutex.synchronize { locks.dup }
  locks_copy.each { |registration| extend_lock(registration) }
  @locks_mutex.synchronize do
    locks.delete_if(&:released)
  end
end
register(lock, extend_interval) click to toggle source

Register a lock to be renewed every extend_interval seconds.

@param lock [#extend] a currently held lock that can be extended @param extend_interval [Fixnum] the interval in seconds after before the

lock is extended

@return [Registration] the receipt of registration

# File lib/master_lock/registry.rb, line 31
def register(lock, extend_interval)
  registration = Registration.new
  registration.lock = lock
  registration.mutex = Mutex.new
  registration.thread = Thread.current
  registration.acquired_at = Time.now
  registration.extend_interval = extend_interval
  registration.released = false
  @locks_mutex.synchronize do
    locks << registration
  end
  registration
end
unregister(registration) click to toggle source

Unregister a lock that has been registered.

@param registration [Registration] the registration returned by the call

to {#register}
# File lib/master_lock/registry.rb, line 49
def unregister(registration)
  registration.mutex.synchronize do
    registration.released = true
  end
end

Private Instance Methods

extend_lock(registration) click to toggle source
# File lib/master_lock/registry.rb, line 69
def extend_lock(registration)
  registration.mutex.synchronize do
    time = Time.now
    lock_key = registration.lock.key
    if !registration.thread.alive?
      registration.released = true
      MasterLock.logger.info(
        "Releasing lock #{lock_key} after owning thread terminated"
      )
    elsif !registration.released &&
        registration.acquired_at + registration.extend_interval < time
      lock_key = registration.lock.key
      if registration.lock.extend
        registration.acquired_at = time
        MasterLock.logger.debug("Renewed lease on lock #{lock_key}")
      else
        registration.released = true
        MasterLock.logger.warn("Could not renew lease on lock #{lock_key}")
      end
    end
  end
end