package io.cattle.platform.lock.provider.impl;
import io.cattle.platform.lock.Lock;
import io.cattle.platform.lock.definition.BlockingLockDefinition;
import io.cattle.platform.lock.definition.LockDefinition;
import io.cattle.platform.lock.exception.FailedToAcquireLockException;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StandardLock implements Lock {
private static final Logger log = LoggerFactory.getLogger(StandardLock.class);
LockDefinition lockDefinition;
java.util.concurrent.locks.Lock lock;
long timeout;
volatile long referenceCount = 0;
volatile Thread owner = null;
long ownerCount = 0;
boolean acquired = false;
public StandardLock(LockDefinition lockDefinition, java.util.concurrent.locks.Lock lock) {
this.lockDefinition = lockDefinition;
this.lock = lock;
if (lockDefinition instanceof BlockingLockDefinition) {
this.timeout = ((BlockingLockDefinition) lockDefinition).getWait();
}
}
@Override
public boolean tryLock() {
log.trace("Try Lock Attempt [{}]", timeout);
boolean result = lock.tryLock();
log.trace("Try Lock [{}] result [{}]", lockDefinition, result);
if (result) {
incrementOwner();
}
return result;
}
public boolean wasAcquired() {
return acquired;
}
@Override
public void lock() throws FailedToAcquireLockException {
log.trace("Lock Attempt [{}], timeout [{}]", lockDefinition, timeout);
try {
if (!doLock()) {
log.trace("Lock [{}], timeout [{}] failed", lockDefinition, timeout);
throw new FailedToAcquireLockException(lockDefinition);
}
} catch (InterruptedException e) {
log.error("Failed to lock [{}], interrupted", lockDefinition, e);
throw new FailedToAcquireLockException(lockDefinition);
}
incrementOwner();
log.trace("Lock [{}] owner", lockDefinition);
}
protected void incrementOwner() {
acquired = true;
ownerCount++;
if (owner == null) {
log.trace("Lock [{}] acquiring ownernship count [{}]", lockDefinition, ownerCount);
owner = Thread.currentThread();
} else {
log.trace("Lock [{}] ownernship count [{}]", lockDefinition, ownerCount);
}
}
protected void decrementOwner() {
ownerCount--;
if (ownerCount <= 0) {
log.trace("Lock [{}] releasing ownernship count [{}]", lockDefinition, ownerCount);
ownerCount = 0;
owner = null;
} else {
log.trace("Lock [{}] ownernship count [{}]", lockDefinition, ownerCount);
}
}
protected boolean doLock() throws InterruptedException {
if (timeout <= 0) {
return lock.tryLock();
} else {
return lock.tryLock(timeout, TimeUnit.MILLISECONDS);
}
}
@Override
public void unlock() {
try {
if (Thread.currentThread() == owner) {
log.trace("Unlock [{}] owner", lockDefinition);
decrementOwner();
lock.unlock();
} else {
log.trace("Unlock [{}] not owner", lockDefinition);
}
} catch (Throwable t) {
log.trace("Failed to unlock [{}], may not own lock", lockDefinition, t);
}
}
@Override
public LockDefinition getLockDefinition() {
return lockDefinition;
}
public long getReference() {
return referenceCount;
}
public long incrementReference() {
log.trace("Lock [{}] reference count increment [{}]", lockDefinition, referenceCount);
return ++referenceCount;
}
public long decrementReference() {
log.trace("Lock [{}] reference count decrement [{}]", lockDefinition, referenceCount);
return --referenceCount;
}
public java.util.concurrent.locks.Lock getLock() {
return lock;
}
}