Package org.jvnet.glassfish.comms.replication.dialogmgmt

Source Code of org.jvnet.glassfish.comms.replication.dialogmgmt.ReplicationDialogFragmentManager$PrivilegedStoreLoadDialogFragment

/*
* 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);
        }                      
    }
      
}
TOP

Related Classes of org.jvnet.glassfish.comms.replication.dialogmgmt.ReplicationDialogFragmentManager$PrivilegedStoreLoadDialogFragment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.