// Attempts to claim a lock. If the overrideLock is set, any existing lock holder // will be destroyed and one more attempt will be made to acquire the lock func (r Replicator) lock(lock kp.Lock, lockPath string, overrideLock bool) error { err := lock.Lock(lockPath) if _, ok := err.(kp.AlreadyLockedError); ok { holder, id, err := r.Store.LockHolder(lockPath) if err != nil { return util.Errorf("Lock already held for %q, could not determine holder due to error: %s", lockPath, err) } else if holder == "" { // we failed to acquire this lock, but there is no outstanding // holder // this indicates that the previous holder had a LockDelay, // which prevents other parties from acquiring the lock for a // limited time return util.Errorf("Lock for %q is blocked due to delay by previous holder", lockPath) } else if overrideLock { err = r.Store.DestroyLockHolder(id) if err != nil { return util.Errorf("Unable to destroy the current lock holder (%s) for %q: %s", holder, lockPath, err) } // try acquiring the lock again, but this time don't destroy holders so we don't try forever return r.lock(lock, lockPath, false) } else { return util.Errorf("Lock for %q already held by lock %q", lockPath, holder) } } return err }
// Listen for errors in lock renewal. If the lock can't be renewed, we need to // 1) stop replication and 2) communicate the error up a level // If replication finishes, destroy the lock func (r replication) handleRenewalErrors(lock kp.Lock, renewalErrCh chan error) { defer func() { close(r.quitCh) close(r.errCh) lock.Destroy() }() select { case <-r.replicationDoneCh: case <-r.replicationCancelledCh: case err := <-renewalErrCh: // communicate the error to the caller. r.errCh <- replicationError{ err: err, isFatal: true, } return } }