Example #1
0
// 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
}
Example #2
0
// 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
	}
}