public GlobalLockerBase(final long timeout, final TimeUnit timeUnit) { this.timeout = timeout; this.timeUnit = timeUnit; this.lockTable = new ReentrantLock(); this.prof = new Profiling<GlobalLock, LockFailedException>(); }
@Override public boolean reset(final String lockName) { return lockTable.releaseLock(lockName); } });
/** * Create a new LockHolder. This is done *after* the distributed lock was acquired. * * @param lockName */ public void createLock(final String lockName, final GlobalLock originalLock) { final String requestId = getRequestId(); if (requestId == null) { return; } synchronized (lockTable) { LockHolder lockHolder = lockTable.get(lockName); if (lockHolder != null) { throw new IllegalStateException(String.format("ReentrantLock createLock %s : lock already current request = %s, owner request = %s", lockName, requestId, lockHolder.getRequestId())); } if (lockHolder == null) { lockHolder = new LockHolder(requestId, originalLock); lockTable.put(lockName, lockHolder); } lockHolder.increment(); } }
@Override protected synchronized GlobalLock doLock(final String lockName) { if (!isFree(lockName)) { return null; } if (locks.get(lockName) == null) { locks.put(lockName, new AtomicBoolean(true)); } else { locks.get(lockName).set(true); } final GlobalLock lock = new GlobalLock() { @Override public void release() { if (lockTable.releaseLock(lockName)) { locks.get(lockName).set(false); } } }; lockTable.createLock(lockName, lock); return lock; }
protected GlobalLock lock(final String lockName) { final TryAcquireLockState lockState = lockTable.tryAcquireLockForExistingOwner(lockName); if (lockState.getLockState() == ReentrantLock.ReentrantLockState.HELD_OWNER) { return lockState.getOriginalLock(); } if (lockState.getLockState() == ReentrantLock.ReentrantLockState.HELD_NOT_OWNER) { // In that case, we need to respect the provided timeout value try { Thread.sleep(TimeUnit.MILLISECONDS.convert(timeout, timeUnit)); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); logger.warn("lock got interrupted", e); } return null; } return doLock(lockName); }
/** * Release a lock. This is always called when the resources are feed * * @param lockName * @return true if nobody still holds the reentrant lock (and thefeore distributed lock can be freed) */ public boolean releaseLock(final String lockName) { // In case there no requestId set, this was not a 'reentrant' lock, so nothing to do but we need to return true // so distributed lock can be released // final String requestId = getRequestId(); if (requestId == null) { return true; } synchronized (lockTable) { final LockHolder lockHolder = lockTable.get(lockName); if (lockHolder == null) { throw new IllegalStateException(String.format("ReentrantLock releaseLock %s : cannot find lock in the table, current request = %s", lockName, requestId)); } if (!lockHolder.getRequestId().equals(requestId)) { throw new IllegalStateException(String.format("ReentrantLock releaseLock %s : current request = %s, owner request = %s", lockName, requestId, lockHolder.getRequestId())); } final boolean free = lockHolder.decrement(); if (free) { lockTable.remove(lockName); } return free; } }
@Override protected GlobalLock doLock(final String lockName) { Connection connection = null; boolean obtained = false; try { connection = dataSource.getConnection(); obtained = globalLockDao.lock(connection, lockName, timeout, timeUnit); if (obtained) { final GlobalLock lock = getGlobalLock(connection, lockName, new ResetReentrantLockCallback() { @Override public boolean reset(final String lockName) { return lockTable.releaseLock(lockName); } }); lockTable.createLock(lockName, lock); return lock; } } catch (final SQLException e) { logger.warn("Unable to obtain lock for {}", lockName, e); } finally { if (!obtained && connection != null) { try { connection.close(); } catch (final SQLException e) { logger.warn("Unable to close connection", e); } } } return null; }
/** * Atomically increment the refCount lock if we are already the owner of that lock. * * @param lockName * @return the ReentrantLockState: lock is FREE, or we already hold it (and incremented the refCount) or it held by somebody else */ public TryAcquireLockState tryAcquireLockForExistingOwner(final String lockName) { synchronized (lockTable) { final LockHolder lockHolder = lockTable.get(lockName); if (lockHolder == null) { return new TryAcquireLockState(ReentrantLockState.FREE); } final String maybeNullRequestId = getRequestId(); if (maybeNullRequestId == null || !lockHolder.getRequestId().equals(maybeNullRequestId)) { return new TryAcquireLockState(ReentrantLockState.HELD_NOT_OWNER); } else { // Increment value before we return while we hold the lockTable lock. lockHolder.increment(); return new TryAcquireLockState(ReentrantLockState.HELD_OWNER, lockHolder.getOriginalLock()); } } }
@Override public void release() { if (lockTable.releaseLock(lockName)) { locks.get(lockName).set(false); } } };