mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-4365 - allow lease locker to be used by kahadb - remove deps on jdbc pa. LockableService now passes a reference to a locker so it can pull the brokerService, extracted some of the jdbc lock common stuff, additional test kahadb with jdbc lease
This commit is contained in:
parent
0f90695db7
commit
efaa351db7
|
@ -27,6 +27,7 @@ public abstract class AbstractLocker extends ServiceSupport implements Locker {
|
||||||
protected String name;
|
protected String name;
|
||||||
protected boolean failIfLocked = false;
|
protected boolean failIfLocked = false;
|
||||||
protected long lockAcquireSleepInterval = DEFAULT_LOCK_ACQUIRE_SLEEP_INTERVAL;
|
protected long lockAcquireSleepInterval = DEFAULT_LOCK_ACQUIRE_SLEEP_INTERVAL;
|
||||||
|
protected LockableServiceSupport lockable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keepAlive() throws IOException {
|
public boolean keepAlive() throws IOException {
|
||||||
|
@ -38,6 +39,10 @@ public abstract class AbstractLocker extends ServiceSupport implements Locker {
|
||||||
this.lockAcquireSleepInterval = lockAcquireSleepInterval;
|
this.lockAcquireSleepInterval = lockAcquireSleepInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLockAcquireSleepInterval() {
|
||||||
|
return lockAcquireSleepInterval;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -47,4 +52,9 @@ public abstract class AbstractLocker extends ServiceSupport implements Locker {
|
||||||
public void setFailIfLocked(boolean failIfLocked) {
|
public void setFailIfLocked(boolean failIfLocked) {
|
||||||
this.failIfLocked = failIfLocked;
|
this.failIfLocked = failIfLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLockable(LockableServiceSupport lockableServiceSupport) {
|
||||||
|
this.lockable = lockableServiceSupport;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ public abstract class LockableServiceSupport extends ServiceSupport implements L
|
||||||
@Override
|
@Override
|
||||||
public void setLocker(Locker locker) throws IOException {
|
public void setLocker(Locker locker) throws IOException {
|
||||||
this.locker = locker;
|
this.locker = locker;
|
||||||
|
locker.setLockable(this);
|
||||||
if (this instanceof PersistenceAdapter) {
|
if (this instanceof PersistenceAdapter) {
|
||||||
this.locker.configure((PersistenceAdapter)this);
|
this.locker.configure((PersistenceAdapter)this);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,7 @@ public abstract class LockableServiceSupport extends ServiceSupport implements L
|
||||||
|
|
||||||
public Locker getLocker() throws IOException {
|
public Locker getLocker() throws IOException {
|
||||||
if (this.locker == null) {
|
if (this.locker == null) {
|
||||||
this.locker = createDefaultLocker();
|
setLocker(createDefaultLocker());
|
||||||
}
|
}
|
||||||
return this.locker;
|
return this.locker;
|
||||||
}
|
}
|
||||||
|
@ -165,4 +166,8 @@ public abstract class LockableServiceSupport extends ServiceSupport implements L
|
||||||
public void setBrokerService(BrokerService brokerService) {
|
public void setBrokerService(BrokerService brokerService) {
|
||||||
this.brokerService = brokerService;
|
this.brokerService = brokerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BrokerService getBrokerService() {
|
||||||
|
return this.brokerService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,10 @@ public interface Locker extends Service {
|
||||||
*/
|
*/
|
||||||
public void setFailIfLocked(boolean failIfLocked);
|
public void setFailIfLocked(boolean failIfLocked);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to what is locked
|
||||||
|
*/
|
||||||
|
public void setLockable(LockableServiceSupport lockable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionally configure the locker with the persistence adapter currently used
|
* Optionally configure the locker with the persistence adapter currently used
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF 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.apache.activemq.store.jdbc;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import org.apache.activemq.broker.AbstractLocker;
|
||||||
|
import org.apache.activemq.store.PersistenceAdapter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class AbstractJDBCLocker extends AbstractLocker {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractJDBCLocker.class);
|
||||||
|
protected DataSource dataSource;
|
||||||
|
protected Statements statements;
|
||||||
|
|
||||||
|
protected boolean createTablesOnStartup;
|
||||||
|
protected int queryTimeout = -1;
|
||||||
|
|
||||||
|
public void configure(PersistenceAdapter adapter) throws IOException {
|
||||||
|
if (adapter instanceof JDBCPersistenceAdapter) {
|
||||||
|
this.dataSource = ((JDBCPersistenceAdapter) adapter).getLockDataSource();
|
||||||
|
this.statements = ((JDBCPersistenceAdapter) adapter).getStatements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataSource(DataSource dataSource) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatements(Statements statements) {
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setQueryTimeout(Statement statement) throws SQLException {
|
||||||
|
if (queryTimeout > 0) {
|
||||||
|
statement.setQueryTimeout(queryTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getQueryTimeout() {
|
||||||
|
return queryTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQueryTimeout(int queryTimeout) {
|
||||||
|
this.queryTimeout = queryTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTablesOnStartup(boolean createTablesOnStartup) {
|
||||||
|
this.createTablesOnStartup = createTablesOnStartup;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Connection getConnection() throws SQLException {
|
||||||
|
return dataSource.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void close(Connection connection) {
|
||||||
|
if (null != connection) {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
} catch (SQLException e1) {
|
||||||
|
LOG.debug("exception while closing connection: " + e1, e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void close(Statement statement) {
|
||||||
|
if (null != statement) {
|
||||||
|
try {
|
||||||
|
statement.close();
|
||||||
|
} catch (SQLException e1) {
|
||||||
|
LOG.debug("exception while closing statement: " + e1, e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preStart() {
|
||||||
|
if (createTablesOnStartup) {
|
||||||
|
String[] createStatements = this.statements.getCreateLockSchemaStatements();
|
||||||
|
|
||||||
|
Connection connection = null;
|
||||||
|
Statement statement = null;
|
||||||
|
try {
|
||||||
|
connection = getConnection();
|
||||||
|
statement = connection.createStatement();
|
||||||
|
setQueryTimeout(statement);
|
||||||
|
|
||||||
|
for (int i = 0; i < createStatements.length; i++) {
|
||||||
|
LOG.debug("Executing SQL: " + createStatements[i]);
|
||||||
|
try {
|
||||||
|
statement.execute(createStatements[i]);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.info("Could not create lock tables; they could already exist." + " Failure was: "
|
||||||
|
+ createStatements[i] + " Message: " + e.getMessage() + " SQLState: " + e.getSQLState()
|
||||||
|
+ " Vendor code: " + e.getErrorCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.warn("Could not create lock tables; Failure Message: " + e.getMessage() + " SQLState: " + e.getSQLState()
|
||||||
|
+ " Vendor code: " + e.getErrorCode(), e);
|
||||||
|
} finally {
|
||||||
|
close(statement);
|
||||||
|
close(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,11 +21,6 @@ import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.SQLFeatureNotSupportedException;
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.AbstractLocker;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.Handler;
|
import org.apache.activemq.util.Handler;
|
||||||
import org.apache.activemq.util.ServiceStopper;
|
import org.apache.activemq.util.ServiceStopper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -38,27 +33,15 @@ import org.slf4j.LoggerFactory;
|
||||||
* @org.apache.xbean.XBean element="database-locker"
|
* @org.apache.xbean.XBean element="database-locker"
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DefaultDatabaseLocker extends AbstractLocker {
|
public class DefaultDatabaseLocker extends AbstractJDBCLocker {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultDatabaseLocker.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DefaultDatabaseLocker.class);
|
||||||
protected DataSource dataSource;
|
|
||||||
protected Statements statements;
|
|
||||||
|
|
||||||
protected volatile PreparedStatement lockCreateStatement;
|
protected volatile PreparedStatement lockCreateStatement;
|
||||||
protected volatile PreparedStatement lockUpdateStatement;
|
protected volatile PreparedStatement lockUpdateStatement;
|
||||||
protected volatile Connection connection;
|
protected volatile Connection connection;
|
||||||
protected volatile boolean stopping;
|
|
||||||
protected Handler<Exception> exceptionHandler;
|
protected Handler<Exception> exceptionHandler;
|
||||||
protected int queryTimeout = 10;
|
|
||||||
|
|
||||||
public void configure(PersistenceAdapter adapter) throws IOException {
|
|
||||||
if (adapter instanceof JDBCPersistenceAdapter) {
|
|
||||||
this.dataSource = ((JDBCPersistenceAdapter) adapter).getLockDataSource();
|
|
||||||
this.statements = ((JDBCPersistenceAdapter) adapter).getStatements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doStart() throws Exception {
|
public void doStart() throws Exception {
|
||||||
stopping = false;
|
|
||||||
|
|
||||||
LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
|
LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
|
||||||
String sql = statements.getLockCreateStatement();
|
String sql = statements.getLockCreateStatement();
|
||||||
|
@ -73,7 +56,7 @@ public class DefaultDatabaseLocker extends AbstractLocker {
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
try {
|
try {
|
||||||
if (stopping) {
|
if (isStopping()) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Cannot start broker as being asked to shut down. "
|
"Cannot start broker as being asked to shut down. "
|
||||||
+ "Interrupted attempt to acquire lock: "
|
+ "Interrupted attempt to acquire lock: "
|
||||||
|
@ -136,7 +119,6 @@ public class DefaultDatabaseLocker extends AbstractLocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doStop(ServiceStopper stopper) throws Exception {
|
public void doStop(ServiceStopper stopper) throws Exception {
|
||||||
stopping = true;
|
|
||||||
try {
|
try {
|
||||||
if (lockCreateStatement != null) {
|
if (lockCreateStatement != null) {
|
||||||
lockCreateStatement.cancel();
|
lockCreateStatement.cancel();
|
||||||
|
@ -178,9 +160,7 @@ public class DefaultDatabaseLocker extends AbstractLocker {
|
||||||
try {
|
try {
|
||||||
lockUpdateStatement = connection.prepareStatement(statements.getLockUpdateStatement());
|
lockUpdateStatement = connection.prepareStatement(statements.getLockUpdateStatement());
|
||||||
lockUpdateStatement.setLong(1, System.currentTimeMillis());
|
lockUpdateStatement.setLong(1, System.currentTimeMillis());
|
||||||
if (queryTimeout > 0) {
|
setQueryTimeout(lockUpdateStatement);
|
||||||
lockUpdateStatement.setQueryTimeout(queryTimeout);
|
|
||||||
}
|
|
||||||
int rows = lockUpdateStatement.executeUpdate();
|
int rows = lockUpdateStatement.executeUpdate();
|
||||||
if (rows == 1) {
|
if (rows == 1) {
|
||||||
result=true;
|
result=true;
|
||||||
|
@ -216,11 +196,4 @@ public class DefaultDatabaseLocker extends AbstractLocker {
|
||||||
this.exceptionHandler = exceptionHandler;
|
this.exceptionHandler = exceptionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getQueryTimeout() {
|
|
||||||
return queryTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setQueryTimeout(int queryTimeout) {
|
|
||||||
this.queryTimeout = queryTimeout;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,6 @@ import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.AbstractLocker;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.IOExceptionSupport;
|
import org.apache.activemq.util.IOExceptionSupport;
|
||||||
import org.apache.activemq.util.ServiceStopper;
|
import org.apache.activemq.util.ServiceStopper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -40,42 +36,27 @@ import org.slf4j.LoggerFactory;
|
||||||
* @org.apache.xbean.XBean element="lease-database-locker"
|
* @org.apache.xbean.XBean element="lease-database-locker"
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class LeaseDatabaseLocker extends AbstractLocker {
|
public class LeaseDatabaseLocker extends AbstractJDBCLocker {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LeaseDatabaseLocker.class);
|
private static final Logger LOG = LoggerFactory.getLogger(LeaseDatabaseLocker.class);
|
||||||
protected DataSource dataSource;
|
|
||||||
protected Statements statements;
|
|
||||||
|
|
||||||
protected boolean stopping;
|
|
||||||
protected int maxAllowableDiffFromDBTime = 0;
|
protected int maxAllowableDiffFromDBTime = 0;
|
||||||
protected long diffFromCurrentTime = Long.MAX_VALUE;
|
protected long diffFromCurrentTime = Long.MAX_VALUE;
|
||||||
protected String leaseHolderId;
|
protected String leaseHolderId;
|
||||||
protected int queryTimeout = -1;
|
|
||||||
JDBCPersistenceAdapter persistenceAdapter;
|
|
||||||
|
|
||||||
|
|
||||||
public void configure(PersistenceAdapter adapter) throws IOException {
|
|
||||||
if (adapter instanceof JDBCPersistenceAdapter) {
|
|
||||||
this.persistenceAdapter = (JDBCPersistenceAdapter)adapter;
|
|
||||||
this.dataSource = ((JDBCPersistenceAdapter) adapter).getLockDataSource();
|
|
||||||
this.statements = ((JDBCPersistenceAdapter) adapter).getStatements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doStart() throws Exception {
|
public void doStart() throws Exception {
|
||||||
stopping = false;
|
|
||||||
|
|
||||||
if (lockAcquireSleepInterval < persistenceAdapter.getLockKeepAlivePeriod()) {
|
if (lockAcquireSleepInterval < lockable.getLockKeepAlivePeriod()) {
|
||||||
LOG.warn("Persistence adapter keep alive period: " + persistenceAdapter.getLockKeepAlivePeriod()
|
LOG.warn("LockableService keep alive period: " + lockable.getLockKeepAlivePeriod()
|
||||||
+ ", which renews the lease, is less than lockAcquireSleepInterval: " + lockAcquireSleepInterval
|
+ ", which renews the lease, is less than lockAcquireSleepInterval: " + lockAcquireSleepInterval
|
||||||
+ ", the lease duration. These values will allow the lease to expire.");
|
+ ", the lease duration. These values will allow the lease to expire.");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info(getLeaseHolderId() + " attempting to acquire exclusive lease to become the Master broker");
|
LOG.info(getLeaseHolderId() + " attempting to acquire exclusive lease to become the master");
|
||||||
String sql = statements.getLeaseObtainStatement();
|
String sql = statements.getLeaseObtainStatement();
|
||||||
LOG.debug(getLeaseHolderId() + " locking Query is "+sql);
|
LOG.debug(getLeaseHolderId() + " locking Query is "+sql);
|
||||||
|
|
||||||
long now = 0l;
|
long now = 0l;
|
||||||
while (!stopping) {
|
while (!isStopping()) {
|
||||||
Connection connection = null;
|
Connection connection = null;
|
||||||
PreparedStatement statement = null;
|
PreparedStatement statement = null;
|
||||||
try {
|
try {
|
||||||
|
@ -110,43 +91,13 @@ public class LeaseDatabaseLocker extends AbstractLocker {
|
||||||
LOG.info(getLeaseHolderId() + " failed to acquire lease. Sleeping for " + lockAcquireSleepInterval + " milli(s) before trying again...");
|
LOG.info(getLeaseHolderId() + " failed to acquire lease. Sleeping for " + lockAcquireSleepInterval + " milli(s) before trying again...");
|
||||||
TimeUnit.MILLISECONDS.sleep(lockAcquireSleepInterval);
|
TimeUnit.MILLISECONDS.sleep(lockAcquireSleepInterval);
|
||||||
}
|
}
|
||||||
if (stopping) {
|
if (isStopping()) {
|
||||||
throw new RuntimeException(getLeaseHolderId() + " failing lease acquire due to stop");
|
throw new RuntimeException(getLeaseHolderId() + " failing lease acquire due to stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info(getLeaseHolderId() + ", becoming master with lease expiry " + new Date(now) + " on dataSource: " + dataSource);
|
LOG.info(getLeaseHolderId() + ", becoming master with lease expiry " + new Date(now) + " on dataSource: " + dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setQueryTimeout(PreparedStatement statement) throws SQLException {
|
|
||||||
if (queryTimeout > 0) {
|
|
||||||
statement.setQueryTimeout(queryTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Connection getConnection() throws SQLException {
|
|
||||||
return dataSource.getConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void close(Connection connection) {
|
|
||||||
if (null != connection) {
|
|
||||||
try {
|
|
||||||
connection.close();
|
|
||||||
} catch (SQLException e1) {
|
|
||||||
LOG.debug(getLeaseHolderId() + " caught exception while closing connection: " + e1, e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void close(PreparedStatement statement) {
|
|
||||||
if (null != statement) {
|
|
||||||
try {
|
|
||||||
statement.close();
|
|
||||||
} catch (SQLException e1) {
|
|
||||||
LOG.debug(getLeaseHolderId() + ", caught while closing statement: " + e1, e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reportLeasOwnerShipAndDuration(Connection connection) throws SQLException {
|
private void reportLeasOwnerShipAndDuration(Connection connection) throws SQLException {
|
||||||
PreparedStatement statement = null;
|
PreparedStatement statement = null;
|
||||||
try {
|
try {
|
||||||
|
@ -188,8 +139,7 @@ public class LeaseDatabaseLocker extends AbstractLocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doStop(ServiceStopper stopper) throws Exception {
|
public void doStop(ServiceStopper stopper) throws Exception {
|
||||||
stopping = true;
|
if (lockable.getBrokerService() != null && lockable.getBrokerService().isRestartRequested()) {
|
||||||
if (persistenceAdapter.getBrokerService() != null && persistenceAdapter.getBrokerService().isRestartRequested()) {
|
|
||||||
// keep our lease for restart
|
// keep our lease for restart
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +194,7 @@ public class LeaseDatabaseLocker extends AbstractLocker {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn(getLeaseHolderId() + ", failed to update lease: " + e, e);
|
LOG.warn(getLeaseHolderId() + ", failed to update lease: " + e, e);
|
||||||
IOException ioe = IOExceptionSupport.create(e);
|
IOException ioe = IOExceptionSupport.create(e);
|
||||||
persistenceAdapter.getBrokerService().handleIOException(ioe);
|
lockable.getBrokerService().handleIOException(ioe);
|
||||||
throw ioe;
|
throw ioe;
|
||||||
} finally {
|
} finally {
|
||||||
close(statement);
|
close(statement);
|
||||||
|
@ -253,26 +203,10 @@ public class LeaseDatabaseLocker extends AbstractLocker {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLockAcquireSleepInterval() {
|
|
||||||
return lockAcquireSleepInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLockAcquireSleepInterval(long lockAcquireSleepInterval) {
|
|
||||||
this.lockAcquireSleepInterval = lockAcquireSleepInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getQueryTimeout() {
|
|
||||||
return queryTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setQueryTimeout(int queryTimeout) {
|
|
||||||
this.queryTimeout = queryTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLeaseHolderId() {
|
public String getLeaseHolderId() {
|
||||||
if (leaseHolderId == null) {
|
if (leaseHolderId == null) {
|
||||||
if (persistenceAdapter.getBrokerService() != null) {
|
if (lockable.getBrokerService() != null) {
|
||||||
leaseHolderId = persistenceAdapter.getBrokerService().getBrokerName();
|
leaseHolderId = lockable.getBrokerService().getBrokerName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return leaseHolderId;
|
return leaseHolderId;
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class Statements {
|
||||||
private String removeAllMessagesStatement;
|
private String removeAllMessagesStatement;
|
||||||
private String removeAllSubscriptionsStatement;
|
private String removeAllSubscriptionsStatement;
|
||||||
private String[] createSchemaStatements;
|
private String[] createSchemaStatements;
|
||||||
|
private String[] createLockSchemaStatements;
|
||||||
private String[] dropSchemaStatements;
|
private String[] dropSchemaStatements;
|
||||||
private String lockCreateStatement;
|
private String lockCreateStatement;
|
||||||
private String lockUpdateStatement;
|
private String lockUpdateStatement;
|
||||||
|
@ -106,10 +107,6 @@ public class Statements {
|
||||||
+ ", CLIENT_ID " + stringIdDataType + " NOT NULL" + ", SUB_NAME " + stringIdDataType
|
+ ", CLIENT_ID " + stringIdDataType + " NOT NULL" + ", SUB_NAME " + stringIdDataType
|
||||||
+ " NOT NULL" + ", SELECTOR " + stringIdDataType + ", LAST_ACKED_ID " + sequenceDataType
|
+ " NOT NULL" + ", SELECTOR " + stringIdDataType + ", LAST_ACKED_ID " + sequenceDataType
|
||||||
+ ", PRIMARY KEY ( CONTAINER, CLIENT_ID, SUB_NAME))",
|
+ ", PRIMARY KEY ( CONTAINER, CLIENT_ID, SUB_NAME))",
|
||||||
"CREATE TABLE " + getFullLockTableName()
|
|
||||||
+ "( ID " + longDataType + " NOT NULL, TIME " + longDataType
|
|
||||||
+ ", BROKER_NAME " + stringIdDataType + ", PRIMARY KEY (ID) )",
|
|
||||||
"INSERT INTO " + getFullLockTableName() + "(ID) VALUES (1)",
|
|
||||||
"ALTER TABLE " + getFullMessageTableName() + " ADD PRIORITY " + sequenceDataType,
|
"ALTER TABLE " + getFullMessageTableName() + " ADD PRIORITY " + sequenceDataType,
|
||||||
"CREATE INDEX " + getFullMessageTableName() + "_PIDX ON " + getFullMessageTableName() + " (PRIORITY)",
|
"CREATE INDEX " + getFullMessageTableName() + "_PIDX ON " + getFullMessageTableName() + " (PRIORITY)",
|
||||||
"ALTER TABLE " + getFullMessageTableName() + " ADD XID " + stringIdDataType,
|
"ALTER TABLE " + getFullMessageTableName() + " ADD XID " + stringIdDataType,
|
||||||
|
@ -121,7 +118,24 @@ public class Statements {
|
||||||
"CREATE INDEX " + getFullAckTableName() + "_XIDX ON " + getFullAckTableName() + " (XID)"
|
"CREATE INDEX " + getFullAckTableName() + "_XIDX ON " + getFullAckTableName() + " (XID)"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return createSchemaStatements;
|
getCreateLockSchemaStatements();
|
||||||
|
String[] allCreateStatements = new String[createSchemaStatements.length + createLockSchemaStatements.length];
|
||||||
|
System.arraycopy(createSchemaStatements, 0, allCreateStatements, 0, createSchemaStatements.length);
|
||||||
|
System.arraycopy(createLockSchemaStatements, 0, allCreateStatements, createSchemaStatements.length, createLockSchemaStatements.length);
|
||||||
|
|
||||||
|
return allCreateStatements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getCreateLockSchemaStatements() {
|
||||||
|
if (createLockSchemaStatements == null) {
|
||||||
|
createLockSchemaStatements = new String[] {
|
||||||
|
"CREATE TABLE " + getFullLockTableName()
|
||||||
|
+ "( ID " + longDataType + " NOT NULL, TIME " + longDataType
|
||||||
|
+ ", BROKER_NAME " + stringIdDataType + ", PRIMARY KEY (ID) )",
|
||||||
|
"INSERT INTO " + getFullLockTableName() + "(ID) VALUES (1)"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return createLockSchemaStatements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDropAckPKAlterStatementEnd() {
|
public String getDropAckPKAlterStatementEnd() {
|
||||||
|
@ -762,6 +776,10 @@ public class Statements {
|
||||||
this.createSchemaStatements = createSchemaStatments;
|
this.createSchemaStatements = createSchemaStatments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCreateLockSchemaStatements(String[] createLockSchemaStatments) {
|
||||||
|
this.createLockSchemaStatements = createLockSchemaStatments;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDeleteOldMessagesStatementWithPriority(String deleteOldMessagesStatementWithPriority) {
|
public void setDeleteOldMessagesStatementWithPriority(String deleteOldMessagesStatementWithPriority) {
|
||||||
this.deleteOldMessagesStatementWithPriority = deleteOldMessagesStatementWithPriority;
|
this.deleteOldMessagesStatementWithPriority = deleteOldMessagesStatementWithPriority;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ public class TransactDatabaseLocker extends DefaultDatabaseLocker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doStart() throws Exception {
|
public void doStart() throws Exception {
|
||||||
stopping = false;
|
|
||||||
|
|
||||||
LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
|
LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
|
||||||
PreparedStatement statement = null;
|
PreparedStatement statement = null;
|
||||||
|
@ -57,7 +56,7 @@ public class TransactDatabaseLocker extends DefaultDatabaseLocker {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (stopping) {
|
if (isStopping()) {
|
||||||
throw new Exception("Cannot start broker as being asked to shut down. Interrupted attempt to acquire lock: " + e, e);
|
throw new Exception("Cannot start broker as being asked to shut down. Interrupted attempt to acquire lock: " + e, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.apache.activemq.util.{JMXSupport, ServiceStopper, ServiceSupport}
|
||||||
import org.apache.activemq.leveldb.{LevelDBStoreViewMBean, LevelDBClient, RecordLog, LevelDBStore}
|
import org.apache.activemq.leveldb.{LevelDBStoreViewMBean, LevelDBClient, RecordLog, LevelDBStore}
|
||||||
import java.net.{NetworkInterface, InetAddress}
|
import java.net.{NetworkInterface, InetAddress}
|
||||||
import org.fusesource.hawtdispatch._
|
import org.fusesource.hawtdispatch._
|
||||||
import org.apache.activemq.broker.Locker
|
import org.apache.activemq.broker.{LockableServiceSupport, Locker}
|
||||||
import org.apache.activemq.store.PersistenceAdapter
|
import org.apache.activemq.store.PersistenceAdapter
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
@ -190,6 +190,7 @@ class ElectingLevelDBStore extends ProxyLevelDBStore {
|
||||||
|
|
||||||
def createDefaultLocker(): Locker = new Locker {
|
def createDefaultLocker(): Locker = new Locker {
|
||||||
|
|
||||||
|
def setLockable(lockable: LockableServiceSupport) {}
|
||||||
def configure(persistenceAdapter: PersistenceAdapter) {}
|
def configure(persistenceAdapter: PersistenceAdapter) {}
|
||||||
def setFailIfLocked(failIfLocked: Boolean) {}
|
def setFailIfLocked(failIfLocked: Boolean) {}
|
||||||
def setLockAcquireSleepInterval(lockAcquireSleepInterval: Long) {}
|
def setLockAcquireSleepInterval(lockAcquireSleepInterval: Long) {}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class DbRestartJDBCQueueMasterSlaveTest extends JDBCQueueMasterSlaveTest
|
||||||
verifyExpectedBroker(inflightMessageCount);
|
verifyExpectedBroker(inflightMessageCount);
|
||||||
if (++inflightMessageCount == failureCount) {
|
if (++inflightMessageCount == failureCount) {
|
||||||
LOG.info("STOPPING DB!@!!!!");
|
LOG.info("STOPPING DB!@!!!!");
|
||||||
final EmbeddedDataSource ds = ((SyncDataSource)getExistingDataSource()).getDelegate();
|
final EmbeddedDataSource ds = ((SyncCreateDataSource)getExistingDataSource()).getDelegate();
|
||||||
ds.setShutdownDatabase("shutdown");
|
ds.setShutdownDatabase("shutdown");
|
||||||
LOG.info("DB STOPPED!@!!!!");
|
LOG.info("DB STOPPED!@!!!!");
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class JDBCQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
// startup db
|
// startup db
|
||||||
sharedDs = new SyncDataSource((EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory()));
|
sharedDs = new SyncCreateDataSource((EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory()));
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,61 +109,4 @@ public class JDBCQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
||||||
return sharedDs;
|
return sharedDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent concurrent calls from attempting to create the db at the same time
|
|
||||||
// can result in "already exists in this jvm" errors
|
|
||||||
class SyncDataSource implements DataSource {
|
|
||||||
final EmbeddedDataSource delegate;
|
|
||||||
SyncDataSource(EmbeddedDataSource dataSource) {
|
|
||||||
this.delegate = dataSource;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Connection getConnection() throws SQLException {
|
|
||||||
synchronized (this) {
|
|
||||||
return delegate.getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Connection getConnection(String username, String password) throws SQLException {
|
|
||||||
synchronized (this) {
|
|
||||||
return delegate.getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PrintWriter getLogWriter() throws SQLException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLogWriter(PrintWriter out) throws SQLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLoginTimeout(int seconds) throws SQLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLoginTimeout() throws SQLException {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbeddedDataSource getDelegate() {
|
|
||||||
return delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF 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.apache.activemq.broker.ft;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import org.apache.derby.jdbc.EmbeddedDataSource;
|
||||||
|
|
||||||
|
// prevent concurrent calls from attempting to create the db at the same time
|
||||||
|
// can result in "already exists in this jvm" errors
|
||||||
|
|
||||||
|
public class SyncCreateDataSource implements DataSource {
|
||||||
|
final EmbeddedDataSource delegate;
|
||||||
|
|
||||||
|
SyncCreateDataSource(EmbeddedDataSource dataSource) {
|
||||||
|
this.delegate = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
synchronized (this) {
|
||||||
|
return delegate.getConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection(String username, String password) throws SQLException {
|
||||||
|
synchronized (this) {
|
||||||
|
return delegate.getConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbeddedDataSource getDelegate() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF 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.apache.activemq.broker.ft;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import org.apache.activemq.broker.BrokerService;
|
||||||
|
import org.apache.activemq.broker.TransportConnector;
|
||||||
|
import org.apache.activemq.store.jdbc.DataSourceServiceSupport;
|
||||||
|
import org.apache.activemq.store.jdbc.LeaseDatabaseLocker;
|
||||||
|
import org.apache.activemq.store.jdbc.Statements;
|
||||||
|
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||||
|
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
||||||
|
import org.apache.activemq.util.IOHelper;
|
||||||
|
import org.apache.derby.jdbc.EmbeddedDataSource;
|
||||||
|
|
||||||
|
public class kahaDbJdbcLeaseQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
||||||
|
protected DataSource sharedDs;
|
||||||
|
protected String MASTER_URL = "tcp://localhost:62001";
|
||||||
|
protected String SLAVE_URL = "tcp://localhost:62002";
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
// startup db
|
||||||
|
sharedDs = new SyncCreateDataSource((EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory()));
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createMaster() throws Exception {
|
||||||
|
master = new BrokerService();
|
||||||
|
master.setBrokerName("master");
|
||||||
|
master.addConnector(MASTER_URL);
|
||||||
|
master.setUseJmx(false);
|
||||||
|
master.setPersistent(true);
|
||||||
|
master.setDeleteAllMessagesOnStartup(true);
|
||||||
|
KahaDBPersistenceAdapter kahaDBPersistenceAdapter = (KahaDBPersistenceAdapter) master.getPersistenceAdapter();
|
||||||
|
LeaseDatabaseLocker leaseDatabaseLocker = new LeaseDatabaseLocker();
|
||||||
|
leaseDatabaseLocker.setCreateTablesOnStartup(true);
|
||||||
|
leaseDatabaseLocker.setDataSource(getExistingDataSource());
|
||||||
|
leaseDatabaseLocker.setStatements(new Statements());
|
||||||
|
configureLocker(kahaDBPersistenceAdapter);
|
||||||
|
kahaDBPersistenceAdapter.setLocker(leaseDatabaseLocker);
|
||||||
|
configureBroker(master);
|
||||||
|
master.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureBroker(BrokerService brokerService) {
|
||||||
|
DefaultIOExceptionHandler stopBrokerOnStoreException = new DefaultIOExceptionHandler();
|
||||||
|
// we want any store io exception to stop the broker
|
||||||
|
stopBrokerOnStoreException.setIgnoreSQLExceptions(false);
|
||||||
|
brokerService.setIoExceptionHandler(stopBrokerOnStoreException);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createSlave() throws Exception {
|
||||||
|
// use a separate thread as the slave will block waiting for
|
||||||
|
// the exclusive db lock
|
||||||
|
Thread t = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
BrokerService broker = new BrokerService();
|
||||||
|
broker.setBrokerName("slave");
|
||||||
|
TransportConnector connector = new TransportConnector();
|
||||||
|
connector.setUri(new URI(SLAVE_URL));
|
||||||
|
broker.addConnector(connector);
|
||||||
|
broker.setUseJmx(false);
|
||||||
|
broker.setPersistent(true);
|
||||||
|
KahaDBPersistenceAdapter kahaDBPersistenceAdapter = (KahaDBPersistenceAdapter) broker.getPersistenceAdapter();
|
||||||
|
LeaseDatabaseLocker leaseDatabaseLocker = new LeaseDatabaseLocker();
|
||||||
|
leaseDatabaseLocker.setDataSource(getExistingDataSource());
|
||||||
|
leaseDatabaseLocker.setStatements(new Statements());
|
||||||
|
configureLocker(kahaDBPersistenceAdapter);
|
||||||
|
kahaDBPersistenceAdapter.setLocker(leaseDatabaseLocker);
|
||||||
|
|
||||||
|
configureBroker(broker);
|
||||||
|
broker.start();
|
||||||
|
slave.set(broker);
|
||||||
|
slaveStarted.countDown();
|
||||||
|
} catch (IllegalStateException expectedOnShutdown) {
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("failed to start slave broker, reason:" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureLocker(KahaDBPersistenceAdapter kahaDBPersistenceAdapter) throws IOException {
|
||||||
|
kahaDBPersistenceAdapter.setLockKeepAlivePeriod(500);
|
||||||
|
kahaDBPersistenceAdapter.getLocker().setLockAcquireSleepInterval(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DataSource getExistingDataSource() throws Exception {
|
||||||
|
return sharedDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue