/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. 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.html
* or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [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.
*/
package org.jvnet.glassfish.comms.replication.dialogmgmt;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import com.ericsson.ssa.sip.DialogFragment;
import com.ericsson.ssa.sip.DialogSet;
import com.ericsson.ssa.sip.PersistentDialogFragmentManager;
import com.ericsson.ssa.sip.RemoteLockException;
import com.ericsson.ssa.sip.SipApplicationSessionUtil;
import com.sun.appserv.ha.spi.BackingStore;
import com.sun.appserv.ha.spi.BackingStoreException;
import com.sun.appserv.ha.spi.BackingStoreFactory;
import com.sun.appserv.ha.spi.BackingStoreRegistry;
import com.sun.appserv.ha.util.SimpleMetadata;
import com.sun.appserv.ha.uow.ReplicableEntity;
import com.sun.appserv.util.cache.BaseCache;
import com.sun.enterprise.web.ServerConfigLookup;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.jvnet.glassfish.comms.replication.sessmgmt.ActivationHelper;
import org.jvnet.glassfish.comms.util.LogUtil;
import com.sun.enterprise.ee.web.sessmgmt.*;
import org.jvnet.glassfish.comms.replication.sessmgmt.SipReplicationUtil;
import org.jvnet.glassfish.comms.replication.sessmgmt.SASLockStatus;
/**
* In-memory replicating DialogFragmentManager.
*
* Get this singleton instance using {@link com.ericsson.ssa.sip.DialogFragmentManager#getInstance()}.
*/
public class ReplicationDialogFragmentManager
extends PersistentDialogFragmentManager
implements ReplicationManager, DynamicOwnershipManager, PurgeCapable {
private static final Logger _logger = LogUtil.SSR_LOGGER.getLogger();
// Singleton class so app_id is always this constant.
private static final String APP_ID = "DialogFragmentManager";
protected static final String MODE_SIP = ReplicationState.MODE_SIP;
final static String DUPLICATE_IDS_SEMANTICS_PROPERTY
= ReplicationState.DUPLICATE_IDS_SEMANTICS_PROPERTY;
final static String SUPPRESS_LOAD_ACK_PROPERTY
= ReplicationState.SUPPRESS_LOAD_ACK_PROPERTY;
final static String REPLICATION_COMPRESSION_PROPERTY
= ReplicationState.REPLICATION_COMPRESSION_PROPERTY;
final static String SESSION_MANAGER_PROPERTY =
ReplicationState.SESSION_MANAGER_PROPERTY; // used during jxtabackingstore creation to store a reference to this session manager in jxtabackingstore.
final static String COMMAND_MAP = "commandmap";
private static final Level TRACE_LEVEL = Level.FINE;
protected static int _maxBaseCacheSize = 4096;
protected static float _loadFactor = 0.75f;
protected static final int _concurrencyLevel = 100;
public final static String BEKEY
= ReplicationState.BEKEY;
private static final Map dialogFragmentCommandMap = new HashMap();
public final static String SAVE_COMMAND
= ReplicationState.SAVE_COMMAND;
public final static String VALVE_SAVE_COMMAND
= ReplicationState.VALVE_SAVE_COMMAND;
public final static String REMOVE_COMMAND
= ReplicationState.REMOVE_COMMAND;
public final static String UNDEPLOY_COMMAND
= ReplicationState.UNDEPLOY_COMMAND;
public final static String REMOVE_EXPIRED_COMMAND
= ReplicationState.REMOVE_EXPIRED_COMMAND;
public final static String UPDATE_LAST_ACCESS_TIME_COMMAND
= ReplicationState.UPDATE_LAST_ACCESS_TIME_COMMAND;
public final static String MESSAGE_BROADCAST_QUERY
= ReplicationState.MESSAGE_BROADCAST_QUERY;
public final static String MESSAGE_BROADCAST_LOAD_RECEIVED
= ReplicationState.MESSAGE_BROADCAST_LOAD_RECEIVED;
public final static String SAVE_DIALOG_FRAGMENT_COMMAND = "savedialogfragment";
public final static String REMOVE_DIALOG_FRAGMENT_COMMAND = "removedialogfragment";
public final static String LOAD_DIALOG_FRAGMENT_COMMAND = "loaddialogfragment";
public final static String UPDATE_LAST_ACCESS_TIME_DIALOG_FRAGMENT_COMMAND
= "updatelastaccesstimedialogfragment";
public final static String MESSAGE_BROADCAST_QUERY_DIALOG_FRAGMENT
= "broadcastfinddialogfragment";
public final static String MESSAGE_BROADCAST_LOAD_RECEIVED_DIALOG_FRAGMENT
= "broadcastloadreceiveddialogfragment";
public final static String MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT
= "broadcastfinddialogfragmentexpatids";
public final static String MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA
= "broadcastfinddialogfragmentreplicaexpatids";
public final static String MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT
= "broadcastreceivedialogfragmentexpatids";
public final static String MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT_REPLICA
= "broadcastreceivedialogfragmentreplicaexpatids";
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_RESPONSE
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_RESPONSE;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_RESPONSE
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_RESPONSE;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_RECONCILIATION_COMPLETE_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_RECONCILIATION_COMPLETE_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_RESPONSE
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_RESPONSE;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_ADVISORY
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_ADVISORY;
public final static String MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_RESPONSE
= RollingUpgradeHandler.MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_RESPONSE;
/**
* There are 3 request/responses :
*
* (a) active reconciliation
* (b) replica reconciliation
* (c) post active reconciliation.
*
* These are separated instead of one because, only (a) is applicable for
* third party backing stores. Whereas, in-memory needs all 3 steps.
*/
public static final String RECONCILE_DF_REQUEST =
"reconciledfrequest";
public static final String RECONCILE_DF_RESPONSE =
"reconciledfresponse";
public static final String RECONCILE_DF_REPLICA_REQUEST =
"reconciledfreplicarequest";
public static final String RECONCILE_DF_REPLICA_RESPONSE =
"reconciledfreplicaresponse";
public static final String POST_RECONCILE_DF_REQUEST =
"postreconciledfrequest";
public static final String POST_RECONCILE_DF_RESPONSE =
"postreconciledfresponse";
/**
* similary there are 3 countdownlatches and 2 responses
* (c) does not have a response, but only signals the
* completion of the (c) in all other instances.
*/
private volatile AtomicReference<CountDownLatch> activeDfReconcileSignal =
new AtomicReference<CountDownLatch>();
private volatile AtomicReference<CountDownLatch> replicaDfReconcileSignal =
new AtomicReference<CountDownLatch>();
private volatile AtomicReference<CountDownLatch> postDfReconcileSignal =
new AtomicReference<CountDownLatch>();
private volatile Map<String, ReplicationState> reconciledActiveDFs =
new HashMap<String, ReplicationState>();
private volatile Map<String, ReplicationState> reconciledReplicaDFs =
new HashMap<String, ReplicationState>();
private volatile Map<String, ReplicationState> remotelyLockedDFs =
new HashMap<String, ReplicationState>();
private static final Object _monitor = new Object();
private static AtomicBoolean useReplicationUnicastLoadResponseBatching
= null;
ExpatListHandler dfExpatListHandler;
ExpatListHandler dfReplicaExpatHandler;
/**
* the list of method names that are broadcasts
*/
private static List broadcastMethods
= Arrays.asList(MESSAGE_BROADCAST_QUERY_DIALOG_FRAGMENT,
LOAD_DIALOG_FRAGMENT_COMMAND,
MESSAGE_BROADCAST_LOAD_RECEIVED_DIALOG_FRAGMENT,
MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT,
MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA,
MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY,
MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT,
MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT_REPLICA,
MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_ADVISORY,
MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_RESPONSE,
MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_ADVISORY,
MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_RESPONSE,
MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_ADVISORY,
MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_RESPONSE,
MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_ADVISORY,
MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_RESPONSE,
MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_RECONCILIATION_COMPLETE_ADVISORY);
/**
* the list of method names that are expensive
* i.e. should not run on single receiving thread
* e.g. expat list query which when received take some time
* which should not occur on the same receiving thread
*/
private static List expensiveMethods
= Arrays.asList(
MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT,
MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA,
MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT,
MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT_REPLICA
);
/**
* the list of method names that remove methods
*/
private static List removeMethods
= Arrays.asList(
REMOVE_DIALOG_FRAGMENT_COMMAND);
private static List saveMethods
= Arrays.asList(
SAVE_DIALOG_FRAGMENT_COMMAND);
private volatile HashMap<String, ExpatListElement> expatIdsMap =
new HashMap<String, ExpatListElement>();
private ReentrantReadWriteLock expatReadWriteLock
= new ReentrantReadWriteLock();
private HashMap<String,String> lastExpatQueryId
= new HashMap<String,String>();
protected String _rollingUpgradeBackupDirectory = null;
protected boolean _skipRollingUpgradeBackupRestore = false;
/**
* get the rollingUpgradeBackupDirectory
*/
public String getRollingUpgradeBackupDirectory() {
return _rollingUpgradeBackupDirectory;
}
/**
* set the rollingUpgradeBackupDirectory
* @param value
*/
public void setRollingUpgradeBackupDirectory(String value) {
_rollingUpgradeBackupDirectory = value;
}
/** should skip backup and restore step for rolling upgrade */
boolean isSkipRollingUpgradeBackupRestore() {
return _skipRollingUpgradeBackupRestore;
}
/**
* set the skipRollingUpgradeBackupRestore
* @param value
*/
public void setSkipRollingUpgradeBackupRestore(boolean value) {
_skipRollingUpgradeBackupRestore = value;
}
protected static java.util.concurrent.atomic.AtomicLong unique =
new AtomicLong(0);
private volatile CountDownLatch reconcileReplicaCacheDoneSignal = null;
private volatile CountDownLatch getIdsForReplicaCacheReconciliationDoneSignal = null;
private volatile CountDownLatch getIdsForActiveCacheReconciliationDoneSignal = null;
private volatile CountDownLatch restoreActiveCacheDoneSignal = null;
private volatile CountDownLatch restoreReplicaCacheDoneSignal = null;
protected ConcurrentHashMap<String, ReplicationState> ownedReplicaListsReceivedForActiveCacheRestoration = null;
protected ConcurrentHashMap<String, ReplicationState> ownedReplicaListsReceivedForReplicaCacheRestoration = null;
protected ConcurrentHashMap<String, ReplicationState> ownedIdsForReplicaCacheReconciliation = null;
protected ConcurrentHashMap<String, ReplicationState> ownedIdsForActiveCacheReconciliation = null;
private StorePool dialogFragmentStorePool;
/**
* Our cache of monitor objects
* keyed by id
*/
protected ReplicationSessionMonitors replicatedSessionMonitors = null;
/**
* Our Replicator instance for DialogFragments (for SimpleMetadata)
*/
private BackingStore dialogFragmentBackingStore = null;
/**
* Our ReplicaCache - the receiving side for replicas
*/
protected ReplicaCache replicaCache = null;
protected String _passedInPersistenceType = null;
protected boolean _duplicateIdsSemanticsAllowed = false;
protected AtomicBoolean _activeCacheReconciliationOngoing
= new AtomicBoolean(false);
protected ConcurrentHashMap stillOwnedDialogFragmentIdsForActiveCacheReconciliation = null;
private AtomicBoolean isReplicationInitialized = new AtomicBoolean(); //defaults to false
private AtomicBoolean isReplicationStarted = new AtomicBoolean(); //defaults to false
private final String instanceName;
private ReplicationUtil replicationUtil;
static {
checkSessionCacheProperties();
initializeCommandMap();
}
private static boolean isReplicationUnicastLoadResponseBatchingEnabled() {
if(useReplicationUnicastLoadResponseBatching != null) {
return useReplicationUnicastLoadResponseBatching.get();
}
synchronized(_monitor) {
if(useReplicationUnicastLoadResponseBatching == null) {
ServerConfigLookup lookup = new ServerConfigLookup();
boolean useBatching
= lookup.isReplicationUnicastLoadResponseBatchingEnabled();
useReplicationUnicastLoadResponseBatching
= new AtomicBoolean(useBatching);
}
}
return useReplicationUnicastLoadResponseBatching.get();
}
/**
* Constructor, which registers the new instance with the
* ReplicationMessageRouter.
*
* @see com.ericsson.ssa.sip.DialogFragmentManager#getInstance()
*/
public ReplicationDialogFragmentManager() {
super();
instanceName = ReplicationUtil.getInstanceName();
ServerConfigLookup lookup = new ServerConfigLookup();
replicationCompressionEnabled = lookup.isReplicationCompression();
replicationUtil = ReplicationUtil.createReplicationUtil();
replicatedSessionMonitors = new ReplicationSessionMonitors(_logger, _maxBaseCacheSize, _loadFactor);
}
protected static boolean checkSessionCacheProperties() {
boolean result = false;
try {
Properties props = System.getProperties();
String cacheSize = props.getProperty(
"HTTP_SESSION_CACHE_MAX_BASE_CACHE_SIZE");
if (null != cacheSize) {
_maxBaseCacheSize = (new Integer(cacheSize).intValue());
}
String loadFactor = props.getProperty(
"HTTP_SESSION_CACHE_MAX_BASE_LOAD_FACTOR");
if (null != loadFactor) {
_loadFactor = (new Float(loadFactor).floatValue());
}
} catch (Exception e) {
//do nothing accept defaults
}
return result;
}
protected static void initializeCommandMap() {
dialogFragmentCommandMap.put(SAVE_COMMAND, SAVE_DIALOG_FRAGMENT_COMMAND);
dialogFragmentCommandMap.put(VALVE_SAVE_COMMAND, SAVE_DIALOG_FRAGMENT_COMMAND);
dialogFragmentCommandMap.put(REMOVE_COMMAND, REMOVE_DIALOG_FRAGMENT_COMMAND);
dialogFragmentCommandMap.put(UPDATE_LAST_ACCESS_TIME_COMMAND, UPDATE_LAST_ACCESS_TIME_DIALOG_FRAGMENT_COMMAND);
dialogFragmentCommandMap.put(MESSAGE_BROADCAST_QUERY, MESSAGE_BROADCAST_QUERY_DIALOG_FRAGMENT);
}
/**
* Initialize ReplicationDialogFragmentManager replication services.
*
* @param passedInPersistenceType
* @param haStorePoolSize
* @param haStorePoolUpperSize
* @param haStorePoolPollTime
*/
public void initializeReplication(String passedInPersistenceType, int haStorePoolSize,
int haStorePoolUpperSize, int haStorePoolPollTime) {
if (isInitialized.get() == false ) {
IllegalStateException ex = new IllegalStateException("DialogFragmentManager must be initialized prior to initializing replication.");
_logger.log(Level.SEVERE, "df_init_replication_error");
_logger.log(Level.SEVERE, ex.getMessage(), ex);
throw ex;
}
// Only initialize once.
if (isReplicationInitialized.compareAndSet(false, true)) {
setPassedInPersistenceType(passedInPersistenceType);
StorePool dialogFragmentStorePool =
new StorePool(haStorePoolSize, haStorePoolUpperSize, haStorePoolPollTime,
new DialogFragmentStoreFactory());
setDialogFragmentStorePool(dialogFragmentStorePool);
setDialogFragmentStore(new DialogFragmentStoreImpl());
dfExpatListHandler = ExpatListHandler.getExpatListHandler(this,
this.getApplicationId(), MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT,
MODE_SIP, "DialogFragmentActive");
}
}
public void startReplication() {
if (isStarted.get() == false ) {
IllegalStateException ex = new IllegalStateException("DialogFragmentManager must be started prior to starting replication.");
_logger.log(Level.SEVERE, "df_start_replication_error");
_logger.log(Level.SEVERE, ex.getMessage(), ex);
throw ex;
}
// Only start once.
if (isReplicationStarted.compareAndSet(false, true)) {
registerWithMessageRouter();
}
}
public boolean isReplicationStarted() {
return isReplicationStarted.get();
}
boolean replicationCompressionEnabled = false;
boolean isReplicationCompressionEnabled() {
return replicationCompressionEnabled;
}
@Override
protected void doStop() {
super.doStop();
deregisterWithMessageRouter();
}
/**
* Factory method to instansiate DialogFragments
* @param ds
* @return
*/
public DialogFragment createDialogFragment(DialogSet ds) {
HADialogFragment hadf = new HADialogFragment(ds);
hadf.initDialogLifeCycle();
return hadf;
}
ExpatListElement getExpatListElement(String id) {
if(expatReadWriteLock.readLock().tryLock()) {
try {
synchronized(expatIdsMap) {
ExpatListElement result = expatIdsMap.get(id);
return result;
}
} finally {
expatReadWriteLock.readLock().unlock();
}
} else {
return null;
}
}
ExpatListElement removeExpatListElement(String id) {
if(expatReadWriteLock.readLock().tryLock()) {
try {
synchronized(expatIdsMap) {
ExpatListElement result = expatIdsMap.remove(id);
return result;
}
} finally {
expatReadWriteLock.readLock().unlock();
}
} else {
return null;
}
}
private static ReplicationMessageRouter getRouter() {
ReplicationMessageRouter receiver = null;
if (Globals.IS_SECURITY_ENABLED) {
receiver = (ReplicationMessageRouter)
AccessController.doPrivileged(
new PrivilegedGetReplicationMessageRouter());
} else {
receiver = ReplicationMessageRouter.createInstance();
}
return receiver;
}
private void registerWithMessageRouter() {
ReplicationMessageRouter router = getRouter();
if(router != null) {
router.addReplicationManager(this.getApplicationId(), (ReplicationManager)this);
router.registerBroadcastMethodList(broadcastMethods);
router.registerExpensiveMethodList(expensiveMethods);
router.registerRemoveMethodList(removeMethods);
router.registerSaveMethodList(saveMethods);
}
//FIXME: this is for testing
//will eventually be triggered by separate admin command
//if(ReplicationUtil.isRollingUpgradeEnabled()) {
//CountDownLatch doneSignal = new CountDownLatch(1);
//doRollingUpgradePostStartupProcessing(System.currentTimeMillis(), doneSignal);
//}
}
private void deregisterWithMessageRouter() {
ReplicationMessageRouter router = getRouter();
if(router != null) {
router.removeReplicationManager(this.getApplicationId());
// FIXME currently no means to deregister Broadcast methodlist.
}
}
public String getApplicationId() {
return APP_ID;
}
/**
* get the backingStore for DialogFragment
*/
synchronized public BackingStore getDialogFragmentBackingStore() {
if (dialogFragmentBackingStore == null) {
dialogFragmentBackingStore = createBackingStore(dialogFragmentCommandMap);
}
return dialogFragmentBackingStore;
}
/**
* create and set the backing store
* @param commandMap map used to translate commands
*/
BackingStore createBackingStore(Map commandMap) {
BackingStoreFactory storeFactory = new JxtaBackingStoreFactory();
BackingStoreRegistry backingStoreRegistry
= BackingStoreRegistry.getInstance();
Properties inputEnv = backingStoreRegistry.getFactoryClassEnv(getPassedInPersistenceType());
Properties env = (Properties)inputEnv.clone();
env.put(DUPLICATE_IDS_SEMANTICS_PROPERTY, Boolean.valueOf(this.isDuplicateIdsSemanticsAllowed()));
env.put(SUPPRESS_LOAD_ACK_PROPERTY, Boolean.TRUE);
env.put(COMMAND_MAP, commandMap);
//does this manager & backing store support replication compression
env.put(REPLICATION_COMPRESSION_PROPERTY, Boolean.valueOf(this.isReplicationCompressionEnabled()));
env.put(SESSION_MANAGER_PROPERTY, this);
BackingStore backingStore = null;
try {
backingStore = storeFactory.createBackingStore(
this.getApplicationId(), //appid
String.class,
SimpleMetadata.class, //type
env);
} catch (BackingStoreException ex) {
//deliberate no-op
}
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("backingStore: " + backingStore);
}
if(backingStore != null) {
if(backingStore instanceof JxtaBackingStoreImpl) {
((JxtaBackingStoreImpl)backingStore).setMode(MODE_SIP);
}
}
return backingStore;
}
ReplicaCache getReplicaCache() {
return replicaCache;
}
public void setReplicaCache(ReplicaCache replicaCache) {
this.replicaCache = replicaCache;
}
public String getPassedInPersistenceType() {
return _passedInPersistenceType;
}
public void setPassedInPersistenceType(String persistenceType) {
_passedInPersistenceType = persistenceType;
}
public boolean isDuplicateIdsSemanticsAllowed() {
return _duplicateIdsSemanticsAllowed;
}
public void setDuplicateIdsSemanticsAllowed(boolean value) {
_duplicateIdsSemanticsAllowed = value;
}
public boolean isActiveCacheReconciliationOngoing() {
return _activeCacheReconciliationOngoing.get();
}
public void setActiveCacheReconciliationOngoing(boolean value) {
_activeCacheReconciliationOngoing.set(value);
}
//DialogFragment cache methods
public Object getReplicationSessionMonitor(String id) {
return replicatedSessionMonitors.get(id);
}
public void processExpiredReplicaMonitors() {
replicatedSessionMonitors.processExpired();
}
public void processExpiredReplicaRemovals() {
replicaCache.processExpiredReplicaRemovals();
}
/**
* get the replicated DialogFragments cache
*/
public BaseCache getReplicatedDialogFragments() {
return replicaCache.getReplicatedSessions();
}
/**
* set the replicated DialogFragments cache
* @param dialogFragmentTable
*/
public void setReplicatedDialogFragments(BaseCache dialogFragmentTable) {
replicaCache.setReplicatedSessions(dialogFragmentTable);
}
/**
* Put dialogFragment State in DialogFragment replica cache
* @param dialogFragmentState
*/
protected void putInDialogFragmentReplicationCache(ReplicationState dialogFragmentState) {
replicaCache.putInReplicationCache(dialogFragmentState);
}
/**
* get DialogFragment State from replica cache based on the id
* @param id
*/
protected ReplicationState getFromDialogFragmentReplicationCache(String id) {
return replicaCache.getFromReplicationCache(id);
}
/**
* remove dialogFragment State from replica cache based on the id
* @param id
*/
protected ReplicationState removeFromDialogFragmentReplicationCache(String id) {
return replicaCache.removeFromReplicationCache(id);
}
/** Returns a store from the pool
* This method intializes the store with right parameters
* @return returns DialogFragmentStoreImpl
*/
public DialogFragmentStoreImpl getDialogFragmentStore() {
return getDialogFragmentStore(ReplicationUtil.isSynchronousReplicationConfigured());
}
/** Returns a store from the pool
* This method intializes the store with right parameters
* @return returns DialogFragmentStoreImpl
*/
public DialogFragmentStoreImpl getDialogFragmentStore(boolean useSingleton) {
if(_logger.isLoggable(Level.FINER)) {
_logger.entering("ReplicationDialogFragmentManager", "getDialogFragmentStore");
}
if(useSingleton) {
return getSingletonDialogFragmentStore();
}
if (dialogFragmentStorePool == null) {
// Replication service not initialized yet.
return null;
}
DialogFragmentStoreImpl store = null;
try {
store = (DialogFragmentStoreImpl) dialogFragmentStorePool.take();
if(_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST,
"ReplicationDialogFragmentManager.getDialogFragmentStore returning " + store);
}
return store;
}
catch (Exception e) {
// FIXME evaluate log level
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "exception occurred during getDialogFragment", e);
}
}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager", "getDialogFragmentStore", store);
}
return store;
}
public int processExpiredSessions() {
//Deliberate no op
return 0;
}
/**
* Returns (puts) a store back to the pool if we are using the pool
*/
private void putDialogFragmentStore(StorePoolElement store) {
putDialogFragmentStore(store, ReplicationUtil.isSynchronousReplicationConfigured());
}
/**
* Returns (puts) a store back to the pool
* @param useSingleton if true we do not put the store back in the pool
*/
private void putDialogFragmentStore(StorePoolElement store, boolean useSingleton) {
if(useSingleton) {
return;
}
//( (DialogFragmentStoreImpl) store).setSipSessionManager(null);
if (store != null && dialogFragmentStorePool != null) {
try {
dialogFragmentStorePool.put(store);
} catch (InterruptedException ex1) {
// FIXME evaluate log level
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "exception occurred during putDialogFragmentStore", ex1);
}
}
}
}
/** Returns the singleton store
* This method intializes the store with right parameters
* @return returns DialogFragmentStoreImpl
*/
public DialogFragmentStoreImpl getSingletonDialogFragmentStore() {
return (DialogFragmentStoreImpl)super.getDialogFragmentStore();
}
//begin send-side methods
/**
* Persists the given DialogFragment.
*
* @param dialogFragment The DialogFragment to be persisted
*/
public void saveDialogFragment(DialogFragment dialogFragment)
throws IOException {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager", "saveDialogFragment");
}
if(dialogFragment == null) {
return;
}
DialogFragmentStoreImpl store = null;
try {
store = getDialogFragmentStore();
if(store != null && dialogFragment.isReplicable()) {
store.save(dialogFragment);
}
}
finally {
this.putDialogFragmentStore(store);
}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager", "saveDialogFragment");
}
}
private ReplicationState doUnicastLoadTest(HADialogFragment df) {
//start unicast load test
ReplicationState resultState = null;
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String partnerInstanceName
= healthChecker.getReshapeReplicateToInstanceName(null, 3000L);
DialogFragmentStoreImpl dfStore = this.getSingletonDialogFragmentStore();
try {
resultState = dfStore.sendUnicastLoadQuery((String)df.getDialogId(), "" + df.getVersion(), partnerInstanceName);
} catch (Throwable th) {
_logger.log(Level.INFO, "error during unicast load test to " + partnerInstanceName, th);
}
return resultState;
//end unicast load test
}
/**
* Removes the given DialogFragment from both the active cache
* and the persistent session store of this session manager,
*
* @param dialogFragment The DialogFragment to be removed
*/
public void removeDialogFragment(DialogFragment dialogFragment, boolean hasTimedOut) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager", "removeDialogFragment");
}
if(dialogFragment == null) {
return;
}
super.removeDialogFragmentFromCache(dialogFragment, hasTimedOut);
DialogFragmentStoreImpl store = null;
try {
store = getDialogFragmentStore();
if(store != null && dialogFragment.isReplicable()) {
store.remove(dialogFragment.getDialogId());
}
} catch (IOException ex) {
_logger.log(Level.WARNING, "df_remove_error", dialogFragment.toString());
_logger.log(Level.WARNING, ex.getMessage(), ex);
} finally {
this.putDialogFragmentStore(store);
}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager", "removeDialogFragment");
}
}
/**
* Removes the given DialogFragment from
* the persistent session store of this session manager,
*
* @param dialogFragmentId The id of the DialogFragment replica to be removed
*/
public void removeDialogFragmentReplica(String dialogFragmentId) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager", "removeDialogFragmentReplica");
}
DialogFragmentStoreImpl store = null;
try {
store = getDialogFragmentStore();
if(store != null) {
store.remove(dialogFragmentId);
}
} catch (IOException ex) {
_logger.log(Level.WARNING, "df_remove_error", dialogFragmentId);
_logger.log(Level.WARNING, ex.getMessage(), ex);
} finally {
this.putDialogFragmentStore(store);
}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager", "removeDialogFragmentReplica");
}
}
/**
* Removes the given DialogFragment from both the active cache and the
* persistent session store of this session manager,
*
* @param id The id of the DialogFragment to be removed
*/
public void removeDialogFragment(String id, boolean hasTimedOut) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager", "removeDialogFragment", id);
}
removeDialogFragmentFromCache(id, hasTimedOut);
DialogFragmentStoreImpl store = null;
try {
store = getDialogFragmentStore();
if(store != null) {
store.remove(id);
}
} catch (IOException ex) {
_logger.log(
Level.WARNING,
"unable to remove DialogFragment:id = " + id,
ex);
} finally {
this.putDialogFragmentStore(store);
}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager", "removeDialogFragment");
}
}
public <V> V __load(String id, String version, JxtaBackingStoreImpl jxtaBackingStore)
throws BackingStoreException {
V session = null;
if (jxtaBackingStore == dialogFragmentBackingStore) {
DialogFragmentStoreImpl store =
getSingletonDialogFragmentStore();
session = (V) store.__load(id, version);
}
return session;
}
private Set<String> remotelyLoadedSessionIds =
Collections.synchronizedSet(new HashSet<String>());
public Set<String> getRemotelyLoadedSessionIds() {
return remotelyLoadedSessionIds;
}
/**
* Look for a DialogFragment in the Store and, if found, restore
* it in the Manager's list of active dialog fragments if appropriate.
* The dialog fragment will be removed from the Store after swapping
* in, but will not be added to the active dialog fragment list if it
* is invalid or past its expiration.
*
* @param id the id of the DialogFragment
*
* @throws RemoteLockException
*/
protected DialogFragment swapInDialogFragment(String id)
throws IOException, RemoteLockException {
return swapInDialogFragment(id, null);
}
/**
* Look for a DialogFragment in the Store and, if found, restore
* it in the Manager's list of active dialog fragments if appropriate.
* The dialog fragment will be removed from the Store after swapping
* in, but will not be added to the active dialog fragment list if it
* is invalid or past its expiration.
* @param id the id of the Dialog Fragment
* @param version - the version of the Dialog Fragment
*
* @throws RemoteLockException
*/
protected DialogFragment swapInDialogFragment(String id, String version)
throws IOException, RemoteLockException {
DialogFragmentStoreImpl store = null;
try {
store = this.getDialogFragmentStore();
if (store == null)
return null;
DialogFragment dialogFragment = null;
try {
SASLockStatus.setSASLocked(false);
if (SecurityUtil.isPackageProtectionEnabled()){
try{
dialogFragment = (DialogFragment) AccessController.doPrivileged(new PrivilegedStoreLoadDialogFragment(id, version, store));
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
if (exception instanceof IOException){
throw (IOException)exception;
} else if (exception instanceof ClassNotFoundException) {
throw (ClassNotFoundException)exception;
}
}
} else {
if (version != null) {
dialogFragment = store.load(id, version);
} else {
dialogFragment = store.load(id);
}
}
} catch (ClassNotFoundException e) {
IOException ex1 =
(IOException) new IOException("Error during swapInSipApplicationSession: " + e.getMessage()).initCause(e);
throw ex1;
}
return activate(dialogFragment, false);
} finally {
SASLockStatus.resetSASLockedToDefaultValue();
this.putDialogFragmentStore(store);
}
}
public DialogFragment activate(DialogFragment df,
boolean removeFromExpat) {
if (df == null)
return (null);
registerDialogFragment(df);
if(removeFromExpat) {
removeExpatListElement(df.getDialogId());
}
return df;
}
//start receiver side process methods
//DialogFragment process methods
/**
* process the save of a DialogFragment
* @param dialogFragmentState - contains the save command
*/
public void processSavedialogfragment(ReplicationState dialogFragmentState) {
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN" + this.getClass().getName() + ">>processSavedialogfragment");
}
this.putInDialogFragmentReplicationCache(dialogFragmentState);
}
/**
* process the removal of a DialogFragment
* @param dialogFragmentState - contains the remove command
*/
public void processRemovedialogfragment(ReplicationState dialogFragmentState) {
if (dialogFragmentState.getState() != null) {
processBulkRemoveDF(dialogFragmentState);
return;
}
replicaCache.processRemove(dialogFragmentState);
}
public void processBulkRemoveDF(ReplicationState replicationState) {
replicaCache.removeFromReplicationCache(
replicationState.getState());
}
/**
* process the update of a DialogFragment
* @param dialogFragmentState - contains the updatelastaccesstime command
*/
public void processUpdatelastaccesstimedialogfragment(ReplicationState dialogFragmentState) {
replicaCache.processUpdatelastaccesstime(dialogFragmentState);
}
public Map getActiveDialogFragments() {
return dialogFragments;
}
public ReplicableEntity findDialogFragmentAndPassivate(String id) {
HADialogFragment haDialogFragment = null;
DialogFragment dialogFragment
= findDialogFragmentFromCacheOnly(id);
if (dialogFragment instanceof HADialogFragment) {
haDialogFragment = (HADialogFragment) dialogFragment;
if (!haDialogFragment.isForegroundLocked()) {
processLoadReceivedDialogFragment((String) id);
}
}
return haDialogFragment;
}
/**
* process the processFindDialogFragment for DialogFragment
* @param queryState
* @param useUnicast
*/
public ReplicationState processFindDialogFragment(ReplicationState queryState,
boolean useUnicast) {
//complete query and send back response
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processFindDialogFragment:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processFindDialogFragment:id=" + queryState.getId());
_logger.fine("in " + this.getClass().getName() + ">>processFindDialogFragment:useUnicast=" + useUnicast);
}
//look in active cache
HADialogFragment haDialogFragment = (HADialogFragment)
findDialogFragmentAndPassivate((String)queryState.getId());
//look in replica cache
ReplicationState replicaState
= getFromDialogFragmentReplicationCache((String)queryState.getId());
ReplicationState returnState
= getBestDialogFragment(haDialogFragment, replicaState, queryState, useUnicast);
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processFindDialogFragment:returnState=" + returnState);
}
return returnState;
}
/**
* process the broadcastfinddialogfragment for DialogFragment
* @param queryState
*/
public ReplicationState processBroadcastfinddialogfragment(ReplicationState queryState) {
//complete query and send back response
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragment:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragment:id=" + queryState.getId());
}
return processFindDialogFragment(queryState, false);
}
/**
* process the unicast load of a DialogFragment
* @param queryState - contains the load command
*/
public ReplicationState processLoaddialogfragment(ReplicationState queryState) {
//complete query and send back response
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processLoaddialogfragment:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processLoaddialogfragment:id=" + queryState.getId());
}
return processFindDialogFragment(queryState, true);
}
public void processBroadcastloadreceiveddialogfragment(ReplicationState queryState) {
//load is acknowledged safe to remove replica now
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processbroadcastloadreceiveddialogfragment:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processbroadcastloadreceiveddialogfragment:id=" + queryState.getId());
}
if(queryState == null || queryState.getId() == null) {
return;
}
String id = (String)queryState.getId();
processLoadReceivedDialogFragment(id);
String ignoreInstance = (String) queryState.getProperty(ReplicationState.IGNORE_REMOVE_INSTANCE_NAME);
//only safe to remove replica if we are not the replica partner
//now determined by passed property
if(ignoreInstance != null && !ignoreInstance.equals(ReplicationUtil.getInstanceName())) {
removeFromDialogFragmentReplicationCache(id);
}
}
public void processLoadReceivedDialogFragment(String id) {
//remove active dialogfragment if present and not locked
DialogFragment dialogFragment
= findDialogFragmentFromCacheOnly(id);
if(dialogFragment != null
&& !dialogFragment.isForegroundLocked()) {
this.removeDialogFragmentFromCache(dialogFragment, false);
}
}
/**
* find the best version of DialogFragment
* removing any stale versions and return query result
* @param activeDialogFragment DialogFragment
* from active cache
* @param replicaDialogFragment DialogFragment
* from replica cache
* @param queryState version requested in query (-1 means
* version unaware
*/
private ReplicationState getBestDialogFragment(HADialogFragment activeDialogFragment,
ReplicationState replicaDialogFragment, ReplicationState queryState, boolean useUnicast) {
ReplicationState bestResult = null;
long queryVersion = queryState.getVersion();
//first check for none found in either active or replica caches
if(replicaDialogFragment == null && activeDialogFragment == null) {
//return nack
if(useUnicast) {
return ReplicationState.createUnicastQueryResponseFrom(queryState, true);
} else {
return ReplicationState.createQueryResponseFrom(queryState, true);
}
}
//next check for artifacts found in both active and replica caches
if(replicaDialogFragment != null && activeDialogFragment != null) {
//compare and remove the lesser version
//keeping the higher version as (tentative) best
if(replicaDialogFragment.getVersion() <= activeDialogFragment.getVersion()) {
//remove stale replica - work with active
removeFromDialogFragmentReplicationCache((String)replicaDialogFragment.getId());
//create appropriate response from active
bestResult
= createDialogFragmentResponseFrom(activeDialogFragment, queryState, useUnicast);
} else {
//remove stale active - work with replica
clearFromDialogFragmentManagerCache(activeDialogFragment.getDialogId(), false);
//create appropriate response from replica
bestResult
= createDialogFragmentResponseFrom(replicaDialogFragment, queryState, useUnicast);
}
} else {
//either replica or active is null and other is non-null
//replica is null and active is not null
if(replicaDialogFragment == null) {
//create appropriate response from active
bestResult
= createDialogFragmentResponseFrom(activeDialogFragment, queryState, useUnicast);
} else {
//active is null & replica is not null
//create appropriate response from replica
bestResult
= createDialogFragmentResponseFrom(replicaDialogFragment, queryState, useUnicast);
}
}
return bestResult;
}
private ReplicationState createDialogFragmentResponseFrom(ReplicationState replicaDialogFragment,
ReplicationState queryState, boolean useUnicast) {
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("createDialogFragmentResponseFromReplicaAndReplica:useUnicast = " + useUnicast
+ " queryState = " + queryState + " replicaSipApplicationSession = " + replicaDialogFragment);
}
//create appropriate response from replica
ReplicationState result = null;
long queryVersion = queryState.getVersion();
if(queryVersion != -1 && replicaDialogFragment.getVersion() < queryVersion) {
//return nack & clear stale replica
removeFromDialogFragmentReplicationCache((String)replicaDialogFragment.getId());
if(useUnicast) {
result = ReplicationState.createUnicastQueryResponseFrom(queryState, true);
} else {
result = ReplicationState.createQueryResponseFrom(queryState, true);
}
} else {
//return real response based on replica
if(useUnicast) {
result = ReplicationState.createUnicastQueryResponseFrom(replicaDialogFragment, queryState.getCommand());
} else {
result = ReplicationState.createQueryResponseFrom(replicaDialogFragment);
}
}
return result;
}
private ReplicationState createDialogFragmentResponseFrom(HADialogFragment activeDialogFragment,
ReplicationState queryState, boolean useUnicast) {
//create appropriate response from active
ReplicationState result = null;
long queryVersion = queryState.getVersion();
if(queryVersion != -1 && activeDialogFragment.getVersion() < queryVersion) {
//return nack & clear stale active
clearFromDialogFragmentManagerCache(activeDialogFragment.getDialogId(), false);
if(useUnicast) {
result = ReplicationState.createUnicastQueryResponseFrom(queryState, true);
} else {
result = ReplicationState.createQueryResponseFrom(queryState, true);
}
} else {
//return real response based on active DF
try {
result = createQueryResponseFrom(activeDialogFragment, useUnicast);
} catch (IOException ioe) {
_logger.log(Level.WARNING, "df_load_error", activeDialogFragment.toString());
_logger.log(Level.WARNING, ioe.getMessage(), ioe);
// We've been unable to serialize the given active
// DialogFragment.
// Clear it from the active cache and return a nack instead
clearFromDialogFragmentManagerCache(
activeDialogFragment.getDialogId(), false);
if(useUnicast) {
result = ReplicationState.createUnicastQueryResponseFrom(queryState, true);
} else {
result = ReplicationState.createQueryResponseFrom(queryState, true);
}
}
}
return result;
}
/**
* Converts the given DialogFragment to a ReplicationState.
*
* @param df The DialogFragment to be converted
*
* @return The ReplicationState corresponding to the given
* DialogFragment
*/
private ReplicationState createQueryResponseFrom(
HADialogFragment df, boolean useUnicast) throws IOException {
byte[] containerExtraParamState = null;
DialogFragmentExtraParams containerExtraParams
= df.getExtraParameters();
if(containerExtraParams != null) {
try {
containerExtraParamState
= ReplicationUtil.getByteArray(containerExtraParams, isReplicationCompressionEnabled());
} catch (IOException ex) {
; //deliberate no-op
}
}
if(!useUnicast) {
return new ReplicationState(
MODE_SIP,
df.getDialogId(),
getApplicationId(),
df.getVersion(),
0L,
0L,
null,
null,
null,
ReplicationState.RETURN_BROADCAST_MSG_COMMAND,
ReplicationUtil.getByteArray(df, isReplicationCompressionEnabled()),
null,
containerExtraParamState);
} else {
return new ReplicationState(
MODE_SIP,
df.getDialogId(),
getApplicationId(),
df.getVersion(),
0L,
0L,
LOAD_DIALOG_FRAGMENT_COMMAND, //put original command in extraParam slot
null,
null,
ReplicationState.RETURN_UNICAST_MSG_COMMAND,
ReplicationUtil.getByteArray(df, isReplicationCompressionEnabled()),
null,
containerExtraParamState);
}
}
//Begin Expat List for DialogFragment
public void handleDynamicOwnershipChanges(Event event,
String triggeringInstance,
boolean isLbChange) {
if(!SipReplicationUtil.isInstanceLoadBalancedByCLB()) {
return;
}
if (!isLbChange) {
return;
}
dfExpatListHandler.eventReceived(event, triggeringInstance);
if(!dfExpatListHandler.shouldCalculateExpatList()) {
return; // expat calculation is already in progress.
}
long startTime = System.currentTimeMillis();
boolean isExpatListLocked = false;
try {
ExpatListHandler.expatCalculationStarted();
currentEvent = event;
currentTriggeringInstance = triggeringInstance;
synchronizeKeys();
dfExpatListHandler.preInvoke(event, triggeringInstance);
if (dfExpatListHandler.isAwaitingExpatList()) { // IMP :: do preInvoke before doing this check.
// if we need to await for any list to be pushed to us from
// remote instance, then only lock the list, otherwise allow
// read on the expat list.
expatReadWriteLock.writeLock().lock();
isExpatListLocked = true;
}
getExpatList();
} finally {
expatIdsMap = mergeWithReplicaExpats(
expatIdsMap, dfReplicaExpatHandler);
dfExpatListHandler.postInvoke();
ExpatListHandler.expatCalculationEnded();
if (isExpatListLocked) {
expatReadWriteLock.writeLock().unlock();
}
currentEvent = null;
currentTriggeringInstance = null;
// Print the final map after the merge to check if everything is fine.
ReplicationUtil.printExpatList(expatIdsMap, "DialogFragment(final)", startTime);
}
}
private Event currentEvent;
private String currentTriggeringInstance;
/**
* Invoke the synchronizeKeys method asynchronously on the store(s).
* Note that this method is common to all stores (in-house or third party)
*/
private void synchronizeKeys() {
// TODO :: For the third party implementation to work,
// TODO :: we need to revisit the parameters.
new SynchronizeKeysTask(getDialogFragmentBackingStore(), null, null, false);
}
/**
* JxtaBackingStoreImpl will call back this method. Hence, this is a
* in-memory implementation specific method.
*/
public void __synchronizeKeys(JxtaBackingStoreImpl jxtaBackingStore) {
ExpatListHandler expatHandler = dfReplicaExpatHandler;
if(expatHandler != null) {
expatHandler.preInvoke(currentEvent, currentTriggeringInstance);
expatHandler.call();
// NOTE :: Since the result of the above call needs to be retained
// until the results are merged with activeExpat, hence the invocation of
// postInvoke is delayed until then. mergeWithReplicaExpats method
// calls postInvoke after merging the replica expat with active expat.
}
}
public void __createStoreExpatHandler(JxtaBackingStoreImpl jxtaBackingStore) {
if (dfReplicaExpatHandler == null) {
dfReplicaExpatHandler = ExpatListHandler.getExpatListHandler(this,
this.getApplicationId(), MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA,
MODE_SIP, "DialogFragmentReplica");
}
}
/**
* For the third party backing store implementations,
* this method will be a no-op.
*/
private HashMap mergeWithReplicaExpats(HashMap activeExpat,
ExpatListHandler replicaExpatHandler) {
HashMap result = activeExpat;
if(replicaExpatHandler != null) {
try {
HashMap replicaExpat = replicaExpatHandler.awaitAndGetResult();
if(replicaExpat != null && !replicaExpat.isEmpty()) {
if(activeExpat != null) {
replicaExpat.putAll(activeExpat);
}
result = replicaExpat;
}
} finally {
// since we have the results now, we can call postInvoke() and
// clear the memory references.
replicaExpatHandler.postInvoke();
}
}
return result;
}
boolean isExpectingExpatIdsMap() {
return dfExpatListHandler.isAwaitingExpatList();
}
boolean canTrustReplicaDuringExpat(String replicaSource) {
if(replicaSource == null) {
return false;
}
DynamicOwnershipManager.Event event = currentEvent;
String instance = currentTriggeringInstance;
if(DynamicOwnershipManager.Event.FAILURE.equals(event) &&
replicaSource.equalsIgnoreCase(instance)) {
return true;
}
return false;
}
public void getExpatList() {
HashMap result = dfExpatListHandler.call();
if(result != null) {
expatIdsMap = result;
}
}
public String getExpatPushCommandFor(String expatQueryCommand) {
if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT.equals(expatQueryCommand)) {
return MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT;
}
// Added on behalf of __synchronizeKeys()
if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA.equals(expatQueryCommand)) {
return MESSAGE_BROADCAST_EXPAT_RECEIVE_DIALOG_FRAGMENT_REPLICA;
}
throw new IllegalArgumentException("Invalid command " + expatQueryCommand);
}
public HashMap<String, ExpatListElement> pruneExpatList(String command) {
if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT.equals(command)) {
// TODO :: how to prune???
return expatIdsMap;
}
if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA.equals(command)) {
return new HashMap<String, ExpatListElement>();
}
throw new IllegalArgumentException("Invalid command " + command);
}
public HashSet<ExpatListElement> getExpatListFor(String instanceName,
String command) {
boolean isRemoteInstance = !ReplicationUtil.getInstanceName().
equals(instanceName);
if (MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT.equals(command)) {
return isRemoteInstance ? getDFExpatIdsFromActive(instanceName)
: new HashSet<ExpatListElement>();
// return getDialogFragmentExpatIds(instanceName, isRemoteInstance);
}
if (MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA.equals(command)) {
return isRemoteInstance ? getDFExpatIdsFromReplica(instanceName)
: new HashSet<ExpatListElement>();
// return getDialogFragmentExpatIds(instanceName, isRemoteInstance);
}
throw new IllegalArgumentException("Invalid command " + command);
}
public void getExpatLists(String command, ExpatListQueryResults result) {
if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT.equals(command)) {
getDFExpatIdsFromActive(result);
} else if(MESSAGE_BROADCAST_EXPAT_QUERY_DIALOG_FRAGMENT_REPLICA.equals(command)) {
getDFExpatIdsFromReplica(result);
} else {
throw new IllegalArgumentException("Invalid command " + command);
}
}
public void processBroadcastreceivedialogfragmentexpatids(
ReplicationState expatListState) {
ExpatListListener expatListener =
dfExpatListHandler.getListener();
if(expatListener != null) {
expatListener.expatListReceived(expatListState);
}
}
private void expatListReceived(ReplicationState expatListState,
ExpatListHandler expatHandler) {
if(expatHandler != null) {
ExpatListListener expatListener =
expatHandler.getListener();
if (expatListener != null) {
expatListener.expatListReceived(expatListState);
}
}
}
public void processBroadcastreceivedialogfragmentreplicaexpatids(
ReplicationState expatListState) {
expatListReceived(expatListState, dfReplicaExpatHandler);
}
/**
* Gets the DialogFragment expatIds for a given instance
*
* @param requestingInstance the querying instance for
* which we are obtaining a list
* @param consultActiveCache should the list consider
* DialogFragments in the active cache
*
* @return The List of expatId elements
*/
/*
private HashSet<ExpatListElement> getDialogFragmentExpatIds(
String requestingInstance, boolean consultActiveCache) {
//using set to avoid dups
HashSet expatIds = new HashSet();
//iterate over df replicas
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
Iterator it = replicatedDialogFragmentsCache.values();
long version = -1L;
while (it.hasNext()) {
ReplicationState state = (ReplicationState) it.next();
String dfId = (String) state.getId();
//use beKey for mapping instance ownership
String beKey = (String) state.getProperty(BEKEY);
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (requestingInstance.equalsIgnoreCase(rightfulOwner)) {
version = state.getVersion();
expatIds.add(new ExpatListElement(dfId, version, instanceName));
}
}
}
if (consultActiveCache) {
try {
//iterate over active dialog fragment cache
Iterator it2 = dialogFragments.values().iterator();
while (it2.hasNext()) {
HADialogFragment df = (HADialogFragment) it2.next();
String dfId = (String) df.getDialogId();
String beKey = df.getBeKey();
if (beKey != null) {
//use beKey for mapping to owning instance
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (requestingInstance.equalsIgnoreCase(rightfulOwner)) {
version = df.getVersion();
expatIds.add(new ExpatListElement(
dfId, version, instanceName, true));
}
}
}
} catch (NoSuchFieldError e) {
;
}
}
return expatIds;
}
*/
/**
* Get the DF' expat list from the active cache for a given instance.
*/
private HashSet<ExpatListElement> getDFExpatIdsFromActive(
String requestingInstance) {
//using set to avoid dups
HashSet expatIds = new HashSet();
long version = -1L;
try {
//iterate over active dialog fragment cache
Iterator it2 = dialogFragments.values().iterator();
while (it2.hasNext()) {
HADialogFragment df = (HADialogFragment) it2.next();
String dfId = (String) df.getDialogId();
String beKey = df.getBeKey();
if (beKey != null) {
//use beKey for mapping to owning instance
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (requestingInstance.equalsIgnoreCase(rightfulOwner)) {
version = df.getVersion();
expatIds.add(new ExpatListElement(
dfId, version, instanceName, true));
}
}
}
} catch (NoSuchFieldError e) {
;
}
return expatIds;
}
/**
* Get the DF' expat list from the replica cache for a given instance.
*/
private HashSet<ExpatListElement> getDFExpatIdsFromReplica(
String requestingInstance) {
//using set to avoid dups
HashSet expatIds = new HashSet();
//iterate over df replicas
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
Iterator it = replicatedDialogFragmentsCache.values();
long version = -1L;
while (it.hasNext()) {
ReplicationState state = (ReplicationState) it.next();
String dfId = (String) state.getId();
//use beKey for mapping instance ownership
String beKey = (String) state.getProperty(BEKEY);
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (requestingInstance.equalsIgnoreCase(rightfulOwner)) {
version = state.getVersion();
expatIds.add(new ExpatListElement(dfId, version, instanceName));
}
}
}
return expatIds;
}
/**
* Get the DF' expat list from the active cache for all the surviving instances.
*/
private void getDFExpatIdsFromActive(ExpatListQueryResults results) {
long version = -1L;
//iterate over active s cache
Iterator it2 = dialogFragments.values().iterator();
while (it2.hasNext()) {
HADialogFragment df = (HADialogFragment) it2.next();
String dfId = (String) df.getDialogId();
String beKey = df.getBeKey();
//use bekey for mapping to owning instance
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (rightfulOwner != null
&& !rightfulOwner.equalsIgnoreCase(instanceName)) {
version = df.getVersion();
ExpatListElement expatElement = new ExpatListElement(
dfId, version, instanceName);
results.addQueryResultFor(rightfulOwner, expatElement);
}
}
}
}
/**
* Get the DF' expat list from the replica cache for all the surviving instances.
*/
private void getDFExpatIdsFromReplica(ExpatListQueryResults results) {
//iterate over df replicas
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
Iterator it = replicatedDialogFragmentsCache.values();
long version = -1L;
while (it.hasNext()) {
ReplicationState state = (ReplicationState) it.next();
String dfId = (String) state.getId();
//use bekey for mapping
String beKey = (String) state.getProperty(BEKEY);
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
version = state.getVersion();
ExpatListElement expatElement = new ExpatListElement(
dfId, version, instanceName);
results.addQueryResultFor(rightfulOwner, expatElement);
}
}
}
/*
private void getAllDialogFragmentExpatIds(ExpatListQueryResults results) {
//iterate over df replicas
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
Iterator it = replicatedDialogFragmentsCache.values();
long version = -1L;
while (it.hasNext()) {
ReplicationState state = (ReplicationState) it.next();
String dfId = (String) state.getId();
//use bekey for mapping
String beKey = (String) state.getProperty(BEKEY);
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
version = state.getVersion();
ExpatListElement expatElement = new ExpatListElement(
dfId, version, instanceName);
results.addQueryResultFor(rightfulOwner, expatElement);
}
}
//iterate over active s cache
Iterator it2 = dialogFragments.values().iterator();
while (it2.hasNext()) {
HADialogFragment df = (HADialogFragment) it2.next();
String dfId = (String) df.getDialogId();
String beKey = df.getBeKey();
//use bekey for mapping to owning instance
if (beKey != null) {
String rightfulOwner = SipApplicationSessionUtil.
getActualServerInstanceForBeKey(beKey);
if (rightfulOwner != null
&& !rightfulOwner.equalsIgnoreCase(instanceName)) {
version = df.getVersion();
ExpatListElement expatElement = new ExpatListElement(
dfId, version, instanceName);
results.addQueryResultFor(rightfulOwner, expatElement);
}
}
}
}
*/
/*
private List getDialogFragmentExpatIdsThirdPartySPI(String owningInstanceName) {
BackingStore dialogFragmentBackingStore
= this.getDialogFragmentBackingStore();
DialogFragmentExtraParams dfExtraParamCriteria
= DialogFragmentExtraParams.createSearchCriteria(
owningInstanceName);
Collection<DialogFragmentExtraParams> dfColl
= dialogFragmentBackingStore.findByCriteria(dfExtraParamCriteria);
List expatIds = new ArrayList();
//using set to avoid dups
HashSet expatIdsSet = new HashSet();
Iterator<DialogFragmentExtraParams> dfResults =
(Iterator<DialogFragmentExtraParams>) dfColl.iterator();
while (dfResults.hasNext()) {
DialogFragmentExtraParams eParam = dfResults.next();
if (owningInstanceName.equals(eParam.getCurrentOwnerInstanceName())) {
expatIdsSet.add(new ExpatListElement((String)eParam.getId(), -1L, null));
}
}
//iterate over active sas cache
long nextVersion = -1L;
Iterator it2 = dialogFragments.values().iterator();
while(it2.hasNext()) {
HADialogFragment nextDialogFragment
= (HADialogFragment)it2.next();
String nextDialogFragmentId
= (String)nextDialogFragment.getDialogId();
//use beKey for mapping to owning instance
String nextBeKey = nextDialogFragment.getBeKey();
String nextRightfulOwnerInstanceName
= SipApplicationSessionUtil.getActualServerInstanceForBeKey(nextBeKey);
if(nextRightfulOwnerInstanceName != null
&& nextRightfulOwnerInstanceName.equalsIgnoreCase(owningInstanceName)) {
nextVersion = nextDialogFragment.getVersion();
expatIdsSet.add(new ExpatListElement(nextDialogFragmentId, nextVersion, instanceName, true));
}
}
expatIds.addAll(expatIdsSet);
return expatIds;
}
*/
/**
* process the processBroadcastfinddialogfragmentexpatids for SipSession
* @param queryState
*/
public ReplicationState processBroadcastfinddialogfragmentexpatids(ReplicationState queryState) {
//complete query and send back response
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentexpatids:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentexpatids:owningInstance=" + queryState.getExtraParam());
}
if (SipReplicationUtil.isInstanceLoadBalancedByCLB() &&
!ReplicationHealthChecker.isServerLbEnabled(
ReplicationUtil.getInstanceName())) {
// Don't respond if the CLB is running but we are not CLB enabled
return null;
}
dfExpatListHandler.sendExpatQueryResponse(queryState);
return null;
}
public ReplicationState processBroadcastfinddialogfragmentreplicaexpatids(ReplicationState queryState) {
//complete query and send back response
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentreplicaexpatids:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentreplicaexpatids:owningInstance=" + queryState.getExtraParam());
}
if (SipReplicationUtil.isInstanceLoadBalancedByCLB() &&
!ReplicationHealthChecker.isServerLbEnabled(
ReplicationUtil.getInstanceName())) {
// Don't respond if the CLB is running but we are not CLB enabled
return null;
}
if(dfReplicaExpatHandler != null) {
dfReplicaExpatHandler.sendExpatQueryResponse(queryState);
}
return null;
}
//End Expat List for DialogFragment
/**
* Adds the given DialogFragment.
*
* @param d The DialogFragment to add
*/
@Override
public void registerDialogFragment(DialogFragment d) {
Object monitor = getReplicationSessionMonitor(d.getDialogId());
synchronized(monitor) {
super.registerDialogFragment(d);
}
}
/**
* Gets the DialogFragment with the given id
* from the active cache only
*
* @return The DialogFragment with the given id, or null if not
* found
*/
@Override
public DialogFragment findDialogFragmentFromCacheOnly(String id) {
if (id == null)
return (null);
Object monitor = getReplicationSessionMonitor(id);
synchronized(monitor) {
HADialogFragment result
= (HADialogFragment)super.findDialogFragmentFromCacheOnly(id);
if(!this.isActiveCacheReconciliationOngoing()) {
return result;
} else {
if(result == null || !result.isSuspect()) {
//if null just return it
//if not suspect it has already been checked
return result;
}
if(RollingUpgradeUtil.canUseSuspectSession(result,
expatIdsMap, expatReadWriteLock)) {
//if it passes the check return it
return result;
} else {
removeDialogFragmentFromCache(result, false);
return null;
}
}
}
}
/**
* Removes the given DialogFragment from only the active cache
*
* @param id The id of the DialogFragment to be removed
* @param hasTimedOut true if the DialogFragment is removed because it has
* expired, false otherwise
*/
@Override
protected void removeDialogFragmentFromCache(String id,
boolean hasTimedOut) {
Object monitor = getReplicationSessionMonitor(id);
synchronized(monitor) {
super.removeDialogFragmentFromCache(id, hasTimedOut);
}
}
/**
* Removes the given DialogFragment from only the active cache
*
* @param df The DialogFragment to be removed
* @param hasTimedOut true if the DialogFragment is removed because it has
* expired, false otherwise
*/
@Override
protected void removeDialogFragmentFromCache(DialogFragment df,
boolean hasTimedOut) {
Object monitor = getReplicationSessionMonitor(df.getDialogId());
synchronized(monitor) {
super.removeDialogFragmentFromCache(df, hasTimedOut);
}
}
protected void clearFromDialogFragmentManagerCache(String id, boolean hasTimedOut) {
DialogFragment df = super.findDialogFragmentFromCacheOnly(id);
if(df != null) {
this.removeDialogFragmentFromCache(df, hasTimedOut);
}
}
//end receiver side process methods
//start expiration related methods
private long deltaMillis = -1L;
/**
* a delta adjustment applied to the calculated wiggle adjustment
* this is to insure that SipSessions and DialogFragments are
* not prematurely purged by the reaper thread before an active
* SAS has possibly extended their expiration times
*/
protected long getDeltaMillis() {
if(deltaMillis == -1L) {
//can change this if reapInterval becomes configurable
long reapIntervalMilliSeconds
= getReaperThreadSleepTime();
deltaMillis = Math.max(ActivationHelper.DELAYED_EXPIRATION,
(reapIntervalMilliSeconds * 2));
}
return deltaMillis;
}
// void processExpiredDialogFragmentReplicas() {
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("in " + this.getClass().getName() + ">>processExpiredDialogFragmentReplicas");
// }
// BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
// ReplicationHealthChecker healthChecker
// = ReplicationHealthChecker.getInstance();
// int expiredReplicas = 0;
// for (Iterator it = replicatedDialogFragmentsCache.keys(); it.hasNext();) {
// ReplicationState nextState = (ReplicationState)
// replicatedDialogFragmentsCache.get((String) it.next());
// if (nextState != null) {
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("in " + this.getClass().getName() +
// ">>processExpiredDialogFragmentReplicas: nextState=" +
// nextState);
// }
// if (isExpiredDialogFragmentReplica(nextState)) {
// //if(!LoadProcessingGovernor.isSystemUnderLoadStress()
// // && !SipReplicationUtil.isExpatExtraDurationInEffect()
// // && !SipReplicationUtil.isExpatInProgress()) {
// if(!ExpatListHandler.isExpatExtraDurationInEffect()
// && !ExpatListHandler.isExpatInProgress()) {
// expiredReplicas++;
// removeFromDialogFragmentReplicationCache((String)nextState.getId());
// }
// }
// }
// }
//
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("in " + this.getClass().getName() +
// ">>processExpiredDialogFragmentReplicas: expiredReplicas.size=" +
// expiredReplicas);
// }
// replicaCache.processExpiredReplicaRemovals();
// }
private DialogFragmentExtraParams getDialogFragmentExtraParamsFrom(ReplicationState state) {
if(state == null) {
return null;
}
if(state.getDeserializedExtraParam() != null) {
return (DialogFragmentExtraParams)state.getDeserializedExtraParam();
} else {
//deserialize and cache result in state
DialogFragmentExtraParams extraParams =
DialogFragmentExtraParams.getDeserializedExtraParams(
state, isReplicationCompressionEnabled());
state.setDeserializedExtraParam(extraParams);
return extraParams;
}
}
protected boolean isExpiredDialogFragmentReplica(ReplicationState state) {
DialogFragmentExtraParams extraParams
= getDialogFragmentExtraParamsFrom(state);
return isExpiredDialogFragmentReplica(extraParams);
}
protected boolean isExpiredDialogFragmentReplica(DialogFragmentExtraParams extraParams) {
if(extraParams == null) {
return false;
} else {
long nextExpirationTime = extraParams.getExpirationTime();
//expirationTime of 0 or -1 means infinite
//in this case we expire if duration since last access
//is greater than SERVLET_TIMER_MAX_THRESHOLD_IN_MILLIS
if(nextExpirationTime == 0L || nextExpirationTime == -1L) {
if( (System.currentTimeMillis() - extraParams.getInternalLastAccessedTime()) > ActivationHelper.SERVLET_TIMER_MAX_THRESHOLD_IN_MILLIS ) {
return true;
} else {
return false;
}
} else {
return (System.currentTimeMillis() >= (nextExpirationTime + getDeltaMillis()));
}
}
}
//TODO: Why should we not have isExpatExtraDurationInEffect() &
// isExpatInProgress() check outside the loop?
Collection<DialogFragmentExtraParams> _findByCriteriaExpiredDialogFragments() {
Collection<DialogFragmentExtraParams> dfResult =
new LinkedList<DialogFragmentExtraParams>();
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>_findByCriteria_ExpiredDF");
}
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
int expiredReplicas = 0;
for (Iterator it = replicatedDialogFragmentsCache.keys(); it.hasNext();) {
ReplicationState nextState = (ReplicationState)
replicatedDialogFragmentsCache.get((String) it.next());
if (!ExpatListHandler.isExpatExtraDurationInEffect()
&& !ExpatListHandler.isExpatInProgress()
&& isExpiredDialogFragmentReplica(nextState)) {
expiredReplicas++;
dfResult.add(getDialogFragmentExtraParamsFrom(nextState));
}
}
return dfResult;
}
void _processExpiredDialogFragments() {
//code assumes that isExpired works for this type of ReplicationState
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>_process_ExpiredDF");
}
BackingStore dialogFragmentBackingStore
= this.getDialogFragmentBackingStore();
DialogFragmentExtraParams dialogFragmentExtraParamCriteria
= DialogFragmentExtraParams.createSearchCriteriaAll(this);
Collection<DialogFragmentExtraParams> dialogFragmentColl
= dialogFragmentBackingStore.findByCriteria(
null, dialogFragmentExtraParamCriteria);
int count = 0;
for (DialogFragmentExtraParams nextExtraParam : dialogFragmentColl) {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + " nextExtraParam=" + nextExtraParam);
}
if (!ExpatListHandler.isExpatExtraDurationInEffect()
&& !ExpatListHandler.isExpatInProgress()
&& isExpiredDialogFragmentReplica(nextExtraParam)) {
count++;
removeFromDialogFragmentReplicationCache(nextExtraParam.getId());
}
}
}
// void processExpiredDialogFragmentReplicasThirdPartySPI() {
// //code assumes that isExpired works for this type of ReplicationState
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("in " + this.getClass().getName() + ">>processExpiredDialogFragmentReplicasThirdPartySPI");
// }
// ArrayList expiredReplicas = new ArrayList(30);
// List dialogFragmentExtraParams = getDialogFragmentExtraParamsThirdPartySPI();
// for(Iterator it = dialogFragmentExtraParams.iterator(); it.hasNext();) {
// DialogFragmentExtraParams nextExtraParam = (DialogFragmentExtraParams)it.next();
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("in " + this.getClass().getName() + " nextExtraParam=" + nextExtraParam);
// }
// if(isExpiredDialogFragmentReplica(nextExtraParam)) {
// expiredReplicas.add(nextExtraParam);
// }
// }
// if(_logger.isLoggable(Level.FINE)) {
// _logger.fine("processExpiredDialogFragmentReplicasThirdPartySPI:expiredReplicas.size=" + expiredReplicas.size());
// }
// for(int i=0; i<expiredReplicas.size(); i++) {
// DialogFragmentExtraParams nextExtraParam =
// (DialogFragmentExtraParams)expiredReplicas.get(i);
// //FIXME not sure if this should be true?
// this.removeDialogFragment((String)nextExtraParam.getId(), false);
// }
// }
//
// List getDialogFragmentExtraParamsThirdPartySPI() {
// BackingStore dialogFragmentBackingStore
// = this.getDialogFragmentBackingStore();
// DialogFragmentExtraParams dialogFragmentExtraParamCriteria
// = DialogFragmentExtraParams.createSearchCriteriaAll();
// Collection<DialogFragmentExtraParams> dialogFragmentColl
// = dialogFragmentBackingStore.findByCriteria(dialogFragmentExtraParamCriteria);
//
// List result = new ArrayList();
// Iterator<DialogFragmentExtraParams> dialogFragmentResults =
// (Iterator<DialogFragmentExtraParams>) dialogFragmentColl.iterator();
// while (dialogFragmentResults.hasNext()) {
// DialogFragmentExtraParams eParam = dialogFragmentResults.next();
// result.add(eParam);
// }
// return result;
// }
//begin implement ReplicationManager
private boolean isBroadcastState(ReplicationState state) {
return(broadcastMethods.contains(state.getCommand()));
}
public void processMessage(ReplicationState message) {
//handle broadcast methods
if(isBroadcastState(message)) {
processBroadcastMessage(message);
return;
}
//handle non-void methods
ReplicationStateQueryResponse queryResult = null;
//do process non-void message (and cannot be response either)
if(!message.isResponseState() && !message.isVoidMethodReturnState()) {
//do non-void processing including sending response
queryResult = this.doProcessQueryMessage(message);
ReplicationState qResponse = queryResult.getState();
if(qResponse != null) {
//sourceInstanceName is preserved in the response
ReplicationState response =
ReplicationState.createResponseFrom(qResponse);
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("RepMgrBase:responseState=" + response);
}
this.doSendResponse(response);
}
return;
}
//end do process non-void message
boolean isResponse = this.doProcessMessage(message);
}
//return true if message is processResponse
public boolean doProcessMessage(ReplicationState message) {
boolean result = false;
String methodName = ReplicationUtil.getProcessMethodName(message);
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>doProcessMessageName=" + methodName);
}
try {
Class myClass = this.getClass();
myClass.getMethod(
methodName,
new Class[]{ message.getClass() }).invoke(
this, new Object[]{ message });
} catch (Throwable t) {
_logger.log(Level.SEVERE, "df_unknown_replication_method_name_error", new Object[] { this.getClass().getName(), methodName });
_logger.log(Level.SEVERE, t.getMessage(), t);
}
if(methodName.equals("processResponse")) {
result = true;
}
return result;
}
/**
* send the response
*
* @param dialogFragmentState
* The replication state response
*/
public void doSendResponse(ReplicationState dialogFragmentState) {
JxtaReplicationReceiver replicationReceiver =
JxtaReplicationReceiver.createInstance();
ReplicationState resultState =
replicationReceiver.sendReplicationStateResponse(dialogFragmentState);
}
public void processBroadcastMessage(ReplicationState message) {
ReplicationStateQueryResponse response = this.doProcessQueryMessage(message);
boolean isResponse = response.isResponse();
ReplicationState responseState = response.getState();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("processBroadcastMessage:after doProcessQueryMessage:response=" + isResponse);
_logger.fine("processBroadcastMessage:after doProcessQueryMessage:responseState=" + responseState);
_logger.fine("processBroadcastMessage:after doProcessQueryMessage:responseStateTrunk=" + responseState.getTrunkState());
_logger.fine("processBroadcastMessage:after doProcessQueryMessage:responseStateAttr=" + responseState.getState());
_logger.fine("processBroadcastMessage:after doProcessQueryMessage:responseStateVer=" + responseState.getVersion());
}
//don't send a response to a response
if(!isResponse) {
//point-to-point response back to sender
//System.out.println("processBroadcastMessage - need to send back result");
doSendQueryResponse(responseState, message.getInstanceName());
}
}
/**
* send the response
*
* @param dialogFragmentState
* The replication state response
* @param instanceName the name of the target instance
*/
public void doSendQueryResponse(ReplicationState dialogFragmentState, String instanceName) {
JxtaReplicationSender replicationSender =
JxtaReplicationSender.createInstance();
ReplicationState resultState =
replicationSender.sendReplicationStateQueryResponse(dialogFragmentState, instanceName, isReplicationUnicastLoadResponseBatchingEnabled());
}
//return true if message is processQueryResponse
public ReplicationStateQueryResponse doProcessQueryMessage(ReplicationState message) {
ReplicationState resultState = null;
String methodName = ReplicationUtil.getProcessMethodName(message);
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>doProcessQueryMessage:methodName=" + methodName);
_logger.fine("in " + this.getClass().getName() + ">>doProcessQueryMessage:thisInstance=" + instanceName + " returnInstance=" + message.getInstanceName() );
}
try {
Class myClass = this.getClass();
resultState = (ReplicationState) myClass.getMethod(
methodName,
new Class[]{ message.getClass() }).invoke(
this, new Object[]{ message });
} catch (Throwable t) {
_logger.log(Level.SEVERE, "df_unknown_replication_method_name_error", new Object[] { this.getClass().getName(), methodName });
_logger.log(Level.SEVERE, t.getMessage(), t);
}
boolean isResponse = (methodName.equals("processBroadcastresponse") || methodName.equals("processUnicastresponse"));
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>doProcessQueryMessage:resultState=" + resultState);
}
if (resultState != null) {
resultState.setRouteAdvertisement(message.getRouteAdvertisement());
}
//System.out.println("in " + this.getClass().getName() + ">>doProcessQueryMessage:resultState=" + resultState);
return new ReplicationStateQueryResponse(resultState, isResponse);
}
public void processQueryMessage(ReplicationState message, String returnInstance) {
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processQueryMessage:returnInstance= " + returnInstance);
}
ReplicationStateQueryResponse response = this.doProcessQueryMessage(message);
boolean isResponse = response.isResponse();
ReplicationState responseState = response.getState();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("processQueryMessage:after doProcessQueryMessage:response=" + isResponse);
_logger.fine("processQueryMessage:after doProcessQueryMessage:responseState=" + responseState);
}
//don't send a response to a response
if(!isResponse && responseState != null) {
//point-to-point response back to sender
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("processQueryMessage - need to send back result to " + returnInstance);
}
doSendQueryResponse(responseState, returnInstance);
}
}
public ReplicationState processBroadcastresponse(ReplicationState queryResponseState) {
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastresponse:queryResponseState=" + queryResponseState);
}
ReplicationResponseRepository.putFederatedEntry(queryResponseState);
return queryResponseState;
}
public void repair(long repairStartTime) {
if (!isRepairDuringFailure()) {
return;
}
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager>>repair");
}
if(ReplicationHealthChecker.isStopping()) {
return;
}
Iterator it = dialogFragments.values().iterator();
while (it.hasNext()) {
DialogFragment fragment = (DialogFragment) it.next();
//by virtue of being in the cache it is considered to
//but since invalidate is called before removal we must check
if(fragment.isValid()
&& (fragment.getDialogId() != null)
&& isDialogFragmentOlderThan(fragment, repairStartTime)) {
if(fragment.lockBackground()) {
try {
((HADialogFragment)fragment).setReplicated(false);
((HADialogFragment)fragment).setDirty(true);
saveDialogFragment(fragment);
} catch (IOException ex) {
_logger.log(Level.WARNING, "df_save_during_repair_error", fragment.toString());
_logger.log(Level.WARNING, ex.getMessage(), ex);
} finally {
fragment.unlockBackground();
}
}
}
}
}
protected boolean isDialogFragmentOlderThan(DialogFragment fragment, long aTime) {
// FIXME Uncomment when getLastAccessedTime is implemented.
// return (fragment.getLastAccessedTime() <= aTime);
return false;
}
public void repair(long repairStartTime, boolean checkForStopping) {
if (!isRepairDuringFailure()) {
return;
}
//FIXME
}
public void purge(String owningInstanceName, long purgeStartTime) {
//do not purge if we are the replica partner
//of the owning instance
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String replicatedFromInstanceName
= healthChecker.getReshapeReplicateFromInstanceName();
if(replicatedFromInstanceName != null && replicatedFromInstanceName.equalsIgnoreCase(owningInstanceName)) {
return;
}
List idsToRemove = new ArrayList();
BaseCache replicatedDialogFragmentsCache = getReplicatedDialogFragments();
Iterator it = replicatedDialogFragmentsCache.values();
/* todo remove after testing
Iterator it = replicatedDialogFragments.values();
*/
while(it.hasNext()) {
ReplicationState nextState
= (ReplicationState)it.next();
DialogFragmentExtraParams extraParams =
DialogFragmentExtraParams.getDeserializedExtraParams(
nextState, isReplicationCompressionEnabled());
if(extraParams != null) {
String nextOwningInstance = extraParams.getCurrentOwnerInstanceName();
if(nextOwningInstance != null
&& nextOwningInstance.equalsIgnoreCase(owningInstanceName)) {
idsToRemove.add((String)nextState.getId());
}
}
}
for(int i=0; i< idsToRemove.size(); i++) {
removeFromDialogFragmentReplicationCache((String)idsToRemove.get(i));
}
}
public void respondToFailure(String failedInstanceName, boolean checkForStopping) {
//FIXME Is there something specific to DialogFragments needed to be done here
// Following comment was copied from ReplicationDialogFragmentManager, doubt it applies to DialogFragment
// only do timer wakeup if failedInstanceName was replication to us
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String replicatedFromInstanceName
= healthChecker.getReshapeReplicateFromInstanceName();
if(!failedInstanceName.equalsIgnoreCase(replicatedFromInstanceName)) {
return;
}
}
private void setDialogFragmentStorePool(StorePool dialogFragmentStorePool) {
this.dialogFragmentStorePool = dialogFragmentStorePool;
}
public boolean isReplicationEnabled() {
return isReplicationInitialized.get() && isReplicationStarted.get();
}
boolean isThirdPartyBackingStoreInUse() {
BackingStore dialogFragmentBackingStore
= getDialogFragmentBackingStore();
return (!(dialogFragmentBackingStore instanceof JxtaBackingStoreImpl));
}
// begin post join reconciliation
/**
* do reconciliation processing
* used for both rolling upgrade and post network partition rejoin
* @param waitTime the waitTime in seconds
* @param ctx the RollingUpgradeContext
*/
public void doPostJoinReconciliation(long waitTime, RollingUpgradeContext ctx) {
long startTime = System.currentTimeMillis();;
if (_logger.isLoggable(Level.FINE)) {
startTime = System.currentTimeMillis();
}
CountDownLatch doneSignal = new CountDownLatch(2);
//do active cache reconciliation
ReconcileActive reconcileActive
= new ReconcileActive(this, waitTime, doneSignal, ctx);
RollingUpgradeHandler.executeTask(reconcileActive);
//trigger replica cache reconciliation
TriggerReconcileReplica triggerReconcileReplica
= new TriggerReconcileReplica(this, waitTime, doneSignal, ctx);
RollingUpgradeHandler.executeTask(triggerReconcileReplica);
try {
doneSignal.await(waitTime, TimeUnit.SECONDS);
} catch(InterruptedException ex) {
;
} finally {
if(doneSignal.getCount() != 0) {
String errorMsg = "ReplicationDialogFragmentManager>>doPostJoinReconciliation timed out after " + waitTime + " seconds";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager doPostJoinReconciliation successful after a wait: wait time = " + (System.currentTimeMillis() - startTime));
}
}
}
}
// end post join reconciliation
// begin rolling upgrade related code
public void doRollingUpgradePreShutdownProcessing(long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
//do syncpoint save
doSyncpointSave(waitTime, doneSignal, ctx);
}
public void doRollingUpgradePostStartupProcessing(String rollingUpgradeType, long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
if(RollingUpgradeHandler.isFileBased(rollingUpgradeType)) {
//do syncpoint load
doSyncpointLoad(waitTime, doneSignal, ctx);
} else {
doMemoryLoad(waitTime, doneSignal, ctx);
}
}
public void doRollingUpgradePostStartupReconciliationProcessing(long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
//do post join reconciliation
try {
doPostJoinReconciliation(waitTime, ctx);
} finally {
doneSignal.countDown();
}
}
void doSyncpointSave(long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
try {
if(this.isSkipRollingUpgradeBackupRestore()) {
return;
}
DialogFragmentFileSync syncStore = new DialogFragmentFileSync((ReplicationManager)this);
try {
syncStore.save(waitTime, ctx);
} catch (IOException ex) {
ex.printStackTrace();
String errorMsg = "ReplicationDialogFragmentManager>>doSyncPointSave IOException";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
}
} finally {
doneSignal.countDown();
}
}
void doSyncpointLoad(long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
try {
if(this.isSkipRollingUpgradeBackupRestore()) {
return;
}
DialogFragmentFileSync syncStore = new DialogFragmentFileSync((ReplicationManager)this);
try {
syncStore.load(waitTime, ctx);
markActiveCacheAsSuspected(true);
} catch (IOException ex) {
String errorMsg = "ReplicationDialogFragmentManager>>doSyncPointLoad IOException";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} catch (ClassNotFoundException ex2) {
String errorMsg = "ReplicationDialogFragmentManager>>doSyncPointLoad ClassNotFoundException";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
}
} finally {
doneSignal.countDown();
}
}
void doMemoryLoad(long waitTime, CountDownLatch doneSignal, RollingUpgradeContext ctx) {
try {
if(this.isSkipRollingUpgradeBackupRestore()) {
return;
}
DialogFragmentMemorySync syncStore = new DialogFragmentMemorySync((ReplicationManager)this);
try {
syncStore.load(waitTime, ctx);
markActiveCacheAsSuspected(true);
} catch (IOException ex) {
String errorMsg = "ReplicationDialogFragmentManager>>doMemoryLoad IOException";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} catch (ClassNotFoundException ex2) {
String errorMsg = "ReplicationDialogFragmentManager>>doMemoryLoad ClassNotFoundException";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
}
} finally {
doneSignal.countDown();
}
}
void restoreActiveCacheViaMemory(long waitTime, RollingUpgradeContext ctx) {
triggerActiveCacheRestoration(waitTime, ctx);
}
void restoreReplicaCacheViaMemory(long waitTime, RollingUpgradeContext ctx) {
triggerReplicaCacheRestoration(waitTime, ctx);
}
public void triggerActiveCacheRestoration(long waitTime, RollingUpgradeContext ctx) {
long startTime = System.currentTimeMillis();
int numberOfRespondants = RollingUpgradeUtil.getNumberOfExpectedRespondants();
restoreActiveCacheDoneSignal = new CountDownLatch(numberOfRespondants);
//trigger replicateTo partner(s) to do
//active cache restoration
ownedReplicaListsReceivedForActiveCacheRestoration
= new ConcurrentHashMap<String, ReplicationState>();
doTriggerActiveCacheRestoration(ReplicationUtil.checkIsInstanceLoadBalancedByCLB());
try {
restoreActiveCacheDoneSignal.await(waitTime, TimeUnit.SECONDS);
processActiveCacheRestorationResults(ownedReplicaListsReceivedForActiveCacheRestoration);
} catch(InterruptedException ex) {
;
} finally {
if(restoreActiveCacheDoneSignal.getCount() != 0) {
String errorMsg = "ReplicationDialogFragmentManager>>triggerActiveCacheRestoration timed out after " + waitTime + " seconds";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager triggerActiveCacheRestoration successful after a wait: wait time = " + (System.currentTimeMillis() - startTime)+ " active DialogFragments restored: " + dialogFragments.size());
}
}
ctx.addMessage(getApplicationId(), "Active cache restoration completed for DialogFragment. " +
", Size of active cache = " + dialogFragments.size() +
", Time taken (ms) = " + (System.currentTimeMillis()-startTime));
}
}
protected void doTriggerActiveCacheRestoration(boolean isInstanceLoadBalancedByCLB) {
if(!isInstanceLoadBalancedByCLB) {
//trigger replicateTo partner to do
//active cache restoration
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String replicateToInstanceName = healthChecker.getReshapeReplicateToInstanceName(null, 0L);
sendRollingUpgradeActiveCacheRestorationAdvisory(replicateToInstanceName);
} else {
//trigger all partners to do
//active cache restoration
sendRollingUpgradeActiveCacheRestorationAdvisory();
}
}
protected void processActiveCacheRestorationResults(ConcurrentHashMap<String, ReplicationState> ownedReplicaListsReceivedForActiveCacheRestoration) {
DialogFragmentStoreImpl store = getSingletonDialogFragmentStore();
Collection<ReplicationState> ownedReplicasList = ownedReplicaListsReceivedForActiveCacheRestoration.values();
Iterator<ReplicationState> it = ownedReplicasList.iterator();
while(it.hasNext()) {
ReplicationState nextOwnedListReplicationState = it.next();
List<ReplicationState>nextOwnedListOfStates
= (List<ReplicationState>)RollingUpgradeUtil.getObject(nextOwnedListReplicationState.getState());
for(int i=0; i<nextOwnedListOfStates.size(); i++) {
ReplicationState nextState = nextOwnedListOfStates.get(i);
HADialogFragment nextDialogFragment = null;
try {
nextDialogFragment = store.getDialogFragment(nextState);
} catch (Exception ex) {}
if(nextDialogFragment != null) {
registerDialogFragment(nextDialogFragment);
}
}
}
}
public void triggerReplicaCacheRestoration(long waitTime, RollingUpgradeContext ctx) {
long startTime = System.currentTimeMillis();
int numberOfRespondants = RollingUpgradeUtil.getNumberOfExpectedRespondants();
restoreReplicaCacheDoneSignal = new CountDownLatch(numberOfRespondants);
//trigger replicateFrom partner(s) to do
//replica cache restoration
ownedReplicaListsReceivedForReplicaCacheRestoration
= new ConcurrentHashMap<String, ReplicationState>();
doTriggerReplicaCacheRestoration(ReplicationUtil.checkIsInstanceLoadBalancedByCLB());
try {
restoreReplicaCacheDoneSignal.await(waitTime, TimeUnit.SECONDS);
processReplicaCacheRestorationResults(ownedReplicaListsReceivedForReplicaCacheRestoration);
} catch(InterruptedException ex) {
;
} finally {
if(restoreReplicaCacheDoneSignal.getCount() != 0) {
String errorMsg = "ReplicationDialogFragmentManager>>triggerReplicaCacheRestoration timed out after " + waitTime + " seconds";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager triggerReplicaCacheRestoration successful after a wait: wait time = " + (System.currentTimeMillis() - startTime) + " replica DialogFragments restored: " + getReplicatedDialogFragments().getEntryCount());
}
}
ctx.addMessage(getApplicationId(), "Replica cache restoration completed for DialogFragment. " +
", Size of replica cache = " + getReplicatedDialogFragments().getEntryCount() +
", Time taken (ms) = " + (System.currentTimeMillis()-startTime));
}
}
protected void doTriggerReplicaCacheRestoration(boolean isInstanceLoadBalancedByCLB) {
if(!isInstanceLoadBalancedByCLB) {
//trigger replicateFrom partner to do
//replica cache restoration
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String replicateFromInstanceName = healthChecker.getReshapeReplicateFromInstanceName(null);
sendRollingUpgradeReplicaCacheRestorationAdvisory(replicateFromInstanceName);
} else {
//trigger all partners to do
//replica cache restoration
sendRollingUpgradeReplicaCacheRestorationAdvisory();
}
}
protected void processReplicaCacheRestorationResults(ConcurrentHashMap<String, ReplicationState> ownedReplicaListsReceivedForActiveCacheRestoration) {
Collection<ReplicationState> ownedReplicasList = ownedReplicaListsReceivedForActiveCacheRestoration.values();
Iterator<ReplicationState> it = ownedReplicasList.iterator();
while(it.hasNext()) {
ReplicationState nextOwnedListReplicationState = it.next();
List<ReplicationState>nextOwnedListOfStates
= (List<ReplicationState>)RollingUpgradeUtil.getObject(nextOwnedListReplicationState.getState());
for(int i=0; i<nextOwnedListOfStates.size(); i++) {
ReplicationState nextState = nextOwnedListOfStates.get(i);
this.putInDialogFragmentReplicationCache(nextState);
}
}
}
void markActiveCacheAsSuspected(boolean value) {
Iterator it = dialogFragments.values().iterator();
while(it.hasNext()) {
((HADialogFragment)it.next()).setSuspect(value);
}
}
public void doActiveCacheReconciliation(long waitTime, RollingUpgradeContext ctx) {
reconcileDialogFragmentActiveCache(waitTime, ctx);
}
public ConcurrentHashMap<String, FederatedQueryListElement> triggerGetIdsForActiveCacheReconciliation(long waitTime) {
long startTime = 0L;
if (_logger.isLoggable(Level.FINE)) {
startTime = System.currentTimeMillis();
}
//sending to all for both types of load balancer
int numberOfRespondants = ReplicationUtil.getNumberExpectedRespondants();
getIdsForActiveCacheReconciliationDoneSignal = new CountDownLatch(numberOfRespondants);
//trigger replicateTo partner(s) to
//provide owned session ids list(s)
ownedIdsForActiveCacheReconciliation
= new ConcurrentHashMap<String, ReplicationState>();
doTriggerGetIdsForActiveCacheReconciliation(ReplicationUtil.checkIsInstanceLoadBalancedByCLB());
ConcurrentHashMap<String, FederatedQueryListElement> result = null;
try {
getIdsForActiveCacheReconciliationDoneSignal.await(waitTime, TimeUnit.SECONDS);
result = processCacheReconciliationResults(ownedIdsForActiveCacheReconciliation);
} catch(InterruptedException ex) {
result = new ConcurrentHashMap<String, FederatedQueryListElement>();
} finally {
if(getIdsForActiveCacheReconciliationDoneSignal.getCount() != 0) {
String errorMsg = "ReplicationDialogFragmentManager>>triggerGetIdsForActiveCacheReconciliation timed out after " + waitTime + " seconds";
_logger.log(Level.WARNING, errorMsg);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager triggerGetIdsForActiveCacheReconciliation successful after a wait: wait time = " + (System.currentTimeMillis() - startTime));
}
}
ownedIdsForActiveCacheReconciliation = null;
}
return result;
}
protected void doTriggerGetIdsForActiveCacheReconciliation(boolean isInstanceLoadBalancedByCLB) {
//trigger all partners to do
//active cache reconciliation
sendRollingUpgradeGetIdsForActiveCacheReconciliationAdvisory();
}
/**
* broadcast a rolling upgrade getIds
* for replica cache reconciliation advisory message
*
*/
protected void sendRollingUpgradeGetIdsForActiveCacheReconciliationAdvisory() {
//broadcast rolling upgrade getIds for replica cache reconciliation advisory
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_ADVISORY);
}
public void processRollingupgradegetidsforactivecachereconciliationadvisory(ReplicationState replicationState) {
String instanceName = ReplicationUtil.getInstanceName();
String owningInstanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processRollingupgradegetidsforactivecachereconciliationadvisory:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processRollingupgradegetidsforactivecachereconciliationadvisory:owningInstance=" + owningInstanceName);
}
List<FederatedQueryListElement> sessionIds = getDialogFragmentIds(owningInstanceName);
sendReplicasList(sessionIds, owningInstanceName, MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_ACTIVE_CACHE_RECONCILIATION_RESPONSE);
}
public void processRollingupgradegetidsforactivecachereconciliationresponse(ReplicationState replicationState) {
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradegetidsforactivecachereconciliationresponse received from " + instanceName);
}
ownedIdsForActiveCacheReconciliation.putIfAbsent(instanceName, replicationState);
getIdsForActiveCacheReconciliationDoneSignal.countDown();
}
// temporarily keep the migratedDFs until they successully reach the destination.
ConcurrentHashMap<String, Set<String>> migratedDfIds =
new ConcurrentHashMap<String, Set<String>>();
public void processReconciledfrequest(ReplicationState reconcileRequest) {
Set<String> migratedSessionIds = RollingUpgradeUtil.processActiveCacheReconciliationRequest(reconcileRequest,
getSingletonDialogFragmentStore(),
RECONCILE_DF_RESPONSE, isReplicationCompressionEnabled());
// keep the migrated DFs and passivate them once they are activated in the remote instance.
migratedDfIds.put(reconcileRequest.getInstanceName(), migratedSessionIds);
}
public void processReconciledfresponse(ReplicationState reconcileResponse) {
reconciledActiveDFs.put(reconcileResponse.getInstanceName(),
reconcileResponse);
activeDfReconcileSignal.get().countDown();
}
public void processReconciledfreplicarequest(ReplicationState reconcileRequest) {
RollingUpgradeUtil.processReplicaCacheReconciliationRequest(reconcileRequest,
dialogFragments,
RECONCILE_DF_REPLICA_RESPONSE, isReplicationCompressionEnabled());
}
public void processReconciledfreplicaresponse(ReplicationState reconcileResponse) {
reconciledReplicaDFs.put(reconcileResponse.getInstanceName(),
reconcileResponse);
replicaDfReconcileSignal.get().countDown();
}
public void processPostreconciledfrequest(ReplicationState reconcileRequest) {
boolean saveMigratedSessionToReplicaCache = EEPersistenceTypeResolver.REPLICATED_TYPE.
equalsIgnoreCase(getPassedInPersistenceType());
RollingUpgradeUtil.processPostActiveCacheReconciliationRequest(reconcileRequest,
getSingletonDialogFragmentStore(),
migratedDfIds.get(reconcileRequest.getInstanceName()),
saveMigratedSessionToReplicaCache,
POST_RECONCILE_DF_RESPONSE);
}
public void processPostreconciledfresponse(ReplicationState reconcileResponse) {
remotelyLockedDFs.put(reconcileResponse.getInstanceName(), reconcileResponse);
postDfReconcileSignal.get().countDown();
}
private void reconcileDialogFragmentActiveCache(long waitTime, RollingUpgradeContext ctx) {
long startTime = System.currentTimeMillis();
DialogFragmentStoreImpl storeImpl = getSingletonDialogFragmentStore();
int reconciledSessions = RollingUpgradeUtil.doActiveCacheReconciliation(
storeImpl, RECONCILE_DF_REQUEST, activeDfReconcileSignal,
waitTime, reconciledActiveDFs);
long timeTaken = (System.currentTimeMillis() - startTime) / 1000;
int suspectSessions = RollingUpgradeUtil.doPostActiveCacheReconcilation(
storeImpl, POST_RECONCILE_DF_REQUEST,
postDfReconcileSignal, waitTime - timeTaken, remotelyLockedDFs);
timeTaken = System.currentTimeMillis() - startTime;
ctx.addMessage(getApplicationId(), "Active cache reconciliation completed for DialogFragment. " +
" No. of sessions reconciled = " + reconciledSessions +
", No. of sessions still in suspect = " + suspectSessions +
", Size of active cache = " + dialogFragments.size() +
", Size of expat = " + expatIdsMap.size() + ", Time taken (ms) = " + timeTaken);
}
protected void doTriggerReplicaCacheReconciliation(long waitTime, boolean isInstanceLoadBalancedByCLB) {
if(!isInstanceLoadBalancedByCLB) {
//trigger replicateFrom partner to do
//replica cache reconciliation
ReplicationHealthChecker healthChecker
= ReplicationHealthChecker.getInstance();
String replicateFromInstanceName = healthChecker.getReshapeReplicateFromInstanceName();
sendRollingUpgradeAdvisory(waitTime, replicateFromInstanceName);
} else {
//trigger all partners to do
//replica cache reconciliation
sendRollingUpgradeAdvisory(waitTime);
}
}
public void triggerReplicaCacheReconciliation(long waitTime, RollingUpgradeContext ctx) {
int numberOfRespondants
= RollingUpgradeUtil.getNumberOfExpectedRespondants();
long startTime = System.currentTimeMillis();
if (_logger.isLoggable(Level.FINE)) {
startTime = System.currentTimeMillis();
}
reconcileReplicaCacheDoneSignal = new CountDownLatch(numberOfRespondants);
//trigger replicateFrom partner(s) to do
//replica cache reconciliation
doTriggerReplicaCacheReconciliation(waitTime, ReplicationUtil.checkIsInstanceLoadBalancedByCLB());
try {
reconcileReplicaCacheDoneSignal.await(waitTime, TimeUnit.SECONDS);
} catch(InterruptedException ex) {
;
} finally {
if(reconcileReplicaCacheDoneSignal.getCount() != 0) {
String errorMsg = "ReplicationDialogFragmentManager>>triggerReplicaCacheReconciliation timed out after " + waitTime + " seconds";
ReplicationUtil.handleErrorMsg(errorMsg, _logger, ctx);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationDialogFragmentManager triggerReplicaCacheReconciliation successful after a wait: wait time = " + (System.currentTimeMillis() - startTime));
}
}
}
}
protected ConcurrentHashMap<String, FederatedQueryListElement> processCacheReconciliationResults(ConcurrentHashMap<String, ReplicationState> ownedIdsForReplicaCacheReconciliation) {
ConcurrentHashMap<String, FederatedQueryListElement> result =
new ConcurrentHashMap<String, FederatedQueryListElement>();
Collection<ReplicationState> ownedReplicasList = ownedIdsForReplicaCacheReconciliation.values();
Iterator<ReplicationState> it = ownedReplicasList.iterator();
while(it.hasNext()) {
ReplicationState nextOwnedListReplicationState = it.next();
List<FederatedQueryListElement>nextOwnedListOfStates
= (List<FederatedQueryListElement>)RollingUpgradeUtil.getObject(nextOwnedListReplicationState.getState());
for(int i=0; i<nextOwnedListOfStates.size(); i++) {
FederatedQueryListElement nextElement = nextOwnedListOfStates.get(i);
String nextElementId = nextElement.getId();
if(nextElementId != null) {
FederatedQueryListElement existingElement = result.get(nextElementId);
if(existingElement == null || existingElement.getVersion() < nextElement.getVersion()) {
result.put(nextElementId, nextElement);
}
}
}
}
return result;
}
/**
* reconcile the replica cache (of your replica partner)
* query instance1 to get a list of replica id/version data elements
* then do 2 iterations:
* iterate over the query result:
* if an id from this list does not exist in this active cache
* issue a remove message & load acknowledgment
* if an id exists and the versions match do nothing
* if an id exists and the active version is > replica version,
* - do a save
* iterate over the active cache
* if an id from active cache does not exist in the replica list
* - do a save
* @param waitTime the waitTime
*/
public void doReplicaCacheReconciliation(long waitTime, RollingUpgradeContext ctx) {
reconcileDialogFragmentReplicaCache(waitTime, ctx);
}
public ConcurrentHashMap<String, FederatedQueryListElement> triggerGetIdsForReplicaCacheReconciliation(long waitTime) {
long startTime = 0L;
if (_logger.isLoggable(Level.FINE)) {
startTime = System.currentTimeMillis();
}
//sending to all for both types of load balancer
int numberOfRespondants = ReplicationUtil.getNumberExpectedRespondants();
getIdsForReplicaCacheReconciliationDoneSignal = new CountDownLatch(numberOfRespondants);
//trigger replicateTo partner(s) to
//provide owned dialog fragment ids list(s)
ownedIdsForReplicaCacheReconciliation
= new ConcurrentHashMap<String, ReplicationState>();
doTriggerGetIdsForReplicaCacheReconciliation(ReplicationUtil.checkIsInstanceLoadBalancedByCLB());
ConcurrentHashMap<String, FederatedQueryListElement> result = null;
try {
getIdsForReplicaCacheReconciliationDoneSignal.await(waitTime, TimeUnit.SECONDS);
result = processCacheReconciliationResults(ownedIdsForReplicaCacheReconciliation);
} catch(InterruptedException ex) {
result = new ConcurrentHashMap<String, FederatedQueryListElement>();
} finally {
if(getIdsForReplicaCacheReconciliationDoneSignal.getCount() != 0) {
String errorMsg = "ReplicationManagerBase>>triggerGetIdsForReplicaCacheReconciliation timed out after " + waitTime + " seconds";
_logger.log(Level.WARNING, errorMsg);
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.fine("ReplicationManagerBase triggerGetIdsForReplicaCacheReconciliation successful after a wait: wait time = " + (System.currentTimeMillis() - startTime));
}
}
ownedIdsForReplicaCacheReconciliation = null;
}
return result;
}
protected void doTriggerGetIdsForReplicaCacheReconciliation(boolean isInstanceLoadBalancedByCLB) {
//trigger all partners to do
//replica cache reconciliation
sendRollingUpgradeGetIdsForReplicaCacheReconciliationAdvisory();
}
void cleanOutZombieReplicas() {
//FIXME for now issue load acknowledgement for each
//active cache entry
//this is functionally correct but not optimal
//solution will be to improve query for replica
//ids to track the source instance and then only
//issue load acks to those ids that are not from
//our replicate to partner
HADialogFragment df = null;
Iterator it = dialogFragments.values().iterator();
while(it.hasNext()) {
df = (HADialogFragment)it.next();
this.sendLoadAcknowledgement(df.getDialogId(), df.getVersion(), MESSAGE_BROADCAST_LOAD_RECEIVED_DIALOG_FRAGMENT, df.getBeKey());
}
}
public void processRollingupgradegetidsforreplicacachereconciliationadvisory(ReplicationState replicationState) {
String instanceName = ReplicationUtil.getInstanceName();
String owningInstanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processRollingupgradegetidsforreplicacachereconciliationadvisory:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processRollingupgradegetidsforreplicacachereconciliationadvisory:owningInstance=" + owningInstanceName);
}
List<FederatedQueryListElement> sessionIds = getDialogFragmentIds(owningInstanceName);
sendReplicasList(sessionIds, owningInstanceName, MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_RESPONSE);
}
public void processRollingupgradegetidsforreplicacachereconciliationresponse(ReplicationState replicationState) {
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradegetidsforreplicacachereconciliationresponse received from " + instanceName);
}
ownedIdsForReplicaCacheReconciliation.putIfAbsent(instanceName, replicationState);
getIdsForReplicaCacheReconciliationDoneSignal.countDown();
}
private void reconcileDialogFragmentReplicaCache(long waitTime, RollingUpgradeContext ctx) {
long startTime = System.currentTimeMillis();
DialogFragmentStoreImpl storeImpl = getSingletonDialogFragmentStore();
int reconciledSessions = RollingUpgradeUtil.doReplicaCacheReconciliation(
storeImpl, RECONCILE_DF_REPLICA_REQUEST,
replicaDfReconcileSignal, waitTime, reconciledReplicaDFs);
long timeTaken = System.currentTimeMillis() - startTime;
ctx.addMessage(getApplicationId(), "Replica cache reconciliation completed for DialogFragment. " +
" No of sessions reconciled = " + reconciledSessions +
", Size of replica cache = " + getReplicatedDialogFragments().getEntryCount() +
", Time taken (ms) = " + timeTaken);
}
protected void sendLoadAcknowledgement(String id, long version, String command, String beKey) {
JxtaReplicationSender sender
= JxtaReplicationSender.createInstance();
ReplicationState loadReceivedState =
ReplicationState.createBroadcastLoadReceivedState(MODE_SIP, id, this.getApplicationId(), version, ReplicationUtil.getInstanceName(), command);
if ((beKey != null) && replicationUtil.isInstanceLoadBalancedByCLB()){
loadReceivedState.setProperty(ReplicationState.IGNORE_REMOVE_INSTANCE_NAME,
replicationUtil.getFailoverServerInstanceForBeKey(beKey));
} else {
ReplicationHealthChecker healthChecker = ReplicationHealthChecker.getInstance();
String currentReplicaPartner = healthChecker.getCurrentPartnerInstanceName();
loadReceivedState.setProperty(ReplicationState.IGNORE_REMOVE_INSTANCE_NAME,
currentReplicaPartner);
}
sender.sendBroadcastQuery(loadReceivedState);
}
protected void readDialogFragments(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
int count = ois.readInt();
for(int i=0; i<count; i++) {
HADialogFragment nextDF = (HADialogFragment)ois.readObject();
dialogFragments.put(nextDF.getDialogId(), nextDF);
}
}
protected void readReplicatedDialogFragmentUpdates(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
replicaCache.readReplicatedSessionUpdates(ois);
}
protected void writeDialogFragments(ObjectOutputStream oos)
throws IOException {
ReplicationUtil.writeHashMap(dialogFragments, oos);
}
protected void writeReplicatedDialogFragmentUpdates(ObjectOutputStream oos)
throws IOException {
replicaCache.writeReplicatedSessionUpdates(oos);
}
List<FederatedQueryListElement> getDialogFragmentIds(String owningInstanceName) {
List<FederatedQueryListElement> dialogFragmentIds = new ArrayList();
//using set to avoid dups
HashSet dialogFragmentIdsSet = new HashSet();
List replicasToRemove = new ArrayList();
ReplicationHealthChecker healthChecker = ReplicationHealthChecker.getInstance();
String correctBuddyReplicaName
= healthChecker.getReshapeReplicateToInstanceName(null, owningInstanceName, 0L);
//iterate over dialog fragment replicas
Iterator it = getReplicatedDialogFragments().values();
while(it.hasNext()) {
ReplicationState nextState
= (ReplicationState)it.next();
if(!RollingUpgradeUtil.filterOwnership(owningInstanceName, correctBuddyReplicaName, nextState, dialogFragmentIdsSet)) {
//we remove this entry if it is not on the correct replica partner - i.e. it is a zombie
replicasToRemove.add(nextState.getId());
}
}
for(int i=0; i<replicasToRemove.size(); i++) {
String nextId = (String)replicasToRemove.get(i);
if(nextId != null) {
removeFromDialogFragmentReplicationCache(nextId);
}
}
dialogFragmentIds.addAll(dialogFragmentIdsSet);
return dialogFragmentIds;
}
List<FederatedQueryListElement> getDialogFragmentIdsThirdPartySPI(String owningInstanceName) {
BackingStore backingStore
= this.getDialogFragmentBackingStore();
DialogFragmentExtraParams dfExtraParamCriteria
= DialogFragmentExtraParams.createSearchCriteria(this, owningInstanceName);
Collection<DialogFragmentExtraParams> dfColl
= backingStore.findByCriteria(null, dfExtraParamCriteria);
List<FederatedQueryListElement> dialogFragmentIds = new ArrayList();
//using set to avoid dups
HashSet dialogFragmentIdsSet = new HashSet();
Iterator<DialogFragmentExtraParams> dfResults =
(Iterator<DialogFragmentExtraParams>) dfColl.iterator();
while (dfResults.hasNext()) {
DialogFragmentExtraParams eParam = dfResults.next();
if (owningInstanceName.equals(eParam.getCurrentOwnerInstanceName())) {
dialogFragmentIdsSet.add(new FederatedQueryListElement((String)eParam.getId(), -1L, ReplicationUtil.getInstanceName()));
}
}
dialogFragmentIds.addAll(dialogFragmentIdsSet);
return dialogFragmentIds;
}
/**
* process the broadcastfinddialogfragmentids for DialogFragment
* @param queryState
*/
public ReplicationState processBroadcastfinddialogfragmentids(ReplicationState queryState) {
//complete query and send back response
String instanceName = ReplicationUtil.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentids:instance: " + instanceName);
_logger.fine("in " + this.getClass().getName() + ">>processBroadcastfinddialogfragmentids:owningInstance=" + queryState.getInstanceName());
}
String owningInstanceName = queryState.getInstanceName();
List dialogFragmentIds = null;
//sessionIds = getDialogFragmentIds(owningInstanceName);
if(this.isThirdPartyBackingStoreInUse()) {
dialogFragmentIds
= getDialogFragmentIdsThirdPartySPI(owningInstanceName);
} else {
dialogFragmentIds
= getDialogFragmentIds(owningInstanceName);
}
byte[] resultState = null;
try {
resultState = ReplicationUtil.getByteArray((ArrayList)dialogFragmentIds);
} catch (IOException ex) {
//deliberate no-op
;
}
//first check for none found in either active or replica caches
if(dialogFragmentIds == null || dialogFragmentIds.isEmpty()) {
//return nack
return ReplicationState.createQueryResponseFrom(queryState, true);
} else {
return ReplicationState.createQueryResponseFrom(queryState, resultState);
}
}
public int removeExpiredSessions() {
//deliberate no op
return 0;
}
/**
* send a rolling upgrade advisory message to instance to trigger
* it to do rolling upgrade reconciliation for the sending
* instance
*
* @param waitTime the waitTime
* @param instanceName the instance to be sent the rolling upgrade advisory
*/
public void sendRollingUpgradeAdvisory(long waitTime, String instanceName) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager",
"sendRollingUpgradeAdvisory",
new Object[] {instanceName});
}
try {
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY, instanceName, waitTime);
} catch (IOException ex) {}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager",
"sendRollingUpgradeAdvisory");
}
}
/**
* broadcast a rolling upgrade advisory message to trigger
* rolling upgrade reconciliation for the sending
* instance
*/
protected void sendRollingUpgradeAdvisory(long waitTime) {
//broadcast rolling upgrade advisory
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY, waitTime);
}
/**
* send a rolling upgrade advisory message to instance to trigger
* it to do rolling upgrade reconciliation for the sending
* instance
*
* @param instanceName the instance to be sent the rolling upgrade advisory
*/
public void sendRollingUpgradeAdvisory(String instanceName) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager",
"sendRollingUpgradeAdvisory",
new Object[] {instanceName});
}
try {
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY, instanceName);
} catch (IOException ex) {}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager",
"sendRollingUpgradeAdvisory");
}
}
/**
* broadcast a rolling upgrade advisory message to trigger
* rolling upgrade reconciliation for the sending
* instance
*/
protected void sendRollingUpgradeAdvisory() {
//broadcast rolling upgrade advisory
JxtaReplicationSender sender
= JxtaReplicationSender.createInstance();
//ok to use this method even while sending via broadcast in this case
ReplicationState rollingUpgradeAdvisoryState
= ReplicationState.createUnicastLoadAdvisoryState(MODE_SIP, "id", this.getApplicationId(), 0L, ReplicationUtil.getInstanceName(), MESSAGE_BROADCAST_ROLLING_UPGRADE_ADVISORY);
sender.sendBroadcastQuery(rollingUpgradeAdvisoryState);
}
/**
* send a rolling upgrade advisory message to instance to trigger
* it to do rolling upgrade active cache restoration for the sending
* instance
*
* @param instanceName the instance to be sent the rolling upgrade advisory
*/
public void sendRollingUpgradeActiveCacheRestorationAdvisory(String instanceName) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager",
"sendRollingUpgradeActiveCacheRestorationAdvisory",
new Object[] {instanceName});
}
try {
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_ADVISORY, instanceName);
} catch (IOException ex) {}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager",
"sendRollingUpgradeActiveCacheRestorationAdvisory");
}
}
/**
* broadcast a rolling upgrade active cache restoration advisory message to trigger
* rolling upgrade active cache restoration for the sending
* instance
*/
protected void sendRollingUpgradeActiveCacheRestorationAdvisory() {
//broadcast rolling upgrade active cache restoration advisory
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_ADVISORY);
}
/**
* send a rolling upgrade advisory message to instance to trigger
* it to do rolling upgrade replica cache restoration for the sending
* instance
*
* @param instanceName the instance to be sent the rolling upgrade advisory
*/
public void sendRollingUpgradeReplicaCacheRestorationAdvisory(String instanceName) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager",
"sendRollingUpgradeReplicaCacheRestorationAdvisory",
new Object[] {instanceName});
}
try {
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_ADVISORY, instanceName);
} catch (IOException ex) {}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager",
"sendRollingUpgradeReplicaCacheRestorationAdvisory");
}
}
/**
* broadcast a rolling upgrade active cache restoration advisory message to trigger
* rolling upgrade replica cache restoration for the sending
* instance
*/
protected void sendRollingUpgradeReplicaCacheRestorationAdvisory() {
//broadcast rolling upgrade active cache restoration advisory
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_ADVISORY);
}
/**
* send a rolling upgrade reconciliation complete advisory message to instance to signal
* to the original caller instance that replica reconciliation is complete
*
* @param instanceName the instance to be sent the rolling upgrade reconciliation complete advisory
*/
public void sendRollingUpgradeReplicaReconciliationCompleteAdvisory(String instanceName) {
if(_logger.isLoggable(Level.FINE)) {
_logger.entering("ReplicationDialogFragmentManager",
"sendRollingUpgradeReplicaReconciliationCompleteAdvisory",
new Object[] {instanceName});
}
try {
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_RECONCILIATION_COMPLETE_ADVISORY, instanceName);
} catch (IOException ex) {}
if(_logger.isLoggable(Level.FINE)) {
_logger.exiting("ReplicationDialogFragmentManager",
"sendRollingUpgradeReplicaReconciliationCompleteAdvisory");
}
}
/**
* broadcast a rolling upgrade getIds
* for replica cache reconciliation advisory message
*
*/
protected void sendRollingUpgradeGetIdsForReplicaCacheReconciliationAdvisory() {
//broadcast rolling upgrade getIds for replica cache reconciliation advisory
RollingUpgradeUtil.sendRollingUpgradeAdvisory((ReplicationManager)this, MODE_SIP, MESSAGE_BROADCAST_ROLLING_UPGRADE_GET_IDS_FOR_REPLICA_CACHE_RECONCILIATION_ADVISORY);
}
public void processRollingupgradeadvisory(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradeadvisory received from " + instanceName);
}
long waitTime = ((Long)replicationState.getProperty(ReplicationState.WAIT_TIME)).longValue();
//we have been triggered to do replica
//cache reconciliation for our replicateTo partner
doReplicaCacheReconciliation(waitTime, null);// TODO :: check last param, this whole method is unused -- remove it later.
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradeadvisory sending reconciliation completed advisory to: " + instanceName);
}
sendRollingUpgradeReplicaReconciliationCompleteAdvisory(instanceName);
}
public void processRollingupgradeactivecacherestorationadvisory(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradeactivecacherestorationadvisory received from " + instanceName);
}
List<ReplicationState> ownedReplicas = getDialogFragmentReplicas(instanceName);
sendReplicationStateList(ownedReplicas, instanceName, MESSAGE_BROADCAST_ROLLING_UPGRADE_ACTIVE_CACHE_RESTORATION_RESPONSE);
}
public void processRollingupgradeactivecacherestorationresponse(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradeactivecacherestorationresponse received from " + instanceName);
}
ownedReplicaListsReceivedForActiveCacheRestoration.putIfAbsent(replicationState.getInstanceName(), replicationState);
restoreActiveCacheDoneSignal.countDown();
}
public void processRollingupgradereplicacacherestorationadvisory(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradereplicacacherestorationadvisory received from " + instanceName);
}
List<ReplicationState> ownedReplicas = getActiveDialogFragmentsToReplicateTo(instanceName);
sendReplicationStateList(ownedReplicas, instanceName, MESSAGE_BROADCAST_ROLLING_UPGRADE_REPLICA_CACHE_RESTORATION_RESPONSE);
}
public void processRollingupgradereplicacacherestorationresponse(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
String instanceName = replicationState.getInstanceName();
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradereplicacacherestorationresponse received from " + instanceName);
}
ownedReplicaListsReceivedForReplicaCacheRestoration.putIfAbsent(replicationState.getInstanceName(), replicationState);
restoreReplicaCacheDoneSignal.countDown();
}
public void processRollingupgradereplicareconciliationcompleteadvisory(ReplicationState replicationState) {
if(replicationState == null) {
return;
}
if(_logger.isLoggable(Level.FINE)) {
_logger.fine("IN " + this.getClass().getName() + ">>processRollingupgradereplicareconciliationcompleteadvisory received from " + replicationState.getInstanceName());
}
reconcileReplicaCacheDoneSignal.countDown();
}
List<ReplicationState> getDialogFragmentReplicas(String owningInstanceName) {
List<ReplicationState> sessionIds = new ArrayList();
//using set to avoid dups
HashSet dialogFragmentIdsSet = new HashSet();
//iterate over dialogFragment replicas
Iterator it = getReplicatedDialogFragments().values();
while(it.hasNext()) {
ReplicationState nextState
= (ReplicationState)it.next();
RollingUpgradeUtil.filterOwnershipOfReplicas(owningInstanceName, nextState, dialogFragmentIdsSet);
}
sessionIds.addAll(dialogFragmentIdsSet);
return sessionIds;
}
List<ReplicationState> getActiveDialogFragmentsToReplicateTo(String owningInstanceName) {
DialogFragmentStoreImpl store = this.getSingletonDialogFragmentStore();
List<ReplicationState> dialogFragmentIds = new ArrayList();
//using set to avoid dups
HashSet dialogFragmentIdsSet = new HashSet();
//iterate over active dialogFragments
Iterator it = dialogFragments.values().iterator();
while(it.hasNext()) {
HADialogFragment nextDialogFragment = (HADialogFragment)it.next();
String beKey = nextDialogFragment.getBeKey();
if(RollingUpgradeUtil.shouldReplicateTo(beKey, owningInstanceName)) {
ReplicationState nextState = null;
try {
nextState = store.getTransmitState(nextDialogFragment);
} catch (IOException ex) {}
if(nextState != null) {
dialogFragmentIdsSet.add(nextState);
}
}
}
dialogFragmentIds.addAll(dialogFragmentIdsSet);
return dialogFragmentIds;
}
private void sendReplicationStateList(Collection<ReplicationState> ownedReplicas,
String instanceName, String command) {
byte[] ownedReplicasState = null;
try {
ownedReplicasState = ReplicationUtil.getByteArray((Serializable)ownedReplicas);
} catch (IOException ex) {}
//need a unique pseudo-id for this query
String appId = getApplicationId();
String id = appId + unique.getAndIncrement();
ReplicationState ownedReplicasListState = new ReplicationState(MODE_SIP,
id, appId, 0L, 0L, 0L, null, null, ReplicationUtil.getInstanceName(),
command, ownedReplicasState, null, null);
if (ownedReplicas == null || ownedReplicas.isEmpty()) {
ownedReplicasListState.setNack(true);
}
JxtaSocketChannel channel = JxtaSocketChannel.getInstance();
channel.send(ownedReplicasListState, instanceName);
}
private void sendReplicasList(List<FederatedQueryListElement> ownedReplicas,
String instanceName, String command) {
byte[] ownedReplicasState = null;
try {
ownedReplicasState = ReplicationUtil.getByteArray((Serializable)ownedReplicas);
} catch (IOException ex) {}
//need a unique pseudo-id for this query
String appId = getApplicationId();
String id = appId + unique.getAndIncrement();
ReplicationState ownedReplicasListState = new ReplicationState(MODE_SIP,
id, appId, 0L, 0L, 0L, null, null, ReplicationUtil.getInstanceName(),
command, ownedReplicasState, null, null);
if (ownedReplicas == null || ownedReplicas.isEmpty()) {
ownedReplicasListState.setNack(true);
}
JxtaSocketChannel channel = JxtaSocketChannel.getInstance();
channel.send(ownedReplicasListState, instanceName);
}
// end rolling upgrade related code
private class PrivilegedStoreLoadDialogFragment
implements PrivilegedExceptionAction {
private String id;
private String version;
private DialogFragmentStoreImpl store;
PrivilegedStoreLoadDialogFragment(String id, String version, DialogFragmentStoreImpl store) {
this.id = id;
this.version = version;
this.store = store;
}
public Object run() throws Exception{
return store.load(id, version);
}
}
}