Return-Path: X-Original-To: apmail-activemq-dev-archive@www.apache.org Delivered-To: apmail-activemq-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E6B3C926F for ; Fri, 8 Mar 2013 18:04:12 +0000 (UTC) Received: (qmail 99390 invoked by uid 500); 8 Mar 2013 18:04:12 -0000 Delivered-To: apmail-activemq-dev-archive@activemq.apache.org Received: (qmail 99364 invoked by uid 500); 8 Mar 2013 18:04:12 -0000 Mailing-List: contact dev-help@activemq.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@activemq.apache.org Delivered-To: mailing list dev@activemq.apache.org Received: (qmail 99356 invoked by uid 99); 8 Mar 2013 18:04:12 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 08 Mar 2013 18:04:12 +0000 Date: Fri, 8 Mar 2013 18:04:12 +0000 (UTC) From: "Paul Gale (JIRA)" To: dev@activemq.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Comment Edited] (AMQ-4365) Allow the Lease Locker to be used with out a JDBCPersistenceAdapter - so it can be a broker lock MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/AMQ-4365?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13597342#comment-13597342 ] Paul Gale edited comment on AMQ-4365 at 3/8/13 6:03 PM: -------------------------------------------------------- So I've been able to get a first cut at a lease database locker that works with the KahaDBPersistenceAdapter, as shown below. This is by no means the ideal solution but it works. Feedback welcome. Longer term, the signature of the configure method should be changed; there is no reason that I can see why it should be coupled to a PersistenceAdapter - that's too broad. Either provide a few overloaded versions of configure() with various arguments that a locker might require or create an interface to be implemented by a persistence provider that makes the contract between the two more explicit. {code:title=MyLeaseDatabaseLocker.java|borderStyle=solid} public class MyLeaseDatabaseLocker extends LeaseDatabaseLocker implements BrokerServiceAware, LockDataSourceCapable { private static final Logger LOG = LoggerFactory.getLogger(MyLeaseDatabaseLocker.class); protected BrokerService brokerService; @Override public void configure(PersistenceAdapter ignore) throws IOException { this.statements = new Statements(); } @Override public boolean keepAlive() throws IOException { boolean result = false; final String sql = statements.getLeaseUpdateStatement(); LOG.debug(getLeaseHolderId() + ", lease keepAlive Query is " + sql); Connection connection = null; PreparedStatement statement = null; try { connection = getConnection(); initTimeDiff(connection); statement = connection.prepareStatement(sql); setQueryTimeout(statement); final long now = System.currentTimeMillis() + diffFromCurrentTime; statement.setString(1, getLeaseHolderId()); statement.setLong(2, now + lockAcquireSleepInterval); statement.setString(3, getLeaseHolderId()); result = (statement.executeUpdate() == 1); } catch(Exception e) { LOG.warn(getLeaseHolderId() + ", failed to update lease: " + e, e); IOException ioe = IOExceptionSupport.create(e); brokerService.handleIOException(ioe); throw ioe; } finally { close(statement); close(connection); } return result; } @Override public void setBrokerService(BrokerService brokerService) { this.brokerService = brokerService; } @Override public String getLeaseHolderId() { if(leaseHolderId == null && brokerService != null) { leaseHolderId = brokerService.getBrokerName(); } return leaseHolderId; } @Override public void setLockDataSource(DataSource lockDataSource) { this.dataSource = lockDataSource; } @Override public DataSource getLockDataSource() { return this.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) return; try { connection.close(); } catch(SQLException e1) { LOG.debug(getLeaseHolderId() + " caught exception while closing connection: " + e1, e1); } } private void close(PreparedStatement statement) { if(null == statement) return; try { statement.close(); } catch(SQLException e1) { LOG.debug(getLeaseHolderId() + ", caught while closing statement: " + e1, e1); } } } {code} {code:title=LockDataSourceCapable.java|borderStyle=solid} public interface LockDataSourceCapable { public void setLockDataSource(DataSource lockDataSource); public DataSource getLockDataSource(); } {code} The activemq.xml (with parts removed) is as follows: {code:xml} {code} was (Author: paulgale): So I've been able to get a first cut at a lease database locker that works with the KahaDBPersistenceAdapter, as shown below. This is by no means the ideal solution but it works. Feedback welcome. Longer term, the signature of the configure method should be changed; there is no reason that I can see why it should be coupled to a PersistenceAdapter - that's too broad. Either provide a few overloaded versions of configure() with various arguments that a locker might require or create an interface to be implemented by a persistence provider that makes the contract between the two more explicit. public class MyLeaseDatabaseLocker extends LeaseDatabaseLocker implements BrokerServiceAware, LockDataSourceCapable { private static final Logger LOG = LoggerFactory.getLogger(MyLeaseDatabaseLocker.class); protected BrokerService brokerService; @Override public void configure(PersistenceAdapter ignore) throws IOException { this.statements = new Statements(); } @Override public boolean keepAlive() throws IOException { boolean result = false; final String sql = statements.getLeaseUpdateStatement(); LOG.debug(getLeaseHolderId() + ", lease keepAlive Query is " + sql); Connection connection = null; PreparedStatement statement = null; try { connection = getConnection(); initTimeDiff(connection); statement = connection.prepareStatement(sql); setQueryTimeout(statement); final long now = System.currentTimeMillis() + diffFromCurrentTime; statement.setString(1, getLeaseHolderId()); statement.setLong(2, now + lockAcquireSleepInterval); statement.setString(3, getLeaseHolderId()); result = (statement.executeUpdate() == 1); } catch(Exception e) { LOG.warn(getLeaseHolderId() + ", failed to update lease: " + e, e); IOException ioe = IOExceptionSupport.create(e); brokerService.handleIOException(ioe); throw ioe; } finally { close(statement); close(connection); } return result; } @Override public void setBrokerService(BrokerService brokerService) { this.brokerService = brokerService; } @Override public String getLeaseHolderId() { if(leaseHolderId == null && brokerService != null) { leaseHolderId = brokerService.getBrokerName(); } return leaseHolderId; } @Override public void setLockDataSource(DataSource lockDataSource) { this.dataSource = lockDataSource; } @Override public DataSource getLockDataSource() { return this.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) return; try { connection.close(); } catch(SQLException e1) { LOG.debug(getLeaseHolderId() + " caught exception while closing connection: " + e1, e1); } } private void close(PreparedStatement statement) { if(null == statement) return; try { statement.close(); } catch(SQLException e1) { LOG.debug(getLeaseHolderId() + ", caught while closing statement: " + e1, e1); } } } public interface LockDataSourceCapable { public void setLockDataSource(DataSource lockDataSource); public DataSource getLockDataSource(); } The activemq.xml (with parts removed) is as follows: > Allow the Lease Locker to be used with out a JDBCPersistenceAdapter - so it can be a broker lock > ------------------------------------------------------------------------------------------------ > > Key: AMQ-4365 > URL: https://issues.apache.org/jira/browse/AMQ-4365 > Project: ActiveMQ > Issue Type: Improvement > Affects Versions: 5.8.0 > Reporter: Gary Tully > Fix For: 5.9.0 > > > The locker interface needs another configure option to provide a broker service, or needs to be brokerService aware so that a locker can get identity and access to the io exception handlers. > The lease database locker is dependent on the jdbc pa to get statements and data source. It should be possible to configure these independently such that it can be used standalone as a broker lock. So setters for each. > This will help sort out some of the dependencies between broker and lock implementations. also making it possible to use a lease lock with kahadb for example. > some context: http://mail-archives.apache.org/mod_mbox/activemq-users/201303.mbox/%3CCAJ5znhurUZ+aEWsaaBAjtwBbpKWn06RyyyT6NqsDg_Su7vMOcg@mail.gmail.com%3E -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira