package io.cattle.platform.lock.impl; import io.cattle.platform.lock.Lock; import io.cattle.platform.lock.LockCallbackWithException; import io.cattle.platform.lock.LockManager; import io.cattle.platform.lock.definition.LockDefinition; import io.cattle.platform.lock.definition.MultiLockDefinition; import io.cattle.platform.lock.provider.LockProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LockManagerImpl extends AbstractLockManagerImpl implements LockManager { private static final Logger log = LoggerFactory.getLogger(LockManagerImpl.class); LockProvider lockProvider; @Override protected <T, E extends Throwable> T doLock(LockDefinition lockDef, LockCallbackWithException<T, E> callback, WithLock with) throws E { Lock lock = null; try { lock = getLock(lockDef); /* * Important to lock in the try because the Lock may be a multi-lock * and if a multi-lock fails to lock it can be in a half locked * state so it must be unlocked */ if (!with.withLock(lock)) return null; return callback.doWithLock(); } finally { if (lock != null) { try { lock.unlock(); } catch (Throwable t) { /* Should never happen, but I don't trust people */ log.error("Failed to unlock [{}], unlock() should never throw an exception", lock.getLockDefinition(), t); } releaseLock(lock); } } } protected void releaseLock(Lock lock) { if (lock instanceof MultiLock) { for (Lock lockPart : ((MultiLock) lock).getLocks()) { try { lockProvider.releaseLock(lockPart); } catch (Throwable t) { /* Should never happen, but I don't trust people */ log.error("Failed to release lock [{}], releaseLock() should never throw an exception", lockPart.getLockDefinition(), t); } } } else { lockProvider.releaseLock(lock); } } protected Lock getLock(LockDefinition def) { if (def instanceof MultiLockDefinition) { return new MultiLock((MultiLockDefinition) def, lockProvider); } else { return lockProvider.getLock(def); } } @Override public LockProvider getLockProvider() { return lockProvider; } public void setLockProvider(LockProvider lockProvider) { this.lockProvider = lockProvider; } }