
org.killbill.commons.locker.GlobalLockerBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of catalog-test Show documentation
Show all versions of catalog-test Show documentation
Test Plugin for CatalogPluginApin
/*
* Copyright 2015 Groupon, Inc
* Copyright 2015 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.killbill.commons.locker;
import org.killbill.commons.locker.ReentrantLock.TryAcquireLockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
public abstract class GlobalLockerBase implements GlobalLocker {
protected static final long DEFAULT_TIMEOUT_MILLIS = 100L;
protected static final Logger logger = LoggerFactory.getLogger(GlobalLockerBase.class);
protected final GlobalLockDao globalLockDao;
private final DataSource dataSource;
protected final long timeout;
protected final TimeUnit timeUnit;
private final ReentrantLock lockTable;
public GlobalLockerBase(final DataSource dataSource, final GlobalLockDao globalLockDao, final long timeout, final TimeUnit timeUnit) {
this.dataSource = dataSource;
this.timeout = timeout;
this.timeUnit = timeUnit;
this.globalLockDao = globalLockDao;
this.lockTable = new ReentrantLock();
}
@Override
public GlobalLock lockWithNumberOfTries(final String service, final String lockKey, final int retry) throws LockFailedException {
final String lockName = getLockName(service, lockKey);
int tries_left = retry;
while (tries_left-- > 0) {
final GlobalLock lock = lock(lockName);
if (lock != null) {
return lock;
}
if (tries_left > 0) {
sleep();
}
}
logger.warn(String.format("Failed to acquire lock %s for service %s after %s retries", lockKey, service, retry));
throw new LockFailedException();
}
@Override
public boolean isFree(final String service, final String lockKey) {
final String lockName = getLockName(service, lockKey);
Connection connection = null;
try {
connection = dataSource.getConnection();
return globalLockDao.isLockFree(connection, lockName);
} catch (final SQLException e) {
logger.warn("Unable to check if lock is free", e);
return false;
} finally {
if (connection != null) {
try {
connection.close();
} catch (final SQLException e) {
logger.warn("Unable to close connection", e);
}
}
}
}
protected GlobalLock lock(final String lockName) throws LockFailedException {
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 tp 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;
}
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(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;
}
protected abstract GlobalLock getGlobalLock(final Connection connection, final String lockName, final ResetReentrantLockCallback resetCb);
protected abstract String getLockName(final String service, final String lockKey);
private void sleep() {
try {
Thread.sleep(TimeUnit.MILLISECONDS.convert(timeout, timeUnit));
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
logger.warn("GlobalLockerBase got interrupted", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy