mq5.0-source.main.mq-broker.persist-jdbc.src.main.java.com.sun.messaging.jmq.jmsserver.persist.jdbc.JDBCStore Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2000-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* @(#)JDBCStore.java 1.163 07/24/07
*/
package com.sun.messaging.jmq.jmsserver.persist.jdbc;
import java.util.concurrent.locks.ReentrantLock;
import com.sun.messaging.jmq.io.SysMessageID;
import com.sun.messaging.jmq.io.Packet;
import com.sun.messaging.jmq.io.Status;
import com.sun.messaging.jmq.util.UID;
import com.sun.messaging.jmq.util.log.Logger;
import com.sun.messaging.jmq.jmsserver.core.*;
import com.sun.messaging.jmq.jmsserver.data.TransactionUID;
import com.sun.messaging.jmq.jmsserver.data.TransactionState;
import com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement;
import com.sun.messaging.jmq.jmsserver.data.TransactionWork;
import com.sun.messaging.jmq.jmsserver.data.TransactionWorkMessage;
import com.sun.messaging.jmq.jmsserver.data.TransactionWorkMessageAck;
import com.sun.messaging.jmq.jmsserver.data.TransactionBroker;
import com.sun.messaging.jmq.jmsserver.util.*;
import com.sun.messaging.jmq.jmsserver.*;
import com.sun.messaging.jmq.jmsserver.persist.api.*;
import com.sun.messaging.jmq.jmsserver.cluster.api.ha.TakingoverTracker;
import com.sun.messaging.jmq.jmsserver.resources.*;
import com.sun.messaging.jmq.jmsserver.Broker;
import com.sun.messaging.jmq.jmsserver.FaultInjection;
import com.sun.messaging.jmq.jmsserver.cluster.api.BrokerState;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.comm.BaseDAO;
import java.io.*;
import java.sql.*;
import java.util.*;
import com.sun.messaging.bridge.api.DupKeyException;
import com.sun.messaging.bridge.api.KeyNotFoundException;
import com.sun.messaging.bridge.api.UpdateOpaqueDataCallback;
import org.jvnet.hk2.annotations.Service;
import javax.inject.Singleton;
/**
* JDBCStore provides JDBC based persistence.
*
* Note that some methods are NOT synchronized.
*/
@Service(name = "com.sun.messaging.jmq.jmsserver.persist.jdbc.JDBCStore")
@Singleton
public class JDBCStore extends Store implements DBConstants, PartitionedStore {
private static boolean DEBUG = getDEBUG();
public static final String LOCK_STORE_PROP =
DBManager.JDBC_PROP_PREFIX + ".lockstore.enabled";
public static final String ENABLE_STORED_PROC_PROP =
DBManager.JDBC_PROP_PREFIX + ".enableStoredProc";
public static final boolean ENABLE_STORED_PROC =
Globals.getConfig().getBooleanProperty(ENABLE_STORED_PROC_PROP, false);
public static final int STORED_PROC_VERSION = 500;
private static final String MSG_ENUM_USE_CURSOR_PROP =
DBManager.JDBC_PROP_PREFIX + ".msgEnumUseResultSetCursor";
// current version of store
public static final int OLD_STORE_VERSION_350 = 350;
public static final int OLD_STORE_VERSION_370 = 370;
public static final int OLD_STORE_VERSION_400 = 400;
public static final int STORE_VERSION = 410;
// database connection
DBManager dbmgr;
DAOFactory daoFactory;
private HashMap pendingDeleteDsts = new HashMap(5);
private HashMap takeoverLockMap = new HashMap();
private StoreSessionReaperTask sessionReaper = null;
private boolean msgEnumUseCursor = true;
private List dataEnums = Collections.synchronizedList(
new ArrayList());
private UID partitionid = PartitionedStore.DEFAULT_UID;
private static final String PARTITION_MODE_PROP =
StoreManager.PARTITION_MODE_PROP;
private static final boolean PARTITION_MODE_DEFAULT= false;
private static final String PARTITION_MIGRATABLE_PROP =
DBManager.JDBC_PROP_PREFIX+".partitionMigratable";
private static final boolean PARTITION_MIGRATABLE_DEFAULT = false;
private static final String INIT_NUM_PARTITION_PROP =
DBManager.JDBC_PROP_PREFIX+".initialNumPartitions";
private static final int INIT_NUM_PARTITION_DEFAULT = 1;
private int initialNumPartitions = INIT_NUM_PARTITION_DEFAULT;
private static final String PARTITION_STORE_CLASS_PROP =
DBManager.JDBC_PROP_PREFIX+".storePartitionClass";
private static final String PARTITION_STORE_CLASS_DEFAULT =
"com.sun.messaging.jmq.jmsserver.persist.partition.jdbc.JDBCStorePartition";
private boolean partitionMode = PARTITION_MODE_DEFAULT;
private boolean partitionMigratable = PARTITION_MIGRATABLE_DEFAULT;
private Class partitionClass = null;
private static final String partitionClassStr = Globals.getConfig().
getProperty(PARTITION_STORE_CLASS_PROP,
PARTITION_STORE_CLASS_DEFAULT);
private LinkedHashMap partitionStores =
new LinkedHashMap();
private List partitionListeners =
new ArrayList();
private List sessionReaperListeners =
new ArrayList();
private ReentrantLock partitionLock = new ReentrantLock();
private FaultInjection FI = null;
/**
* When instantiated, the object configures itself by reading the
* properties specified in BrokerConfig.
*/
public JDBCStore() throws BrokerException {
FI = FaultInjection.getInjection();
partitionMode = StoreManager.isConfiguredPartitionMode(
PARTITION_MODE_DEFAULT);
if (partitionMode && !Globals.getHAEnabled()) {
partitionMode = false;
logger.log(logger.WARNING, br.getKString(
br.W_IGNORE_PROP_SETTING, PARTITION_MODE_PROP+"="+true));
}
if (partitionMode) {
try {
partitionClass = Class.forName(partitionClassStr);
} catch (Exception e) {
throw new BrokerException(e.getMessage(), e);
}
int val = config.getIntProperty(
INIT_NUM_PARTITION_PROP, INIT_NUM_PARTITION_DEFAULT);
if (val > 0) {
initialNumPartitions = val;
}
partitionMigratable = config.getBooleanProperty(
PARTITION_MIGRATABLE_PROP, PARTITION_MIGRATABLE_DEFAULT);
String reskey = br.I_STORE_USE_PARTITION_MODE;
if (partitionMigratable) {
reskey = br.I_STORE_USE_MIGRATABLE_PARTITION_MODE;
}
String str = "";
if (initialNumPartitions > 1) {
str = "["+INIT_NUM_PARTITION_PROP+"="+initialNumPartitions+"]";
}
logger.log(logger.INFO, br.getKString(reskey, getStoreType())+str);
}
dbmgr = DBManager.getDBManager();
daoFactory = dbmgr.getDAOFactory();
// print out info messages
String url = dbmgr.getOpenDBURL();
if (url == null) {
url = "not specified";
}
String user = dbmgr.getUser();
if (user == null) {
user = "not specified";
}
String msgArgs[] = { String.valueOf(STORE_VERSION), dbmgr.getBrokerID(), url, user };
logger.logToAll(Logger.INFO,
br.getString(BrokerResources.I_JDBC_STORE_INFO, msgArgs));
if (createStore) {
logger.log(Logger.INFO, BrokerResources.I_STORE_AUTOCREATE_ENABLED);
} else {
logger.log(Logger.INFO, BrokerResources.I_STORE_AUTOCREATE_DISABLED);
}
msgEnumUseCursor = config.getBooleanProperty( MSG_ENUM_USE_CURSOR_PROP, !dbmgr.isHADB() );
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection( true );
// this will create, remove, reset, or upgrade old store
if ( !checkStore( conn ) ) {
// false=dont unlock; since tables are dropped already
closeDB(false);
return;
}
if ( Globals.getHAEnabled() ) {
try {
// Schedule inactive store session reaper for every 24 hrs.
long period = 86400000; // 24 hours
long delay = 60000 + (long)(Math.random() * 240000); // 1 - 5 mins
sessionReaper = new StoreSessionReaperTask(this);
Globals.getTimer().schedule(sessionReaper, delay, period);
logger.log(Logger.INFO, br.getKString(
br.I_STORE_SESSION_REAPER_SCHEDULED)+
"[delay="+delay+", period="+period+"]");
} catch (IllegalStateException e) {
logger.logStack(Logger.WARNING,
br.getKString(br.W_CANNOT_SCHEDULE_STORE_SESSION_REAPER), e);
}
} else {
// Lock the tables so that no other processes will access them
if ( config.getBooleanProperty( LOCK_STORE_PROP, true ) ) {
dbmgr.lockTables( conn, true );
}
}
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close( null, null, conn, myex );
}
dbmgr.setStoreInited(true);
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore instantiated.");
}
}
@Override
public void checkPartitionMode() throws BrokerException {
}
/**
* Get the JDBC store version.
* @return JDBC store version
*/
public final int getStoreVersion() {
return STORE_VERSION;
}
/**
* @return list of property settings that must be enforced cluster-wide consistent
*/
@Override
public Map getClusterMatchProperties()
throws BrokerException {
Map map = new LinkedHashMap();
if (partitionMode) {
map.put(PARTITION_MODE_PROP, "true");
if (partitionMigratable) {
map.put(PARTITION_MIGRATABLE_PROP, "true");
}
}
if (Globals.getHAEnabled()) {
map.put(StoreManager.STORE_TYPE_PROP, getStoreType());
}
return map;
}
/**
* Store a message, which is uniquely identified by it's SysMessageID,
* and it's list of interests and their states.
*
* @param message the message to be persisted
* @param iids an array of interest ids whose states are to be
* stored with the message
* @param states an array of states
* @param sync if true, will synchronize data to disk
* @exception BrokerException if a message with the same id exists
* in the store already
*/
public void storeMessage(DestinationUID dst, Packet message,
ConsumerUID[] iids, int[] states, boolean sync)
throws BrokerException {
if (partitionMode) {
throw new BrokerException(br.E_INTERNAL_ERROR+
" JDBCStore.storeMessage(,,,,,): unexpected call for partition mode ");
}
if (iids.length == 0 || iids.length != states.length) {
throw new BrokerException(br.getKString(
BrokerResources.E_BAD_INTEREST_LIST));
}
storeMessage(dst, message, iids, states, getStoreSession(), true);
}
/**
* Store a message which is uniquely identified by it's system message id.
*
* @param message the readonly packet to be persisted
* @param sync if true, will synchronize data to disk
* @exception BrokerException if a message with the same id exists
* in the store already
*/
public void storeMessage(DestinationUID dst, Packet message, boolean sync)
throws BrokerException {
if (partitionMode) {
throw new BrokerException(br.E_INTERNAL_ERROR+
" JDBCStore.storeMessage(,,,): unexpected call for partition mode ");
}
storeMessage(dst, message, null, null, getStoreSession(), true);
}
protected void storeMessage(DestinationUID dst, Packet message,
ConsumerUID[] iids, int[] states, long storeSessionID,
boolean checkMsgExist) throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
storeMessageInternal(dst, message, iids, states,
storeSessionID, checkMsgExist);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void storeMessageInternal(DestinationUID dst, Packet message,
ConsumerUID[] iids, int[] states, long storeSessionID,
boolean checkMsgExist) throws BrokerException {
if (message == null) {
throw new NullPointerException();
}
if (DEBUG) {
if (iids == null) {
logger.log(Logger.INFO,
"JDBCStore.storeMessageInternal("+dst+", "+
message.getSysMessageID().getUniqueName()+
", "+iids+", "+states+", "+storeSessionID+", "+checkMsgExist+")");
} else {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < iids.length; i++) {
buf.append("[consumer="+iids[i]+", state="+states[i]+"], ");
}
logger.log(Logger.INFO,
"JDBCStore.storeMessageInternal("+dst+", "+
message.getSysMessageID().getUniqueName()+
", "+buf.toString()+storeSessionID+", "+checkMsgExist+")");
}
}
boolean replaycheck = false;
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getMessageDAO().insert(null, dst, message, iids,
states, storeSessionID, message.getTimestamp(),
checkMsgExist, replaycheck);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
replaycheck = retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Move the message from one destination to another.
* The message will be stored in the target destination with the
* passed in consumers and their corresponding states.
* After the message is persisted successfully, the message in the
* original destination will be removed.
*
* @param message message to be moved
* @param from destination the message is currently in
* @param to destination to move the message to
* @param iids an array of interest ids whose states are to be
* stored with the message
* @param states an array of states
* @param sync if true, will synchronize data to disk.
* @exception IOException if an error occurs while moving the message
* @exception BrokerException if the message is not found in source
* destination
* @exception NullPointerException if message
,
* from
, to
,
* iids
, or states
is
* null
*/
public void moveMessage(Packet message, DestinationUID from,
DestinationUID to, ConsumerUID[] iids, int[] states, boolean sync)
throws BrokerException {
// make sure store is not closed then increment in progress count
super.checkClosedAndSetInProgress();
try {
moveMessageInternal(message, from, to, iids, states, sync);
} finally {
// decrement in progress count
super.setInProgress(false);
}
}
public void moveMessageInternal(Packet message, DestinationUID from,
DestinationUID to, ConsumerUID[] iids, int[] states, boolean sync)
throws BrokerException {
if (message == null || from == null || to == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.INFO,
"JDBCStore.moveMessageInternal("+message.getSysMessageID().getUniqueName()+
", "+from+", "+to+", "+iids+", "+states+", "+sync+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getMessageDAO().moveMessage(
null, message, from, to, iids, states);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Remove the message from the persistent store.
* If the message has an interest list, the interest list will be
* removed as well.
*
* @param dID the destination the message is associated with
* @param mID the system message id of the message to be removed
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the message is not found in the store
*/
public void removeMessage(DestinationUID dID, SysMessageID mID, boolean sync, boolean onRollback)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
removeMessageInternal(dID, mID, sync, onRollback);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void removeMessageInternal(DestinationUID dID, SysMessageID mID,
boolean sync, boolean onRollback)
throws BrokerException {
if (mID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.removeMessageInternal("+dID+", "+mID.getUniqueName()+
", "+sync+", "+onRollback+")");
}
boolean replaycheck = false;
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getMessageDAO().delete(null, dID, mID, replaycheck);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
replaycheck = retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Remove all messages associated with the specified destination
* from the persistent store.
*
* @param dst the destination whose messages are to be removed
* @param sync if true, will synchronize data to disk
* @exception IOException if an error occurs while removing the messages
* @exception BrokerException if the destination is not found in the store
* @exception NullPointerException if destination
is
* null
*/
public void removeAllMessages(Destination dst, boolean sync)
throws IOException, BrokerException {
if (dst == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.removeAllMessages("+dst.getUniqueName()+")");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getMessageDAO().deleteByDestinationBySession(
null, dst.getDestinationUID(), null);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Return an enumeration of all persisted messages for the given
* destination.
* Use the Enumeration methods on the returned object to fetch
* and load each message sequentially.
*
*
* This method is to be used at broker startup to load persisted
* messages on demand.
*
* @return an enumeration of all persisted messages, an empty
* enumeration will be returned if no messages exist for the
* destionation
* @exception BrokerException if an error occurs while getting the data
*/
public Enumeration messageEnumeration(Destination dst)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return messageEnumerationInternal(dst, null);
} catch (RuntimeException e) {
setInProgress(false);
throw e;
} catch (BrokerException e) {
setInProgress(false);
throw e;
} finally {
if (!msgEnumUseCursor) {
setInProgress(false);
}
}
}
public boolean getMessageEnumUseCursor() {
return msgEnumUseCursor;
}
public Enumeration messageEnumerationInternal(Destination dst, Long storeSession)
throws BrokerException {
if (dst == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.INFO,
"JDBCStore.messageEnumerationInternal("+dst.getUniqueName()+", "+storeSession+")");
}
String brokerID = dbmgr.getBrokerID();
if (!msgEnumUseCursor) {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getMessageDAO().messageEnumeration(
dst, brokerID, storeSession);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} else {
Enumeration en = null;
try {
Util.RetryStrategy retry = null;
do {
try {
en = daoFactory.getMessageDAO().
messageEnumerationCursor(dst, brokerID, storeSession);
dataEnums.add(en);
return en;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (Throwable e) {
if (en != null) {
dataEnums.remove(en);
((MessageEnumeration)en).close();
}
if (e instanceof BrokerException) {
throw (BrokerException)e;
}
throw new BrokerException(e.toString(), e);
}
}
}
public void closeEnumeration(Enumeration en) {
if (!(en instanceof MessageEnumeration)) {
return;
}
try {
closeEnumerationInternal(en);
} finally {
setInProgress(false);
}
}
public void closeEnumerationInternal(Enumeration en) {
dataEnums.remove(en);
((MessageEnumeration)en).close();
}
/**
* Return the number of persisted messages for the given broker.
*
* @return the number of persisted messages for the given broker
* @exception BrokerException if an error occurs while getting the data
*/
public int getMessageCount(String brokerID) throws BrokerException {
if (brokerID == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG,
"JDBCStore.getMessageCount() called for broker: " + brokerID);
}
// make sure store is not closed then increment in progress count
super.checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getMessageDAO().getMessageCount(null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Return the number of persisted messages and total number of bytes for
* the given destination.
*
* @param dst the destination whose messages are to be counted
* @return A HashMap of name value pair of information
* @throws BrokerException if an error occurs while getting the data
*/
public HashMap getMessageStorageInfo(Destination dst)
throws BrokerException {
// make sure store is not closed then increment in progress count
super.checkClosedAndSetInProgress();
try {
return getMessageStorageInfoInternal(dst, null);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public HashMap getMessageStorageInfoInternal(Destination dst, Long storeSession)
throws BrokerException {
if (dst == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.INFO,
"JDBCStore.getMessageStorageInfoInternal("+dst.getUniqueName()+", "+storeSession+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getMessageDAO().getMessageStorageInfo(null, dst, storeSession);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Return the message with the specified message id.
*
* @param dID the destination the message is associated with
* @param mID the system message id of the message to be retrieved
* @return a message
* @exception BrokerException if the message is not found in the store
* or if an error occurs while getting the data
*/
public Packet getMessage(DestinationUID dID, SysMessageID mID)
throws BrokerException {
if (mID == null) {
throw new NullPointerException();
}
return getMessage(dID, mID.toString());
}
/**
* Return the message with the specified message id.
*
* @param dID the destination the message is associated with
* @param mID the message id of the message to be retrieved
* @return a message
* @exception BrokerException if the message is not found in the store
* or if an error occurs while getting the data
*/
public Packet getMessage(DestinationUID dID, String mID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
return getMessageInternal(dID, mID);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public Packet getMessageInternal(DestinationUID dID, String mID)
throws BrokerException {
if (mID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO, "JDBCStore.getMessageInternal("+dID+", "+mID+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getMessageDAO().getMessage(null, dID, mID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Store the given list of interests and their states with the
* specified message. The message should not have an interest
* list associated with it yet.
*
* @param dID the destination the message is associated with
* @param mID system message id of the message that the interest
* is associated with
* @param iids an array of interest ids whose states are to be
* stored
* @param states an array of states
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the message is not in the store;
* if there's an interest list associated with
* the message already; or if an error occurs
* while persisting the data
*/
public void storeInterestStates(DestinationUID dID,
SysMessageID mID, ConsumerUID[] iids, int[] states, boolean sync, Packet msg)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
storeInterestStatesInternal(dID, mID, iids, states, sync, msg);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void storeInterestStatesInternal(DestinationUID dID,
SysMessageID mID, ConsumerUID[] iids, int[] states, boolean sync, Packet msg)
throws BrokerException {
if (mID == null || iids == null || states == null) {
throw new NullPointerException();
}
if (iids.length == 0 || iids.length != states.length) {
throw new BrokerException(br.getKString(BrokerResources.E_BAD_INTEREST_LIST));
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeInterestStatesInternal("+dID+", "+
mID.getUniqueName()+", "+iids+", "+states+")");
}
boolean replaycheck = false;
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerStateDAO().insert(
null, dID.toString(), mID, iids, states, true, replaycheck);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
replaycheck = retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Update the state of the interest associated with the specified
* message. If the message does not have an interest list associated
* with it, the interest list will be created. If the interest is not
* in the interest list, it will be added to the interest list.
*
* @param dID the destination the message is associated with
* @param mID system message id of the message that the interest
* is associated with
* @param iID id of the interest whose state is to be updated
* @param state state of the interest
* @param sync if true, will synchronize data to disk
* @param txid current transaction id. Unused by jdbc store
* @param isLastAck Unused by jdbc store
* @exception BrokerException if the message is not in the store
*/
public void updateInterestState(DestinationUID dID,
SysMessageID mID, ConsumerUID iID, int state, boolean sync, TransactionUID txid, boolean isLastAck)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
updateInterestStateInternal(dID, mID, iID, state, sync, txid, isLastAck);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void updateInterestStateInternal(DestinationUID dID,
SysMessageID mID, ConsumerUID iID, int state, boolean sync, TransactionUID txid, boolean isLastAck)
throws BrokerException {
if (mID == null || iID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateInterestStateInternal("+dID+", "+ mID.getUniqueName()+
", "+iID.toString()+", "+state+", "+sync+", "+txid+", "+isLastAck+")");
}
boolean replaycheck = false;
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerStateDAO().updateState(null, dID, mID, iID, state, replaycheck);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
replaycheck = retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Update the state of the interest associated with the specified
* message. If the message does not have an interest list associated
* with it, the interest list will be created. If the interest is not
* in the interest list, it will be added to the interest list.
*
* @param dID the destination the message is associated with
* @param mID system message id of the message that the interest
* is associated with
* @param iID id of the interest whose state is to be updated
* @param newState state of the interest
* @param expectedState the expected state
* @exception BrokerException if the message is not in the store
*/
public void updateInterestState(DestinationUID dID,
SysMessageID mID, ConsumerUID iID, int newState, int expectedState)
throws BrokerException {
if (mID == null || iID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.updateInterestState() called with message: " +
mID.getUniqueName() + ", consumer: " + iID.toString() +
", state=" + newState + ", expected: " + expectedState);
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerStateDAO().updateState(
null, dID, mID, iID, newState, expectedState);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Get the state of the interest associated with the specified message.
*
* @param dID the destination the message is associated with
* @param mID system message id of the message that the interest
* is associated with
* @param iID id of the interest whose state is to be returned
* @return state of the interest
* @exception BrokerException if the specified interest is not
* associated with the message; or if the message is not in the
* store
*/
public int getInterestState(
DestinationUID dID, SysMessageID mID, ConsumerUID iID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getInterestStateInternal(dID, mID, iID);
} finally {
setInProgress(false);
}
}
public int getInterestStateInternal(
DestinationUID dID, SysMessageID mID, ConsumerUID iID)
throws BrokerException {
if (mID == null || dID == null || iID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getInterestStateInternal("+dID+", "+mID.getUniqueName()+", "+iID+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(true);
Util.RetryStrategy retry = null;
do {
try {
// check existence of message
daoFactory.getMessageDAO().checkMessage(
conn, dID.toString(), mID.getUniqueName());
return daoFactory.getConsumerStateDAO().getState(conn, mID, iID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
public HashMap getInterestStates(DestinationUID dID, SysMessageID mID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getInterestStatesInternal(dID, mID);
} finally {
setInProgress(false);
}
}
public HashMap getInterestStatesInternal(DestinationUID dID, SysMessageID mID)
throws BrokerException {
if (mID == null || dID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getInterestStatesInternal("+dID+", "+mID.getUniqueName()+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(true);
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getConsumerStateDAO().getStates(conn, mID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
/**
* Retrieve all interest IDs associated with the specified message.
* Note that the state of the interests returned is either
* INTEREST_STATE_ROUTED or INTEREST_STATE_DELIVERED, i.e., interest
* whose state is INTEREST_STATE_ACKNOWLEDGED will not be returned in the
* array.
*
* @param dID the destination the message is associated with
* @param mID system message id of the message whose interests
* are to be returned
* @return an array of ConsumerUID objects associated with the message; a
* zero length array will be returned if no interest is
* associated with the message
* @exception BrokerException if the message is not in the store
*/
public ConsumerUID[] getConsumerUIDs(DestinationUID dID, SysMessageID mID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getConsumerUIDsInternal(dID, mID);
} finally {
setInProgress(false);
}
}
public ConsumerUID[] getConsumerUIDsInternal(DestinationUID dID, SysMessageID mID)
throws BrokerException {
if (mID == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getConsumerUIDsInternal("+dID+", "+mID.getUniqueName()+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(true);
Util.RetryStrategy retry = null;
do {
try {
// check existence of message
daoFactory.getMessageDAO().checkMessage(
conn, dID.toString(), mID.getUniqueName());
return (ConsumerUID[])
daoFactory.getConsumerStateDAO().getConsumerUIDs(conn, mID).toArray(
new ConsumerUID[0]);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close( null, null, conn, myex );
}
}
/**
* Store an Interest which is uniquely identified by it's id.
*
* @param interest the interest to be persisted
* @param sync if true, will synchronize data to disk
* @exception IOException if an error occurs while persisting the interest
* @exception BrokerException if an interest with the same id exists in
* the store already
*/
public void storeInterest(Consumer interest, boolean sync)
throws IOException, BrokerException {
if (interest == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeInterest("+
interest.getConsumerUID().toString()+", "+sync+")");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerDAO().insert(null, interest,
System.currentTimeMillis());
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Remove the interest from the persistent store.
*
* @param interest the interest to be removed from persistent store
* @param sync if true, will synchronize data to disk
* @exception IOException if an error occurs while removing the interest
* @exception BrokerException if the interest is not found in the store
*/
public void removeInterest(Consumer interest, boolean sync)
throws IOException, BrokerException {
if (interest == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.removeInterest() called with interest: " +
interest.getConsumerUID().toString());
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerDAO().delete(null, interest);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Retrieve all interests in the store.
* Will return as many interests as we can read.
* Any interests that are retrieved unsuccessfully will be logged as a
* warning.
*
* @return an array of Interest objects; a zero length array is
* returned if no interests exist in the store
* @exception IOException if an error occurs while getting the data
*/
public Consumer[] getAllInterests() throws IOException, BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getAllInterests() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return (Consumer[])
daoFactory.getConsumerDAO().getAllConsumers(null).toArray(
new Consumer[0]);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Store a Destination.
*
* @param destination the destination to be persisted
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the same destination exists
* the store already
* @exception NullPointerException if destination
is
* null
*/
public void storeDestination(Destination destination, boolean sync)
throws BrokerException {
checkClosedAndSetInProgress();
try {
storeDestinationInternal(destination, getStoreSession());
} finally {
setInProgress(false);
}
}
protected void storeDestination(Destination destination, long storeSession)
throws BrokerException {
checkClosedAndSetInProgress();
try {
storeDestinationInternal(destination, storeSession);
} finally {
setInProgress(false);
}
}
public void storeDestinationInternal(Destination destination, long storeSessionID)
throws BrokerException {
if (destination == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeDestinationInternal("+destination.getUniqueName()+", "+storeSessionID+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getDestinationDAO().insert(null, destination,
storeSessionID, 0, System.currentTimeMillis());
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Update the specified destination.
*
* @param destination the destination to be updated
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the destination is not found in the store
* or if an error occurs while updating the
* destination
*/
public void updateDestination(Destination destination, boolean sync)
throws BrokerException {
checkClosedAndSetInProgress();
try {
updateDestinationInternal(destination);
} finally {
setInProgress(false);
}
}
public void updateDestinationInternal(Destination destination)
throws BrokerException {
if (destination == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateDestinationInternal("+destination.getUniqueName()+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getDestinationDAO().update(null, destination);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Remove the destination from the persistent store.
*
* @param destination the destination to be removed
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the destination is not found in the store
*/
public void removeDestination(Destination destination, boolean sync)
throws BrokerException {
checkClosedAndSetInProgress();
try {
removeDestinationInternal(destination, null);
} finally {
setInProgress(false);
}
}
public void removeDestinationInternal(Destination destination, Long storeSessionID)
throws BrokerException {
if (destination == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.removeDestinationInternal("+destination.getUniqueName()+", "+storeSessionID+")");
}
Util.RetryStrategy retry = null;
do {
try {
boolean isDeleted =
daoFactory.getDestinationDAO().delete(null, destination, storeSessionID);
if (destination.isAutoCreated() && Globals.getHAEnabled() &&
storeSessionID == null) {
DestinationUID dstID = destination.getDestinationUID();
synchronized(pendingDeleteDsts) {
if (isDeleted) {
pendingDeleteDsts.remove(dstID);
} else {
pendingDeleteDsts.put(dstID,
Integer.valueOf(destination.getType()));
}
}
}
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Reap auto-created destinations.
*
* Only applicable for broker running in HA mode and will should be invoked
* when a broker is removed from the cluster.
*
* @exception BrokerException
*/
public void reapAutoCreatedDestinations()
throws BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.reapAutoCreatedDestinations() called" );
}
if (!Globals.getHAEnabled()) {
return; // No-op
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
synchronized (pendingDeleteDsts) {
if (!pendingDeleteDsts.isEmpty()) {
// Iterate over the auto-created dst pending removal
// list and see if any can be removed from the DB
DestinationDAO dao = daoFactory.getDestinationDAO();
Iterator itr = pendingDeleteDsts.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry e = (Map.Entry)itr.next();
DestinationUID dst = (DestinationUID)e.getKey();
int type = ((Integer)e.getValue()).intValue();
if (dao.delete(null, dst, type)) {
logger.log(Logger.DEBUG,
"Auto-created destination " + dst +
" has been removed from HA Store");
// Remove from pending list if it is reaped
itr.remove();
}
}
}
}
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Retrieve a destination in the store.
*
* @param id the destination ID
* @return a Destination object
* @throws BrokerException if no destination exist in the store
*/
public Destination getDestination(DestinationUID id) throws BrokerException {
checkClosedAndSetInProgress();
try {
return getDestinationInternal(id);
} finally {
setInProgress(false);
}
}
public Destination getDestinationInternal(DestinationUID id) throws BrokerException {
if (id == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getDestinationInternal("+id+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getDestinationDAO().getDestination(null, id.toString());
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Retrieve all destinations in the store.
*
* @return an array of Destination objects; a zero length array is
* returned if no destinations exist in the store
* @exception IOException if an error occurs while getting the data
*/
public Destination[] getAllDestinations() throws BrokerException {
checkClosedAndSetInProgress();
try {
return getAllDestinationsInternal(dbmgr.getBrokerID(), null);
} finally {
setInProgress(false);
}
}
/**
* Retrieve all destinations in the store for the specified broker ID.
*
* @param brokerID the broker ID
* @return an array of Destination objects; a zero length array is
* returned if no destinations exist in the store
* @exception IOException if an error occurs while getting the data
*/
protected Destination[] getAllDestinations(String brokerID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getAllDestinationsInternal(brokerID, null);
} finally {
setInProgress(false);
}
}
public Destination[] getAllDestinationsInternal(Long storeSessionID)
throws BrokerException {
return getAllDestinationsInternal(dbmgr.getBrokerID(), storeSessionID);
}
/**
* currently storeSessionID, added for partitioned store, is ignored
*/
public Destination[] getAllDestinationsInternal(String brokerID, Long storeSessionID)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getAllDestinationsInternal("+brokerID+", "+storeSessionID+")");
}
Util.RetryStrategy retry = null;
do {
try {
return (Destination[])
daoFactory.getDestinationDAO().getAllDestinations(
null, brokerID).toArray(new Destination[0]);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Store a transaction.
*
* @param id the id of the transaction to be persisted
* @param ts the transaction state to be persisted
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the same transaction id exists
* the store already
* @exception NullPointerException if id
is
* null
*/
public void storeTransaction(TransactionUID id, TransactionState ts,
boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
storeTransactionInternal(id, ts, sync, getStoreSession());
} finally {
setInProgress(false);
}
}
public void storeTransactionInternal(TransactionUID id, TransactionState ts,
boolean sync, long storeSession) throws BrokerException {
if (id == null || ts == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeTransactionInternal("+
id+", "+ts+", "+sync+", "+storeSession+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().insert(
null, id, ts, storeSession);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Remove the transaction from the persistent store.
*
* @param id the id of the transaction to be removed
* @param removeAcks if true, will remove all associated acknowledgements
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the transaction is not found
* in the store
*/
public void removeTransaction(TransactionUID id, boolean removeAcks,
boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
removeTransactionInternal(id, removeAcks, sync);
} finally {
setInProgress(false);
}
}
public void removeTransactionInternal(TransactionUID id, boolean removeAcks,
boolean sync) throws BrokerException {
if (id == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.removeTransactionInternal("+id+", "+removeAcks+", "+sync+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(false);
Util.RetryStrategy retry = null;
do {
try {
// First, remove the acks
if (removeAcks) {
daoFactory.getConsumerStateDAO().clearTransaction(conn, id);
}
// Now, remove the txn
daoFactory.getTransactionDAO().delete(conn, id);
conn.commit();
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
try {
retry.assertShouldRetry( e, conn );
} catch (RetrySQLRecoverableException ee) {
try {
Util.close(null, null, conn, ee);
conn = dbmgr.getConnection(false);
} catch (Exception eee) {
logger.logStack(Logger.WARNING, eee.getMessage(), eee);
conn = null;
if (e instanceof BrokerException) {
throw (BrokerException)e;
}
throw new BrokerException(e.getMessage(), e);
}
}
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
/**
* Update the state of a transaction
*
* @param id the transaction id to be updated
* @param ts the new transaction state
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the transaction id does NOT exists in
* the store already
* @exception NullPointerException if id
is
* null
*/
public void updateTransactionState(TransactionUID id, TransactionState ts,
boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
updateTransactionStateInternal(id, ts, sync);
} finally {
setInProgress(false);
}
}
public void updateTransactionStateInternal(TransactionUID id, TransactionState ts,
boolean sync) throws BrokerException {
if (id == null || ts == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateTransactionStateInternal("+id+", "+ts+", "+sync+")");
}
boolean replaycheck = false;
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().updateTransactionState(null, id, ts, replaycheck);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
replaycheck = retry.assertShouldRetry( e );
}
} while ( true );
}
public void updateTransactionStateWithWork(TransactionUID id,
TransactionState ts, TransactionWork txnwork, boolean sync)
throws BrokerException {
if (partitionMode) {
throw new BrokerException(br.E_INTERNAL_ERROR+
" JDBCStore.updateTransactionStateWithWork(): Unexpected call for partition mode");
}
checkClosedAndSetInProgress();
try {
updateTransactionStateWithWorkInternal(id, ts, txnwork, getStoreSession(), sync);
} finally {
setInProgress(false);
}
}
public void updateTransactionStateWithWorkInternal(TransactionUID tid,
TransactionState ts, TransactionWork txnwork, long storeSessionID, boolean sync)
throws BrokerException {
if (tid == null || ts == null || txnwork == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateTransactionStateInternal("+tid+", "+ts+", "+", "+txnwork+", "+sync+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(false);
Util.RetryStrategy retry = null;
do {
boolean inside = false;
try {
Iterator itr1 = txnwork.getSentMessages().iterator();
while (itr1.hasNext()) {
TransactionWorkMessage txnmsg = itr1.next();
Packet m = txnmsg.getMessage();
if (m == null) {
continue;
}
inside = true;
daoFactory.getMessageDAO().insert(conn, txnmsg.getDestUID(),
m, null, null, storeSessionID, m.getTimestamp(), true, false);
inside = false;
}
if (FI.FAULT_INJECTION) {
try {
FI.checkFaultAndThrowBrokerException(
FaultInjection.FAULT_TXN_PERSIST_WORK_1_5, null);
} catch (BrokerException e) {
FI.unsetFault(FI.FAULT_TXN_PERSIST_WORK_1_5);
throw e;
}
}
List txnacks = txnwork.getMessageAcknowledgments();
if (txnacks != null) {
Iterator itr2 = txnacks.iterator();
while (itr2.hasNext()) {
TransactionWorkMessageAck txnack = itr2.next();
TransactionAcknowledgement ta = txnack.getTransactionAcknowledgement();
if (ta != null) {
inside = true;
daoFactory.getConsumerStateDAO().updateTransaction(conn,
ta.getSysMessageID(), ta.getStoredConsumerUID(), tid);
inside = false;
}
}
}
inside = true;
daoFactory.getTransactionDAO().updateTransactionState(conn, tid, ts, false);
inside = false;
conn.commit();
return;
} catch ( Exception e ) {
if (!inside) {
try {
conn.rollback();
} catch ( SQLException rbe ) {
logger.logStack(Logger.WARNING,
BrokerResources.X_DB_ROLLBACK_FAILED, rbe);
}
}
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
try {
retry.assertShouldRetry( e, conn );
} catch (RetrySQLRecoverableException ee) {
try {
Util.close(null, null, conn, ee);
conn = dbmgr.getConnection(false);
} catch (Exception eee) {
logger.logStack(Logger.WARNING, eee.getMessage(), eee);
conn = null;
if (e instanceof BrokerException) {
throw (BrokerException)e;
}
throw new BrokerException(e.getMessage(), e);
}
}
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
/**
* Retrieve all transaction ids in the store with their state
*
* @return a HashMap. The key is a TransactionUID.
* The value is a TransactionState.
* @exception IOException if an error occurs while getting the data
*/
public HashMap getAllTransactionStates()
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getAllTransactionStatesInternal(null);
} finally {
setInProgress(false);
}
}
public HashMap getAllTransactionStatesInternal(Long storeSession)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getAllTransactionStatesInternal("+storeSession+")");
}
String brokerID = dbmgr.getBrokerID();
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionStatesByBroker(
null, brokerID, storeSession);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public HashMap getAllRemoteTransactionStates()
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getAllRemoteTransactionStatesInternal(null);
} finally {
setInProgress(false);
}
}
public HashMap getAllRemoteTransactionStatesInternal(Long storeSession)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getAllRemoteTransactionStatesInternal("+storeSession+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getRemoteTransactionStatesByBroker(
null, dbmgr.getBrokerID(), storeSession);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Store the acknowledgement for the specified transaction.
*
* @param tid the transaction id with which the acknowledgment is to
* be stored
* @param ack the acknowledgement to be stored
* @param sync if true, will synchronize data to disk
* @exception BrokerException if the transaction id is not found in the
* store, if the acknowledgement already
* exists, or if it failed to persist the data
*/
public void storeTransactionAck(TransactionUID tid,
TransactionAcknowledgement ack, boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
storeTransactionAckInternal(tid, ack, sync);
} finally {
setInProgress(false);
}
}
public void storeTransactionAckInternal(TransactionUID tid,
TransactionAcknowledgement ack, boolean sync) throws BrokerException {
if (tid == null || ack == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeTransactionAckInternal("+tid+", "+ack+", "+sync+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerStateDAO().updateTransaction(null,
ack.getSysMessageID(), ack.getStoredConsumerUID(), tid);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Remove all acknowledgements associated with the specified
* transaction from the persistent store.
*
* From 4.0 onward, acknowledgement is implemented as a TRANSACTION_ID
* column on the message and consumer state table so to remove the acks
* is the same as clear txnID from the column.
*
* @param tid the transaction id whose acknowledgements are
* to be removed
* @param sync if true, will synchronize data to disk
* @exception BrokerException if error occurs while removing the
* acknowledgements
*/
public void removeTransactionAck(TransactionUID tid, boolean sync)
throws BrokerException {
checkClosedAndSetInProgress();
try {
removeTransactionAckInternal(tid, sync);
} finally {
setInProgress(false);
}
}
public void removeTransactionAckInternal(TransactionUID tid, boolean sync)
throws BrokerException {
if (tid == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.removeTransactionAckInternal("+tid+", "+sync+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConsumerStateDAO().clearTransaction(null, tid);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Retrieve all acknowledgement list in the persistence store together
* with their associated transaction id. The data is returned in the
* form a HashMap. Each entry in the HashMap has the transaction id as
* the key and an array of the associated TransactionAcknowledgement
* objects as the value.
* @return a HashMap object containing all acknowledgement lists in the
* persistence store
*/
public HashMap getAllTransactionAcks() throws BrokerException {
checkClosedAndSetInProgress();
try {
return getAllTransactionAcksInternal(null);
} finally {
setInProgress(false);
}
}
public HashMap getAllTransactionAcksInternal(Long storeSession)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO, "JDBCStore.getAllTransactionAcksInternal("+storeSession+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getConsumerStateDAO().getAllTransactionAcks(null);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
/**
* Retrieve all acknowledgements for the specified transaction.
*
* @param id id of the transaction whose acknowledgements
* are to be returned
* @exception BrokerException if the transaction id is not in the store
*/
public TransactionAcknowledgement[] getTransactionAcks(
TransactionUID id) throws BrokerException {
checkClosedAndSetInProgress();
try {
return getTransactionAcksInternal(id);
} finally {
setInProgress(false);
}
}
public TransactionAcknowledgement[] getTransactionAcksInternal(TransactionUID id)
throws BrokerException {
if (id == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO, "JDBCStore.getTransactionAcksInternal("+id+")");
}
Util.RetryStrategy retry = null;
do {
try {
return (TransactionAcknowledgement[])
daoFactory.getConsumerStateDAO().getTransactionAcks(null, id).toArray(
new TransactionAcknowledgement[0]);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public void storeTransaction(TransactionUID tid, TransactionInfo txnInfo,
boolean sync) throws BrokerException {
storeTransaction(tid, txnInfo, getStoreSession());
}
protected void storeTransaction(TransactionUID tid, TransactionInfo txnInfo,
long storeSessionID) throws BrokerException {
if (tid == null || txnInfo == null) {
throw new NullPointerException();
}
int type = TransactionInfo.TXN_NOFLAG;
BrokerAddress txnHomeBroker = null;
TransactionBroker[] txnBrokers = null;
if (txnInfo.isCluster()) {
type = TransactionInfo.TXN_CLUSTER;
txnBrokers = txnInfo.getTransactionBrokers();
} else if (txnInfo.isRemote()) {
type = TransactionInfo.TXN_REMOTE;
txnHomeBroker = txnInfo.getTransactionHomeBroker();
} else if (txnInfo.isLocal()) {
type = TransactionInfo.TXN_LOCAL;
} else {
String errorMsg = "Illegal transaction type: " + txnInfo.getType();
logger.log( Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR,
errorMsg );
throw new BrokerException(
br.getKString( BrokerResources.E_INTERNAL_BROKER_ERROR, errorMsg ) );
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().insert(null, tid,
txnInfo.getTransactionState(), txnHomeBroker,
txnBrokers, type, storeSessionID);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void storeClusterTransaction(TransactionUID tid, TransactionState ts,
TransactionBroker[] txnBrokers, boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
storeClusterTransactionInternal(tid, ts, txnBrokers, sync, getStoreSession());
} finally {
setInProgress(false);
}
}
public void storeClusterTransactionInternal(TransactionUID tid, TransactionState ts,
TransactionBroker[] txnBrokers, boolean sync, long storeSession)
throws BrokerException {
if (tid == null || ts == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO, "JDBCStore.storeClusterTransactionInternal("+
tid+", "+ts+", "+txnBrokers+", "+sync+", "+storeSession+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().insert(null, tid, ts, null,
txnBrokers, TransactionInfo.TXN_CLUSTER, storeSession);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public void updateClusterTransaction(TransactionUID tid,
TransactionBroker[] txnBrokers, boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
updateClusterTransactionInternal(tid, txnBrokers, sync);
} finally {
setInProgress(false);
}
}
public void updateClusterTransactionInternal(TransactionUID tid,
TransactionBroker[] txnBrokers, boolean sync) throws BrokerException {
if (tid == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateClusterTransactionInternal("+tid+", "+txnBrokers+", "+sync+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().updateTransactionBrokers(null, tid, txnBrokers);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public void updateClusterTransactionBrokerState(TransactionUID tid,
int expectedTxnState, TransactionBroker txnBroker, boolean sync)
throws BrokerException {
checkClosedAndSetInProgress();
try {
updateClusterTransactionBrokerStateInternal(tid, expectedTxnState, txnBroker, sync);
} finally {
setInProgress(false);
}
}
public void updateClusterTransactionBrokerStateInternal(TransactionUID tid,
int expectedTxnState, TransactionBroker txnBroker, boolean sync)
throws BrokerException {
if (tid == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateClusterTransactionBrokerStateInternal("+
tid+", "+expectedTxnState+", "+txnBroker+", "+sync+")");
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().updateTransactionBrokerState(
null, tid, expectedTxnState, txnBroker);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public void updateRemoteTransaction(TransactionUID tid,
TransactionAcknowledgement[] txnAcks,
BrokerAddress txnHomeBroker, boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
updateRemoteTransactionInternal(tid, txnAcks, txnHomeBroker, sync);
} finally {
setInProgress(false);
}
}
public void updateRemoteTransactionInternal(TransactionUID tid,
TransactionAcknowledgement[] txnAcks,
BrokerAddress txnHomeBroker, boolean sync) throws BrokerException {
if (tid == null) {
throw new NullPointerException();
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.updateRemoteTransactionInternal("+
tid+", "+txnAcks+", "+txnHomeBroker+", "+sync+")");
}
if (!Globals.getHAEnabled()) {
throw new UnsupportedOperationException(
"Operation not supported by the " + getStoreType() +
" store in non-HA mode" );
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(false);
Util.RetryStrategy retry = null;
do {
try {
//store the acks if any
if (txnAcks != null && txnAcks.length > 0) {
for (int i = 0, len = txnAcks.length; i < len; i++) {
TransactionAcknowledgement ack = txnAcks[i];
if (ack.shouldStore()) {
daoFactory.getConsumerStateDAO().updateTransaction(
conn, ack.getSysMessageID(),
ack.getStoredConsumerUID(),
tid);
}
}
}
// In HA mode, the txn is owned by another broker
// so we'll only update the txn home broker
daoFactory.getTransactionDAO().updateTransactionHomeBroker(
conn, tid, txnHomeBroker);
conn.commit();
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
public void storeRemoteTransaction(TransactionUID tid, TransactionState ts,
TransactionAcknowledgement[] txnAcks, BrokerAddress txnHomeBroker,
boolean sync) throws BrokerException {
checkClosedAndSetInProgress();
try {
storeRemoteTransactionInternal(tid, ts, txnAcks,
txnHomeBroker, sync, getStoreSession());
} finally {
setInProgress(false);
}
}
public void storeRemoteTransactionInternal(TransactionUID tid, TransactionState ts,
TransactionAcknowledgement[] txnAcks, BrokerAddress txnHomeBroker,
boolean sync, long storeSession) throws BrokerException {
if (tid == null) {
throw new NullPointerException();
}
if (Globals.getHAEnabled()) {
throw new UnsupportedOperationException(
"Operation not supported by the "+getStoreType()+" store in HA mode" );
}
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.storeRemoteTransactionInternal("+
tid+", "+ts+", "+txnAcks+", "+txnHomeBroker+", "+sync+")");
}
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(false);
Util.RetryStrategy retry = null;
do {
try {
// First, store the txn
daoFactory.getTransactionDAO().insert(
conn, tid, ts, txnHomeBroker, null,
TransactionInfo.TXN_REMOTE, storeSession);
// Now, store the acks if any
if (txnAcks != null && txnAcks.length > 0) {
for (int i = 0, len = txnAcks.length; i < len; i++) {
TransactionAcknowledgement ack = txnAcks[i];
if (ack.shouldStore()) {
daoFactory.getConsumerStateDAO().updateTransaction(
conn, ack.getSysMessageID(),
ack.getStoredConsumerUID(),
tid);
}
}
}
conn.commit();
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close(null, null, conn, myex);
}
}
/**
* Persist the specified property name/value pair.
* If the property identified by name exists in the store already,
* it's value will be updated with the new value.
* If value is null, the property will be removed.
* The value object needs to be serializable.
*
* @param name name of the property
* @param value value of the property
* @param sync if true, will synchronize data to disk
* @exception BrokerException if an error occurs while persisting the data
* @exception NullPointerException if name
is
* null
*/
public void updateProperty(String name, Object value, boolean sync)
throws BrokerException {
if (name == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG,
"JDBCStore.updateProperty() called with name: " + name);
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getPropertyDAO().update(null, name, value);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Retrieve the value for the specified property.
*
* @param name name of the property whose value is to be retrieved
* @return the property value; null is returned if the specified
* property does not exist in the store
* @exception BrokerException if an error occurs while retrieving the
* data
* @exception NullPointerException if name
is
* null
*/
public Object getProperty(String name) throws BrokerException {
if (name == null) {
throw new NullPointerException();
}
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG,
"JDBCStore.getProperty() called with name: " + name);
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getPropertyDAO().getProperty( null, name);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Return the names of all persisted properties.
*
* @return an array of property names; an empty array will be returned
* if no property exists in the store.
*/
public String[] getPropertyNames() throws BrokerException {
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG, "JDBCStore.getPropertyNames() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return (String[])
daoFactory.getPropertyDAO().getPropertyNames(null).toArray(
new String[0]);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Return all persisted properties.
*
* @return a properties object.
*/
public Properties getAllProperties() throws BrokerException {
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG, "JDBCStore.getAllProperties() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getPropertyDAO().getProperties(null);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Append a new record to the config change record store.
* The timestamp is also persisted with the recordData.
* The config change record store is an ordered list (sorted
* by timestamp).
*
* @param createdTime The time when this record was created.
* @param recordData The record data.
* @param sync if true, will synchronize data to disk
* @exception BrokerException if an error occurs while persisting
* the data or if the timestamp is less than 0
* @exception NullPointerException if recordData
is
* null
*/
public void storeConfigChangeRecord(long createdTime, byte[] recordData,
boolean sync) throws BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.storeConfigChangeRecord() called");
}
if (createdTime <= 0) {
String ts = String.valueOf(createdTime);
logger.log(Logger.ERROR, BrokerResources.E_INVALID_TIMESTAMP, ts);
throw new BrokerException(
br.getKString(BrokerResources.E_INVALID_TIMESTAMP, ts));
}
if (recordData == null) {
throw new NullPointerException();
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConfigRecordDAO().insert(null, recordData, createdTime);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Get all the config change records since the given timestamp.
* Retrieves all the entries with recorded timestamp greater than
* the specified timestamp.
*
* @return a list of ChangeRecordInfo, empty list if no record
*/
public ArrayList getConfigChangeRecordsSince(long timeStamp)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.getConfigChangeRecordsSince() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return (ArrayList)daoFactory.getConfigRecordDAO().getRecordsSince(
null, timeStamp);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Return all config records with their corresponding timestamps.
*
* @return a list of ChangeRecordInfo
* @exception BrokerException if an error occurs while getting the data
*/
public List getAllConfigRecords() throws BrokerException {
if (Store.getDEBUG()) {
logger.log(Logger.DEBUG,
"JDBCStore.getAllConfigRecords() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getConfigRecordDAO().getAllRecords(null);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
/**
* Clear all config change records in the store.
*
* @param sync if true, will synchronize data to disk
* @exception BrokerException if an error occurs while clearing the data
*/
public void clearAllConfigChangeRecords(boolean sync)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG,
"JDBCStore.clearAllConfigChangeRecords() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getConfigRecordDAO().deleteAll(null);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void clearAll(boolean sync) throws BrokerException {
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.clearAll() called");
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection(false);
Util.RetryStrategy retry = null;
do {
try {
if (Globals.getHAEnabled()) {
// In HA mode, only reset txns, dsts, states, and msgs
// in the specified order
daoFactory.getTransactionDAO().deleteAll(conn);
daoFactory.getDestinationDAO().deleteAll(conn);
daoFactory.getConsumerStateDAO().deleteAll(conn);
daoFactory.getMessageDAO().deleteAll(conn);
daoFactory.getTMLogRecordDAOJMSBG().deleteAll(conn);
daoFactory.getJMSBGDAO().deleteAll(conn);
} else {
List daos = daoFactory.getAllDAOs();
Iterator itr = daos.iterator();
while (itr.hasNext()) {
BaseDAO dao = (BaseDAO)itr.next();
if ( !(dao instanceof VersionDAO ||
dao instanceof BrokerDAO ||
dao instanceof StoreSessionDAO) ) {
dao.deleteAll(conn);
}
}
}
conn.commit();
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch ( Exception e ) {
myex = e;
throw new BrokerException(
br.getKString( BrokerResources.X_CLEAR_ALL_FAILED ), e );
} finally {
try {
Util.close(null, null, conn, myex);
} finally {
// decrement in progress count
setInProgress(false);
}
}
}
public void close(boolean cleanup) {
// make sure all operations are done before we proceed to close
setClosedAndWait();
if (partitionMode) {
PartitionedStore pstore = null;
synchronized(partitionStores) {
Iterator itr = partitionStores.values().iterator();
while (itr.hasNext()) {
pstore = itr.next();
pstore.close();
}
}
}
// true = unlock the tables
closeDB(true);
dbmgr.setStoreInited(false);
if (DEBUG) {
logger.log(Logger.INFO, "JDBCStore.close("+ cleanup +") done.");
}
}
protected void beforeWaitOnClose() {
Iterator itr = null;
synchronized(dataEnums) {
itr = dataEnums.iterator();
Enumeration en = null;
while (itr.hasNext()) {
en = itr.next();
if (en instanceof MessageEnumeration) {
((MessageEnumeration)en).cancel();
}
}
}
if (dbmgr != null) {
dbmgr.setIsClosing();
}
}
// HA operations
public long getBrokerHeartbeat(String brokerID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getHeartbeat(null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public HashMap getAllBrokerHeartbeats() throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getAllHeartbeats(null);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public Long updateBrokerHeartbeat(String brokerID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().updateHeartbeat(null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
// Override default so total retry time is 30 secs
retry = new Util.RetryStrategy(dbmgr,
DBManager.TRANSACTION_RETRY_DELAY_DEFAULT, 4, true);
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public Long updateBrokerHeartbeat(String brokerID, long lastHeartbeat)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().updateHeartbeat(null,
brokerID, lastHeartbeat);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
// Override default so total retry time is 30 secs
retry = new Util.RetryStrategy(dbmgr,
DBManager.TRANSACTION_RETRY_DELAY_DEFAULT, 4, false, true);
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void addBrokerInfo(String brokerID, String URL, BrokerState state,
int version, long sessionID, long heartbeat) throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
List additionalSessions = null;
if (partitionMode) {
additionalSessions = new ArrayList();
for (int i = 0; i < initialNumPartitions-1; i++) {
additionalSessions.add(new UID());
}
}
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getBrokerDAO().insert(null, brokerID, null, URL,
version, state.intValue(), Long.valueOf(sessionID),
heartbeat, additionalSessions);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void addBrokerInfo(HABrokerInfo bkrInfo, boolean sync) throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getBrokerDAO().insert(null, bkrInfo.getId(),
bkrInfo.getTakeoverBrokerID(), bkrInfo.getUrl(),
bkrInfo.getVersion(), bkrInfo.getState(),
null, bkrInfo.getHeartbeat(), null);
List sessions = bkrInfo.getAllSessions();
if (sessions != null && !sessions.isEmpty()) {
StoreSessionDAO dao = daoFactory.getStoreSessionDAO();
Iterator itr = sessions.iterator();
while (itr.hasNext()) {
HABrokerInfo.StoreSession ses =
(HABrokerInfo.StoreSession)itr.next();
dao.insert(null, ses.getBrokerID(), ses.getID(),
ses.getIsCurrent(), ses.getCreatedBy(),
ses.getCreatedTS());
}
}
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public UID updateBrokerInfo( String brokerID, int updateType,
Object oldValue, Object newValue )
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().update(null, brokerID,
updateType, oldValue, newValue);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public HABrokerInfo getBrokerInfo(String brokerID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getBrokerInfo(null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public HashMap getAllBrokerInfos(boolean loadSession)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getAllBrokerInfos(null, loadSession);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public HashMap getAllBrokerInfoByState(BrokerState state)
throws BrokerException {
if (state == null) {
throw new NullPointerException();
}
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getAllBrokerInfosByState(null, state);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public String getStoreSessionOwner( long sessionID )
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getStoreSessionDAO().getStoreSessionOwner(null, sessionID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public boolean ifOwnStoreSession( long sessionID, String brokerID )
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getStoreSessionDAO().ifOwnStoreSession(null, sessionID, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public String getStoreSessionCreator( long sessionID )
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getStoreSessionDAO().getStoreSessionCreator(null, sessionID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public boolean updateBrokerState(String brokerID, BrokerState newState,
BrokerState expectedState, boolean local) throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().updateState( null, brokerID,
newState, expectedState, local );
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
// Override default so total retry time is about 1 min
retry = new Util.RetryStrategy(dbmgr,
DBManager.TRANSACTION_RETRY_DELAY_DEFAULT, 5, false, true);
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public BrokerState getBrokerState(String brokerID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getState(null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy(dbmgr,
DBManager.TRANSACTION_RETRY_DELAY_DEFAULT, 5, true);
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public Object[] getAllBrokerStates() throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getBrokerDAO().getAllStates(null);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public void getTakeOverLock(String brokerID, String targetBrokerID,
long lastHeartbeat, BrokerState expectedState,
long newHeartbeat, BrokerState newState, boolean force,
TakingoverTracker tracker)
throws TakeoverLockException, BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
tracker.setStage_BEFORE_GET_LOCK();
Connection conn = null;
Exception myex = null;
try {
synchronized ( takeoverLockMap ) {
// Verify if a lock has been acquired for the target broker
TakeoverStoreInfo takeoverInfo =
(TakeoverStoreInfo)takeoverLockMap.get( targetBrokerID );
if (takeoverInfo != null) {
logger.logToAll( Logger.WARNING,
BrokerResources.W_UNABLE_TO_ACQUIRE_TAKEOVER_LOCK, targetBrokerID );
return;
}
conn = dbmgr.getConnection( true );
Util.RetryStrategy retry = null;
do {
try {
// Try to obtain the lock by updating the target broker
// entry in the broker table; an exception is thrown if we
// are unable to get the lock.
HABrokerInfo savedInfo =
daoFactory.getBrokerDAO().takeover(
conn, brokerID, targetBrokerID, lastHeartbeat,
expectedState, newHeartbeat, newState );
savedInfo.setTakeoverTimestamp(newHeartbeat);
tracker.setStage_AFTER_GET_LOCK();
long timestamp = System.currentTimeMillis();
logger.logToAll( Logger.INFO,
BrokerResources.I_TAKEOVER_LOCK_ACQUIRED,
targetBrokerID, String.valueOf(timestamp) );
takeoverInfo = new TakeoverStoreInfo(
targetBrokerID, savedInfo, timestamp );
// Save the broker's state
takeoverLockMap.put( targetBrokerID, takeoverInfo );
// Now, get the all the msgs and corresponding dst IDs
// that we'll be taking over to track and ensure that
// they can't be accessed while we're taking over!
Map msgMap =
daoFactory.getMessageDAO().getMsgIDsAndDstIDsByBroker(
conn, targetBrokerID );
tracker.setMessageMap( msgMap );
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
try {
Util.close( null, null, conn, myex );
} finally {
// decrement in progress count
setInProgress(false);
}
}
}
public TakeoverStoreInfo takeOverBrokerStore(String brokerID,
String targetBrokerID, TakingoverTracker tracker)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
tracker.setStage_BEFORE_TAKE_STORE();
partitionLock.lock();
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection( false );
BrokerDAO brokerDAO = daoFactory.getBrokerDAO();
HABrokerInfo bkrInfo = null;
Util.RetryStrategy retry = null;
do { // JDBC Retry loop
try {
bkrInfo = brokerDAO.getBrokerInfo( conn, targetBrokerID );
break;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
if ( bkrInfo == null ) {
String errorMsg = br.getKString(
BrokerResources.E_BROKERINFO_NOT_FOUND_IN_STORE, targetBrokerID );
logger.log( Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR,
errorMsg );
throw new BrokerException(
br.getKString( BrokerResources.E_INTERNAL_BROKER_ERROR, errorMsg ) );
}
// Verify a takeover lock has been acquired for the target broker.
TakeoverStoreInfo takeoverInfo = null;
synchronized ( takeoverLockMap ) {
takeoverInfo = (TakeoverStoreInfo)takeoverLockMap.get( targetBrokerID );
}
if ( takeoverInfo == null ||
!brokerID.equals( bkrInfo.getTakeoverBrokerID() ) ) {
// Cannot takeover a store without 1st obtaining the lock
logger.log( Logger.ERROR, BrokerResources.E_TAKEOVER_WITHOUT_LOCK,
targetBrokerID );
throw new BrokerException(
br.getKString( BrokerResources.E_TAKEOVER_WITHOUT_LOCK, targetBrokerID ) );
}
tracker.setStoreSession(bkrInfo.getSessionID());
// Start takeover process...
try {
retry = null;
do { // JDBC Retry loop
try {
// Get local destinations of target broker
DestinationDAO dstDAO = daoFactory.getDestinationDAO();
List dstList = dstDAO.getAllLocalDestinations( conn, targetBrokerID );
takeoverInfo.setDestinationList( dstList );
String args[] = { String.valueOf(dstList.size()),
targetBrokerID, dstList.toString() };
logger.log( Logger.INFO, br.getString(
BrokerResources.I_TAKINGOVER_LOCAL_DSTS, args) );
// Get messages of target broker
MessageDAO msgDAO = daoFactory.getMessageDAO();
Map msgMap = msgDAO.getMsgIDsAndDstIDsByBroker( conn, targetBrokerID );
takeoverInfo.setMessageMap( msgMap );
logger.log( Logger.INFO, br.getString(
BrokerResources.I_TAKINGOVER_MSGS,
msgMap.size(), targetBrokerID) );
// Get transactions of target broker
TransactionDAO txnDAO = daoFactory.getTransactionDAO();
List txnList = txnDAO.getTransactionsByBroker( conn, targetBrokerID );
takeoverInfo.setTransactionList( txnList );
logger.log( Logger.INFO, br.getString(
BrokerResources.I_TAKINGOVER_TXNS,
txnList.size(), targetBrokerID) );
// Get remote transactions of target broker
List remoteTxnList = txnDAO.getRemoteTransactionsByBroker( conn, targetBrokerID );
takeoverInfo.setRemoteTransactionList( remoteTxnList );
logger.log( Logger.INFO, br.getString(
BrokerResources.I_TAKINGOVER_REMOTE_TXNS,
remoteTxnList.size(), targetBrokerID) );
tracker.setStage_BEFORE_DB_SWITCH_OWNER();
// Takeover all store sessions of target broker
StoreSessionDAO sesDAO = daoFactory.getStoreSessionDAO();
List sesList = sesDAO.takeover( conn, brokerID, targetBrokerID );
takeoverInfo.setTakeoverStoreSessionList(sesList);
String args2[] = { String.valueOf(sesList.size()),
targetBrokerID, sesList.toString() };
logger.log( Logger.INFO, br.getString(
BrokerResources.I_TAKINGOVER_STORE_SESSIONS, args2) );
if (!brokerDAO.updateState( conn, targetBrokerID,
BrokerState.FAILOVER_COMPLETE,
BrokerState.FAILOVER_STARTED, false )) {
try {
conn.rollback();
} catch (SQLException rbe) {
logger.logStack( Logger.ERROR, BrokerResources.X_DB_ROLLBACK_FAILED, rbe );
}
throw new BrokerException(
"Unable to update state to "+ BrokerState.FAILOVER_COMPLETE+
" for broker "+targetBrokerID );
}
conn.commit();
tracker.setStage_AFTER_DB_SWITCH_OWNER();
// Removed saved state from cache
synchronized( takeoverLockMap ) {
takeoverLockMap.remove( targetBrokerID );
}
tracker.setStage_AFTER_TAKE_STORE();
if (partitionMode) {
addPartitionStores(sesList);
}
return takeoverInfo;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch ( Throwable thr ) {
// We need to remove the takeover lock on the broker table
// if we're unable to takeover the store due to an error.
// We do not need to do a transaction rollback here because
// the DAO layer should done this already.
logger.logToAll( Logger.INFO,
BrokerResources.I_REMOVING_TAKEOVER_LOCK, targetBrokerID );
HABrokerInfo savedInfo = takeoverInfo.getSavedBrokerInfo();
try {
retry = null;
do { // JDBC Retry loop
try {
// Restore original heartbeat
brokerDAO.update( conn, targetBrokerID,
HABrokerInfo.RESTORE_HEARTBEAT_ON_TAKEOVER_FAIL,
brokerID,
savedInfo );
// Removed the lock, i.e. restore entry values
brokerDAO.update( conn, targetBrokerID, HABrokerInfo.RESTORE_ON_TAKEOVER_FAIL,
brokerID, savedInfo );
logger.log(logger.INFO, br.getKString(br.I_BROKER_STATE_RESTORED_TAKEOVER_FAIL,
targetBrokerID, BrokerState.getState(savedInfo.getState()).toString()+
"[StoreSession:"+savedInfo.getSessionID()+"]"));
conn.commit();
synchronized( takeoverLockMap ) {
takeoverLockMap.remove( targetBrokerID );
}
break; // // JDBC Retry loop
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} catch ( Exception e ) {
logger.logStack( Logger.ERROR,
BrokerResources.E_UNABLE_TO_REMOVE_TAKEOVER_LOCK,
targetBrokerID, e );
}
throw new BrokerException(
br.getKString( BrokerResources.E_UNABLE_TO_TAKEOVER_BROKER,
targetBrokerID), thr );
}
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
try {
Util.close( null, null, conn, myex );
} finally {
partitionLock.unlock();
// decrement in progress count
setInProgress(false);
}
}
}
public void updateTransactionAccessedTime(TransactionUID txnID,
long accessedTime) throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTransactionDAO().updateAccessedTime(null,
txnID, accessedTime);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public TransactionState getTransactionState(TransactionUID txnID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getTransactionStateInternal(txnID);
} finally {
setInProgress(false);
}
}
public TransactionState getTransactionStateInternal(TransactionUID txnID)
throws BrokerException {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionState(null, txnID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public BrokerAddress getRemoteTransactionHomeBroker(TransactionUID tid)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getRemoteTransactionHomeBrokerInternal(tid);
} finally {
setInProgress(false);
}
}
public BrokerAddress getRemoteTransactionHomeBrokerInternal(TransactionUID tid)
throws BrokerException {
if (DEBUG) {
logger.log(logger.INFO, "JDBCStore.getRemoteTransactionHomeBrokerInternal("+tid+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionHomeBroker(null, tid);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public TransactionBroker[] getClusterTransactionBrokers(TransactionUID tid)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getClusterTransactionBrokersInternal(tid);
} finally {
setInProgress(false);
}
}
public TransactionBroker[] getClusterTransactionBrokersInternal(TransactionUID tid)
throws BrokerException {
if (DEBUG) {
logger.log(logger.INFO, "JDBCStore.getClusterTransactionBrokersInternal("+tid+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionBrokers(null, tid);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public long getTransactionAccessedTime(TransactionUID txnID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getAccessedTime( null, txnID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public TransactionInfo getTransactionInfo(TransactionUID txnID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getTransactionInfoInternal(txnID);
} finally {
setInProgress(false);
}
}
public TransactionInfo getTransactionInfoInternal(TransactionUID txnID)
throws BrokerException {
if (DEBUG) {
logger.log(logger.INFO, "JDBCStore.getTransactionInfoInternal("+txnID+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionInfo( null, txnID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
protected Collection getTransactions(String brokerID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionsByBroker(
null, brokerID);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
// decrement in progress count
setInProgress(false);
}
}
public int[] getTransactionUsageInfo(TransactionUID txnID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getTransactionUsageInfoInternal(txnID);
} finally {
setInProgress(false);
}
}
public int[] getTransactionUsageInfoInternal(TransactionUID txnID)
throws BrokerException {
if (DEBUG) {
logger.log(logger.INFO, "JDBCStore.getTransactionUsageInfoInternal("+txnID+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTransactionDAO().getTransactionUsageInfo(null, txnID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public long getDestinationConnectedTime(Destination destination)
throws BrokerException {
checkClosedAndSetInProgress();
try {
return getDestinationConnectedTimeInternal(destination);
} finally {
setInProgress(false);
}
}
public long getDestinationConnectedTimeInternal(Destination destination)
throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO,
"JDBCStore.getDestinationConnectedTimeInternal("+destination.getUniqueName()+")");
}
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getDestinationDAO().getDestinationConnectedTime(
null, destination.getUniqueName());
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
public boolean hasMessageBeenAcked(DestinationUID dst, SysMessageID mID)
throws BrokerException {
// make sure store is not closed then increment in progress count
checkClosedAndSetInProgress();
try {
return hasMessageBeenAckedInternal(dst, mID);
} finally {
// decrement in progress count
setInProgress(false);
}
}
public boolean hasMessageBeenAckedInternal(DestinationUID dst, SysMessageID mID)
throws BrokerException {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getMessageDAO().hasMessageBeenAcked(null, dst, mID);
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
}
// unlock indicates whether we need to unlock the tables before we close
private void closeDB(boolean unlock) {
Connection conn = null;
Exception myex = null;
try {
if (unlock) {
conn = dbmgr.getConnection( true);
// unlock the tables
if ( !Globals.getHAEnabled() &&
config.getBooleanProperty( LOCK_STORE_PROP, true ) ) {
dbmgr.lockTables( conn, false );
}
}
} catch (Exception e) {
myex = e;
logger.log(Logger.WARNING, BrokerResources.X_CLOSE_DATABASE_FAILED, e);
} finally {
try {
Util.close( null, null, conn, myex );
} catch ( Exception e ) {}
}
dbmgr.close();
}
public String getStoreType() {
return JDBC_STORE_TYPE;
}
/**
* The following methods does not apply to jdbc store.
* Data synchronization methods are implemented as no-ops
* after the necessary checks. Others will throw BrokerException.
*/
public HashMap getStorageInfo(Destination destination)
throws BrokerException {
throw new BrokerException(br.getKString(BrokerResources.E_NOT_JDBC_STORE_OPERATION));
}
/**
* Get debug information about the store.
* @return A Hashtable of name value pair of information
*/
public Hashtable getDebugState() throws BrokerException {
String url = dbmgr.getOpenDBURL();
String bid = "(" + dbmgr.getBrokerID() + ")";
Hashtable t = new Hashtable();
t.put("JDBC-based store", url + bid);
t.put("Store version", String.valueOf(STORE_VERSION));
Connection conn = null;
Exception myex = null;
try {
conn = dbmgr.getConnection( true );
Iterator itr = daoFactory.getAllDAOs().iterator();
while ( itr.hasNext() ) {
// Get debug info for each DAO
t.putAll( ((BaseDAO)itr.next()).getDebugInfo( conn ) );
}
} catch (BrokerException e) {
myex = e;
throw e;
} finally {
Util.close( null, null, conn, myex );
}
t.put(dbmgr.toString(), dbmgr.getDebugState());
return t;
}
public boolean isHADBStore() {
if (dbmgr != null) {
return dbmgr.isHADB();
}
return false;
}
public void resetConnectionPool() throws BrokerException {
if (dbmgr != null) {
dbmgr.resetConnectionPool();
}
throw new BrokerException("JDBCStore not inited !");
}
public void compactDestination(Destination destination)
throws BrokerException {
throw new BrokerException(br.getKString(BrokerResources.E_NOT_JDBC_STORE_OPERATION));
}
/**
* 1. if new store exists (store of current version exists)
* print reminder message if old version still exists
* check to see if store need to be remove or reset
* 2. if new store NOT exists
* check if old store exists
* 3. if old store exists
* check to see if store need to be upgrade
* 4. if old store NOT exists
* check if store need to be create
*/
private boolean checkStore( Connection conn ) throws BrokerException {
boolean status = true; // Set to false for caller to close DB
// Check old store
int oldStoreVersion = -1;
if ( checkOldStoreVersion( conn,
dbmgr.getTableName( VersionDAO.TABLE + SCHEMA_VERSION_40 ),
VersionDAO.STORE_VERSION_COLUMN, OLD_STORE_VERSION_400 ) ) {
oldStoreVersion = OLD_STORE_VERSION_400;
} else if ( checkOldStoreVersion( conn, VERSION_TBL_37 + dbmgr.getBrokerID(),
TVERSION_CVERSION, OLD_STORE_VERSION_370 ) ) {
oldStoreVersion = OLD_STORE_VERSION_370;
} else if ( checkOldStoreVersion( conn, VERSION_TBL_35 + dbmgr.getBrokerID(),
TVERSION_CVERSION, OLD_STORE_VERSION_350 ) ) {
oldStoreVersion = OLD_STORE_VERSION_350;
}
// Get the store version
boolean foundNewStore = false;
int storeVersion = 0;
try {
storeVersion = daoFactory.getVersionDAO().getStoreVersion( conn );
} catch ( BrokerException e ) {
// Assume new store doesn't exist
logger.log(Logger.WARNING, e.getMessage(), e.getCause() );
}
// Verify the version match
if ( storeVersion > 0 ) {
foundNewStore = ( storeVersion == STORE_VERSION );
if ( foundNewStore ) {
// Make sure tables exist
DBTool.updateStoreVersion410IfNecessary( conn, dbmgr );
if ( dbmgr.checkStoreExists(conn) == -1 ) {
logger.log(Logger.ERROR, BrokerResources.E_BAD_STORE_MISSING_TABLES);
throw new BrokerException(br.getKString(
BrokerResources.E_BAD_STORE_MISSING_TABLES));
}
} else {
// Store doesn't have the version that we are expecting!
String found = String.valueOf(storeVersion);
String expected = String.valueOf(STORE_VERSION);
logger.log(Logger.ERROR, BrokerResources.E_BAD_STORE_VERSION,
found, expected);
throw new BrokerException(br.getKString(
BrokerResources.E_BAD_STORE_VERSION,
found, expected));
}
if ( ( oldStoreVersion > 0 ) && !removeStore ) {
// old store exists & removeStore is not true so
// log reminder message to remove old tables, i.e. 3.5
logger.logToAll(Logger.INFO,
BrokerResources.I_REMOVE_OLDTABLES_REMINDER);
}
}
// Process any cmd line options
if ( foundNewStore ) {
if ( removeStore ) {
try {
// just drop all tables
DBTool.dropTables( conn, false, dbmgr );
} catch (SQLException e) {
throw new BrokerException(
br.getKString(BrokerResources.E_REMOVE_JDBC_STORE_FAILED,
dbmgr.getOpenDBURL()), e);
}
status = false; // Signal calling method to close DB
} else if ( resetStore ) {
clearAll(true);
}
} else {
boolean createNew = false;
if ( createStore ) {
// Are we supposed to automatically create the store?
createNew = true;
}
boolean dropOld = false;
String dropMsg = null; // Reason for dropping the old store
if ( oldStoreVersion > 0 ) {
if ( removeStore ) {
dropOld = true;
dropMsg = BrokerResources.I_REMOVE_OLD_DATABASE_TABLES;
} else if ( resetStore ) {
createNew = true;
dropOld = true;
dropMsg = BrokerResources.I_RESET_OLD_DATABASE_TABLES;
} else {
// log message to do upgrade
logger.logToAll(Logger.INFO, BrokerResources.I_UPGRADE_STORE_MSG,
new Integer( oldStoreVersion ) );
if (upgradeNoBackup && !Broker.getBroker().force) {
// will throw BrokerException if the user backs out
getConfirmation();
}
// Upgrade the store to the new version
if (!Globals.getHAEnabled()) {
new UpgradeStore(this, oldStoreVersion).upgradeStore(conn);
return status;
}
}
}
if ( !createNew ) {
// Error - user must create the store manually!
logger.log(Logger.ERROR, BrokerResources.E_NO_DATABASE_TABLES);
throw new BrokerException(
br.getKString(BrokerResources.E_NO_DATABASE_TABLES));
}
// Now, do required actions
if ( dropOld ) {
logger.logToAll(Logger.INFO, dropMsg);
try {
// just drop all old tables
DBTool.dropTables(conn, dbmgr.getTableNames( oldStoreVersion ),
false, false, dbmgr );
} catch (Exception e) {
logger.logToAll(Logger.ERROR, BrokerResources.E_REMOVE_OLD_TABLES_FAILED, e);
throw new BrokerException(
br.getKString(BrokerResources.E_REMOVE_OLD_TABLES_FAILED), e);
}
}
if ( createNew ) {
logger.logToAll(Logger.INFO, BrokerResources.I_WILL_CREATE_NEW_STORE);
try {
// create the tables
DBTool.createTables( conn );
} catch (Exception e) {
String url = dbmgr.getCreateDBURL();
if ( url == null || url.length() == 0 ) {
url = dbmgr.getOpenDBURL();
}
String msg = br.getKString(
BrokerResources.E_CREATE_DATABASE_TABLE_FAILED, url);
logger.logToAll(Logger.ERROR, msg+": "+e);
logger.logStack(Logger.ERROR, msg, e);
throw new BrokerException(msg, e);
}
}
}
return status;
}
/**
* Get the current store session ID.
*/
private long getStoreSession() throws BrokerException {
if (Globals.getHAEnabled()) {
return Globals.getStoreSession().longValue();
} else {
StoreSessionDAO sessionDAO = daoFactory.getStoreSessionDAO();
return sessionDAO.getStoreSession( null, dbmgr.getBrokerID() );
}
}
/**
* Return true if table exists and stored version match what's expected
* Return false if table does not exist
*/
public boolean checkOldStoreVersion( Connection conn, String vTable,
String vColumn, int version ) throws BrokerException {
try {
String selectSQL = "SELECT " + vColumn + " FROM " + vTable;
Statement stmt = null;
ResultSet rs = null;
Exception myex = null;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery( selectSQL );
if ( rs.next() ) {
int storeVersion = rs.getInt( 1 );
if ( storeVersion == version ) {
return true;
}
// Old store doesn't have the version we are expecting
String found = String.valueOf(storeVersion);
String expected = String.valueOf(version);
logger.log(Logger.ERROR, BrokerResources.E_BAD_OLDSTORE_VERSION,
found, expected);
throw new BrokerException(br.getKString(
BrokerResources.E_BAD_OLDSTORE_VERSION,
found, expected));
} else {
// Old store doesn't have any data
logger.log(Logger.ERROR,
BrokerResources.E_BAD_OLDSTORE_NO_VERSIONDATA, vTable);
throw new BrokerException(br.getKString(
BrokerResources.E_BAD_OLDSTORE_NO_VERSIONDATA, vTable));
}
} catch ( SQLException e ) {
myex = e;
// assume that the table does not exist
logger.log( Logger.DEBUG, "Assume old store does not exist because : " +
e.getMessage() );
} finally {
Util.close( rs, stmt, null, myex );
}
} catch ( Exception e ) {
logger.log(Logger.ERROR, BrokerResources.X_STORE_VERSION_CHECK_FAILED, e);
throw new BrokerException(
br.getKString(BrokerResources.X_STORE_VERSION_CHECK_FAILED), e);
}
return false;
}
boolean resetMessage() {
return resetMessage;
}
boolean resetInterest() {
return resetInterest;
}
static class StoreSessionReaperTask extends TimerTask
{
private boolean canceled = false;
Logger logger = Globals.getLogger();
JDBCStore store = null;
public StoreSessionReaperTask(JDBCStore store) {
this.store = store;
}
public synchronized boolean cancel() {
canceled = true;
return super.cancel();
}
public void run() {
synchronized(this) {
if (canceled) {
return;
}
}
try {
if (!store.partitionMode) {
StoreSessionDAO sesDAO = store.daoFactory.getStoreSessionDAO();
List reaped = sesDAO.deleteInactiveStoreSession(null);
if (reaped.size() == 0) {
store.notifyPartitionRemoved(null, null);
} else {
Iterator itr = reaped.iterator();
while (itr.hasNext()) {
store.notifyPartitionRemoved(new UID(itr.next()), null);
}
}
}
List moretasks = null;
synchronized(store.sessionReaperListeners) {
moretasks = new ArrayList(
store.sessionReaperListeners);
}
Iterator itr = moretasks.iterator();
while (itr.hasNext()) {
itr.next().runStoreSessionTask();
}
} catch (Exception e) {
logger.logStack( Logger.ERROR,
BrokerResources.E_INACTIVE_SESSION_REMOVAL_FAILED, e );
}
}
}
/******************************************************************
* Extended Store Interface methods, JMSBridgeStore (JDBC only)
******************************************************************/
/**
* Store a log record
*
* @param xid the global XID
* @param logRecord the log record data for the xid
* @param name the jmsbridge name
* @param sync - not used
* @param logger_ can be null
* @exception DupKeyException if already exist
* else Exception on error
*/
public void storeTMLogRecord(String xid, byte[] logRecord,
String name, boolean sync,
java.util.logging.Logger logger_)
throws DupKeyException, Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (logRecord == null) throw new IllegalArgumentException("null logRecord");
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.storeTMLogRecord("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.storeTMLogRecord("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTMLogRecordDAOJMSBG().insert(null,
xid, logRecord, name, logger_);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Update a log record
*
* @param xid the global XID
* @param logRecord the new log record data for the xid
* @param name the jmsbridge name
* @param addIfNotExist
* @param sync - not used
* @param callback to obtain updated data
* @param logger_ can be null
* @exception KeyNotFoundException if not found and addIfNotExist false
* else Exception on erorr
*/
public void updateTMLogRecord(String xid, byte[] logRecord,
UpdateOpaqueDataCallback callback,
String name, boolean addIfNotExist,
boolean sync,
java.util.logging.Logger logger_)
throws Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (logRecord == null) throw new IllegalArgumentException("null logRecord");
if (name == null) throw new IllegalArgumentException("null name");
if (callback == null) throw new IllegalArgumentException("null callback");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.updateTMLogRecord("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.updateTMLogRecord("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTMLogRecordDAOJMSBG().updateLogRecord(null,
xid, logRecord, name,
callback, addIfNotExist,
logger_);
return;
} catch (Exception e) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Remove a log record
*
* @param xid the global XID
* @param name the jmsbride name
* @param sync - not used
* @param logger_ can be null
* @exception KeyNotFoundException if not found
* else Exception on error
*/
public void removeTMLogRecord(String xid, String name,
boolean sync,
java.util.logging.Logger logger_)
throws KeyNotFoundException, Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.removeTMLogRecord("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.removeTMLogRecord("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getTMLogRecordDAOJMSBG().delete(null,
xid, name, logger_);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get a log record
*
* @param xid the global XID
* @param name the jmsbridge name
* @param logger_ can be null
* @return null if not found
* @exception Exception if error
*/
public byte[] getTMLogRecord(String xid, String name,
java.util.logging.Logger logger_)
throws Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getTMLogRecord("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getTMLogRecord("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTMLogRecordDAOJMSBG().getLogRecord(null,
xid, name, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get last update time of a log record
*
* @param xid the global XID
* @param name the jmsbridge name
* @param logger_ can be null
* @exception KeyNotFoundException if not found
* else Exception on error
*/
public long getTMLogRecordUpdatedTime(String xid, String name,
java.util.logging.Logger logger_)
throws KeyNotFoundException, Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getTMLogRecordUpdatedTime("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getTMLogRecordUpdatedTime("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTMLogRecordDAOJMSBG().getUpdatedTime(
null, xid, name, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get a log record creation time
*
* @param xid the global XID
* @param name the jmsbridge name
* @param logger_ can be null
* @exception KeyNotFoundException if not found
* else Exception on error
*/
public long getTMLogRecordCreatedTime(String xid, String name,
java.util.logging.Logger logger_)
throws KeyNotFoundException, Exception {
if (xid == null) throw new IllegalArgumentException("null xid");
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getTMLogRecordCreatedTime("+xid+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getTMLogRecordcreatedTime("+ xid+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTMLogRecordDAOJMSBG().getCreatedTime(
null, xid, name, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get all log records for a TM name
*
* @param name the jmsbridge name
* @param logger_ can be null
* @return a list of log records
* @exception Exception if error
*/
public List getTMLogRecordsByName(String name,
java.util.logging.Logger logger_)
throws Exception {
return getLogRecordsByNameByBroker(name, dbmgr.getBrokerID(), logger_);
}
/**
* Get all log records for a JMS bridge in a broker
*
* @param name the jmsbridge name
* @param logger_ can be null
* @return a list of log records
* @exception Exception if error
*/
public List getLogRecordsByNameByBroker(String name,
String brokerID,
java.util.logging.Logger logger_)
throws Exception {
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getTMLogRecordsByNameByBroker("+name+", "+brokerID+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getTMLogRecordsByNameByBroker("+name+", "+brokerID+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTMLogRecordDAOJMSBG().getLogRecordsByNameByBroker(
null, name, brokerID, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get JMS bridge names in all log records owned by a brokerID
*
* @param brokerID
* @param logger_ can be null
* @return a list of log records
* @exception Exception if error
*/
public List getNamesByBroker(String brokerID,
java.util.logging.Logger logger_)
throws Exception {
if (brokerID == null) throw new IllegalArgumentException("null brokerID");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getTMNamesByBroker("+brokerID+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getTMNamesByBroker("+brokerID+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getTMLogRecordDAOJMSBG().getNamesByBroker(
null, brokerID, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Add a JMS Bridge
*
* @param name jmsbridge name
* @param sync - not used
* @param logger_ can be null
* @exception DupKeyException if already exist
* else Exception on error
*/
public void addJMSBridge(String name, boolean sync,
java.util.logging.Logger logger_)
throws DupKeyException, Exception {
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.addJMSBridge("+name+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.addJMSBridge("+name+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getJMSBGDAO().insert(null, name, logger_);
return;
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* Get JMS bridges owned by this broker
*
* @param logger_ can be null
* @return a list of names
* @exception Exception if error
*/
public List getJMSBridges(java.util.logging.Logger logger_)
throws Exception {
return getJMSBridgesByBroker(dbmgr.getBrokerID(), logger_);
}
/**
* Get JMS bridges owned by a broker
*
* @param brokerID
* @param logger_ can be null
* @return a list of names
* @exception Exception if error
*/
public List getJMSBridgesByBroker(String brokerID,
java.util.logging.Logger logger_)
throws Exception {
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getJMSBridgesByBroker("+brokerID+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getJMSBridges("+brokerID+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getJMSBGDAO().getNamesByBroker(null, brokerID, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* @param name jmsbridge name
* @param logger_ can be null;
* @return updated time
* @throws KeyNotFoundException if not found
* else Exception on error
*/
public long getJMSBridgeUpdatedTime(String name,
java.util.logging.Logger logger_)
throws KeyNotFoundException, Exception {
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getJMSBridgeUpdatedTime("+name+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getJMSBridgeUpdatedTime("+name+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getJMSBGDAO().getUpdatedTime(null, name, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* @param name jmsbridge name
* @param logger_ can be null;
* @return created time
* @throws KeyNotFoundException if not found
* else Exception on error
*/
public long getJMSBridgeCreatedTime(String name,
java.util.logging.Logger logger_)
throws KeyNotFoundException, Exception {
if (name == null) throw new IllegalArgumentException("null name");
if (DEBUG) {
logger.log(Logger.DEBUG, "JDBCStore.getJMSbridgeCreatedTime("+name+")");
Util.logExt(logger_, java.util.logging.Level.FINE,
"JDBCStore.getJMSBridgeCreatedTime("+name+")", null);
}
checkClosedAndSetInProgress();
try {
Util.RetryStrategy retry = null;
do {
try {
return daoFactory.getJMSBGDAO().getCreatedTime(null, name, logger_);
} catch ( Exception e ) {
// Exception will be log & re-throw if operation cannot be retry
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
public void closeJMSBridgeStore() throws Exception {
//ignore
}
/************************************************
* Additional PartitionedStore Methods
************************************************/
/**
* Return the LoadException for loading destinations; null if there's
* none.
*/
public LoadException getLoadDestinationException() {
return null;
}
/**
* Return the LoadException for loading transactions; null if there's none.
*/
public LoadException getLoadTransactionException() {
return null;
}
/**
* Return the LoadException for loading transaction acknowledgements;
* null if there's none.
*/
public LoadException getLoadTransactionAckException() {
return null;
}
/**
* Remove the message from the persistent store.
* If the message has an interest list, the interest list will be
* removed as well.
*
* @param dID the destination the message is associated with
* @param mID the system message id of the message to be removed
* @param sync if true, will synchronize data to disk
* @exception IOException if an error occurs while removing the message
* @exception BrokerException if the message is not found in the store
* @exception NullPointerException if dID
is
* null
*/
public void removeMessage(DestinationUID dID,
SysMessageID mID, boolean sync)
throws IOException, BrokerException {
removeMessage(dID,mID,sync, false);
}
/********************************************
* Partitioned Store Specific Methods
**********************************************/
public void init(Store store, UID id, boolean isPrimrary)
throws BrokerException {
throw new UnsupportedOperationException(
"Operation not supported by JDBCStore class");
}
@Override
public boolean getPartitionModeEnabled() {
return partitionMode;
}
@Override
public boolean isPartitionMigratable() {
return partitionMigratable;
}
public String toString() {
return "["+getStoreType()+"]";
}
public int hashCode() {
return partitionid.hashCode();
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (!(anObject instanceof PartitionedStore)) {
return false;
}
return getPartitionID().equals(
((PartitionedStore)anObject).getPartitionID());
}
public UID getPartitionID() {
return partitionid;
}
public boolean isPrimaryPartition() {
return true;
}
@Override
public void partitionsReady() throws BrokerException {
synchronized(closedLock) {
partitionsReady = true;
}
initPartitionStores();
}
@Override
public List getAllStorePartitions() throws BrokerException {
synchronized(partitionStores) {
return new ArrayList(partitionStores.values());
}
}
@Override
public PartitionedStore getStorePartition(UID id) throws BrokerException {
PartitionedStore ps = null;
checkClosedAndSetInProgress();
try {
synchronized(partitionStores) {
ps = partitionStores.get(id);
}
if (ps == null) {
throw new BrokerException(
br.getKString(br.X_STORE_PARTITION_NOT_FOUND, id),
Status.NOT_FOUND);
}
} finally {
setInProgress(false);
}
return ps;
}
public void partitionDeparture(UID partitionID, String targetBrokerID)
throws BrokerException {
checkClosedAndSetInProgress();
try {
if (!partitionMode) {
throw new BrokerException("Broker store not partition mode",
Status.PRECONDITION_FAILED);
}
if (!partitionMigratable) {
throw new BrokerException("Broker store partition not migratable",
Status.PRECONDITION_FAILED);
}
synchronized(closedLock) {
if (!partitionsReady) {
throw new BrokerException("Store partitions init not ready yet", Status.PRECONDITION_FAILED);
}
}
synchronized(partitionStores) {
PartitionedStore pstore = partitionStores.remove(partitionID);
if (pstore == null) {
String emsg = "Departure partition "+partitionID+" does not exist in this broker";
throw new BrokerException(emsg, Status.NOT_FOUND);
}
notifyPartitionRemoved(partitionID, targetBrokerID); //XXX
if (!pstore.isClosed()) {
throw new BrokerException("Departure partition "+partitionID+ " not closed");
}
}
Util.RetryStrategy retry = null;
do {
try {
daoFactory.getStoreSessionDAO().moveStoreSession(
null, partitionID.longValue(), targetBrokerID);
return;
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
/**
* @partitionID the UID for the arrived partition
* or null if check partition arrival
* @return a list contains the PartitionedStore for the partitionID
* or a list of arrived PartitionedStore during check
*/
public List partitionArrived(UID partitionID)
throws BrokerException {
PartitionedStore pstore = null;
checkClosedAndSetInProgress();
boolean locked = false;
try {
synchronized(closedLock) {
if (!partitionsReady) {
throw new BrokerException(
"Store partitions init not ready yet", Status.PRECONDITION_FAILED);
}
}
if (!partitionMode) {
throw new BrokerException("Broker store not partition mode", Status.NOT_ALLOWED);
}
if (partitionID != null) {
synchronized(partitionStores) {
pstore = partitionStores.get(partitionID);
if (pstore != null) {
logger.log(logger.INFO,
"Arrived partition "+partitionID+" has already been loaded in store");
List p = new ArrayList();
p.add(pstore);
return p;
}
}
}
Util.RetryStrategy retry = null;
do {
try {
if (partitionID != null) {
String brokerID = daoFactory.getStoreSessionDAO().
getStoreSessionOwner(null, partitionID.longValue());
if (brokerID == null || !brokerID.equals(dbmgr.getBrokerID())) {
String emsg = br.getKString(
br.X_NOT_OWN_ARRIVED_STORE_PARTITION, partitionID);
throw new BrokerException(emsg, Status.NOT_ALLOWED);
}
List l = new ArrayList();
l.add(Long.valueOf(partitionID.longValue()));
return addPartitionStores(l);
} else {
if (!partitionLock.tryLock()) {
throw new BrokerException(
"Broker takeover in process, retry operation later", Status.RETRY);
}
locked = true;
//This method is executed by 1 dedicated thread - partition monitor
List sessions = dbmgr.getDAOFactory().getStoreSessionDAO().
getStoreSessionsByBroker( null, dbmgr.getBrokerID() );
List l = new ArrayList();
synchronized(partitionStores) {
Iterator itr = sessions.iterator();
while (itr.hasNext()) {
Long s = itr.next();
if (partitionStores.get(new UID(s)) == null) {
l.add(s);
}
}
}
return addPartitionStores(l);
}
} catch ( Exception e ) {
if ( retry == null ) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
if (locked) {
partitionLock.unlock();
}
setInProgress(false);
}
}
private List addPartitionStores(List storeSessions)
throws BrokerException {
List loaded = new ArrayList();
UID uid = null;
PartitionedStore ps = null;
try {
synchronized(partitionStores) {
Iterator itr = storeSessions.iterator();
while (itr.hasNext()) {
uid = new UID(itr.next().longValue());
if (partitionStores.get(uid) != null) {
throw new BrokerException(
br.getKString(br.X_ADD_STORE_PARTITION_ALREAD_EXIST, uid));
}
logger.log(logger.INFO, br.getKString(br.I_CREATE_STORE_PARTITION, uid));
if (Globals.isNucleusManagedBroker()) {
ps = Globals.getHabitat().
getService(PartitionedStore.class, partitionClassStr);
} else {
ps = (PartitionedStore)partitionClass.newInstance();
}
ps.init(this, uid, (uid.longValue() == getStoreSession()));
partitionStores.put(uid, ps);
loaded.add(ps);
notifyPartitionAdded(uid);
}
}
return loaded;
} catch (Exception e) {
throw new BrokerException(e.getMessage(), e);
}
}
private void initPartitionStores() throws BrokerException {
checkClosedAndSetInProgress();
try {
if (!partitionMode) {
partitionStores.put(getPartitionID(), this);
return;
}
synchronized(closedLock) {
if (!partitionsReady) {
throw new BrokerException("IllegalState: store partitions not ready");
}
}
List sessions = new ArrayList();
sessions.add(Long.valueOf(getStoreSession()));
addPartitionStores(sessions);
Util.RetryStrategy retry = null;
do {
try {
sessions = dbmgr.getDAOFactory().getStoreSessionDAO().
getStoreSessionsByBroker( null, dbmgr.getBrokerID() );
logger.log(logger.INFO, br.getKString(
br.I_OWN_STORE_SESSIONS_CREATE_PARTITIONS,
Integer.valueOf(sessions.size())));
sessions.remove(Long.valueOf(getStoreSession()));
addPartitionStores(sessions);
return;
} catch ( Exception e ) {
if (retry == null) {
retry = new Util.RetryStrategy();
}
retry.assertShouldRetry( e );
}
} while ( true );
} finally {
setInProgress(false);
}
}
public PartitionedStore getPrimaryPartition() throws BrokerException {
checkClosedAndSetInProgress();
try {
if (!partitionMode) {
return this;
}
if (partitionStores.size() == 0) {
throw new BrokerException("IllegalStateException: partition store not ready");
}
return partitionStores.get(new UID(getStoreSession()));
} finally {
setInProgress(false);
}
}
protected void notifyPartitionRemoved(UID partitionID, String removedToBroker) {
synchronized(partitionStores) {
Iterator itr = partitionListeners.iterator();
while (itr.hasNext()) {
itr.next().partitionRemoved(partitionID, this, removedToBroker);
}
}
}
protected void notifyPartitionAdded(UID partitionID) {
synchronized(partitionStores) {
Iterator itr = partitionListeners.iterator();
while (itr.hasNext()) {
itr.next().partitionAdded(partitionID, this);
}
}
}
/**
* @param listener the PartitionListener to be added
* @exception BrokerException
*/
@Override
public void addPartitionListener(PartitionListener listener)
throws BrokerException {
checkClosedAndSetInProgress();
try {
synchronized(partitionStores) {
partitionListeners.add(listener);
}
} finally {
setInProgress(false);
}
}
/**
* @param listener the PartitionListener to be removed
* @exception BrokerException
*/
@Override
public void removePartitionListener(PartitionListener listener)
throws BrokerException {
checkClosedAndSetInProgress();
try {
synchronized(partitionStores) {
partitionListeners.remove(listener);
}
} finally {
setInProgress(false);
}
}
/**
* @exception BrokerException
*/
@Override
public void addStoreSessionReaperListener(StoreSessionReaperListener listener)
throws BrokerException {
checkClosedAndSetInProgress();
try {
synchronized(sessionReaperListeners) {
sessionReaperListeners.add(listener);
}
} finally {
setInProgress(false);
}
}
/**
* @exception BrokerException
*/
@Override
public void removeStoreSessionReaperListener(StoreSessionReaperListener listener)
throws BrokerException {
checkClosedAndSetInProgress();
try {
synchronized(sessionReaperListeners) {
sessionReaperListeners.remove(listener);
}
} finally {
setInProgress(false);
}
}
}