Package com.sun.enterprise.ee.web.sessmgmt

Source Code of com.sun.enterprise.ee.web.sessmgmt.JxtaBackingStoreImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. 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.
*/
/*
* JxtaBackingStoreImpl.java
*
* Created on October 6, 2006, 1:19 PM
*
*/

package com.sun.enterprise.ee.web.sessmgmt;

import java.io.*;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;
import com.sun.logging.LogDomains;

import org.apache.catalina.session.*;
import org.glassfish.enterprise.ha.store.criteria.Criteria;

import com.sun.appserv.ha.spi.BackingStore;
import com.sun.appserv.ha.spi.BackingStoreException;
import com.sun.appserv.ha.spi.StoreEntryEvaluator;
import com.sun.appserv.ha.util.Metadata;
import com.sun.appserv.ha.util.SimpleMetadata;
import com.sun.appserv.ha.util.CompositeMetadata;
import com.sun.appserv.ha.util.SimpleMetadataFactory;

/**
* This class now used in simple web, sso, ejb cases
* //sso and ejb not done yet
* @author Larry White
*/
public class JxtaBackingStoreImpl<V extends Metadata> extends BackingStore<String, V> {

    final static String CLASS_NAME = "JxtaBackingStoreImpl";
    final static String MODE_WEB = ReplicationState.MODE_WEB;
    final static String MODE_SSO = ReplicationState.MODE_SSO;
    final static String MODE_EJB = ReplicationState.MODE_EJB;
    final static String MODE_SIP = ReplicationState.MODE_SIP;
   
    final static String COMPOSITE_SAVE_COMMAND
        = ReplicationState.COMPOSITE_SAVE_COMMAND;
    final static String VALVE_SAVE_COMMAND
        = ReplicationState.VALVE_SAVE_COMMAND;   
    final static String REMOVE_COMMAND
        = ReplicationState.REMOVE_COMMAND;
    final static String REMOVE_EXPIRED_COMMAND
        = ReplicationState.REMOVE_EXPIRED_COMMAND;
    final static String UPDATE_LAST_ACCESS_TIME_COMMAND
        = ReplicationState.UPDATE_LAST_ACCESS_TIME_COMMAND;
    final static String SIZE_COMMAND
        = ReplicationState.SIZE_COMMAND;
    final static String REMOVE_IDS_COMMAND
        = ReplicationState.REMOVE_IDS_COMMAND;
    final static String MESSAGE_BROADCAST_QUERY
        = ReplicationState.MESSAGE_BROADCAST_QUERY;
    final static String MESSAGE_BROADCAST_LOAD_RECEIVED
        = ReplicationState.MESSAGE_BROADCAST_LOAD_RECEIVED;
   
    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 COMMAND_MAP = "commandmap";
   
    private CommandAccumulator removeCommandAccumator = null;
   
    /**
     * The logger to use for logging ALL web container related messages.
     */
    private static final Logger _logger
        = LogDomains.getLogger(LogDomains.WEB_LOGGER);   


    private static String DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS_PROPERTY_NAME = "com.sun.enterprise.ee.web.sessmgmt.FLUSH_INTERVAL_FOR_REMOVAL_MILLIS";

    private static int DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS = 15000;

    private static int DEFAULT_REMOVAL_SIZE_THRESHOLD = 20000;

    static {
        String sipTransClassName = "org.jvnet.glassfish.comms.replication.sessmgmt.SipTransactionPersistentManager";
        try {
            Class.forName(sipTransClassName);
        } catch (Throwable th) {
            DEFAULT_REMOVAL_SIZE_THRESHOLD = 1;
        }

        try {
            String flushStr = System.getProperty(DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS_PROPERTY_NAME, null);
            if (flushStr != null) {
                DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS = Integer.valueOf(flushStr);
            }
        } catch (Throwable th) {
            //Ignore
        }

        _logger.warning("Default Removal size threshold: " + DEFAULT_REMOVAL_SIZE_THRESHOLD);
        _logger.warning("Default Removal interval threshold: " + DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS);
    }
   
    /**
     * Creates a new instance of JxtaBackingStoreImpl
     */
    public JxtaBackingStoreImpl() {
        removeCommandAccumator =
                new CommandAccumulator("BulkRemove", new BulkRemove(),
                        DEFAULT_REMOVAL_SIZE_THRESHOLD,
                        DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS);
    }
   
    /**
     * Creates a new instance of JxtaBackingStoreImpl
     */
    public JxtaBackingStoreImpl(String appid, Properties env) {
        _mode = MODE_WEB;
        _appid = appid;
        //duplicate id semantics allowed - used by batch replication
        if(env != null) {
            _duplicateIdsSemanticsAllowed = ((Boolean)env.get(DUPLICATE_IDS_SEMANTICS_PROPERTY)).booleanValue();
            _commandMap = (Map)env.get(COMMAND_MAP);
            if(env.get(SUPPRESS_LOAD_ACK_PROPERTY) != null) {
                _suppressLoadAck = ((Boolean)env.get(SUPPRESS_LOAD_ACK_PROPERTY)).booleanValue();
            }
            if(env.get(REPLICATION_COMPRESSION_PROPERTY) != null) {
                _replicationCompressionEnabled = ((Boolean)env.get(REPLICATION_COMPRESSION_PROPERTY)).booleanValue();
            }
            setSessionManager((ReplicationManager)
                env.remove(ReplicationState.SESSION_MANAGER_PROPERTY));
            createExpatHandler();
            removeCommandAccumator =
                    new CommandAccumulator(appid + "BulkRemove", new BulkRemove(),
                            DEFAULT_REMOVAL_SIZE_THRESHOLD, DEFAULT_REMOVAL_FLUSH_INTERVAL_MILLIS);
        } else {
            _duplicateIdsSemanticsAllowed = true;
            _replicationCompressionEnabled = false;
        }
    }

    /**
     * get the command corresponding to the give inputCommand
     * if there is no passed in map - return the inputCommand
     * else return the command mapped to this command
     * also return the input command if a map exists but
     * there is no mapped command
     * @param inputCommand the input command
     * @return the command
     */   
    public String getCommand(String inputCommand) {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("getCommand:inputCommand=" + inputCommand + " _commandMap=" + _commandMap);
        }
        String returnCommand = null;
        if(_commandMap == null) {
            return inputCommand;
        } else {
            if((returnCommand = (String)_commandMap.get(inputCommand)) != null) {
                return returnCommand;
            } else {
                return inputCommand;
            }           
        }
    }
   
    /**
     * Load and return the value for the given id
     * @param id the id whose value must be returned
     * @param version the version requested
     * @return the value if this store contains it or null
     */
    public V load(String id, String version) throws BackingStoreException {
        if(sessionManager != null) {
            return (V)sessionManager.__load(id, version, this);
        } else {
            return null;
        }
    }

    public ReplicationState __load(String id, String version) throws BackingStoreException {
        final String METHOD_NAME = "load(id,version)";
        boolean loadCalledDuringReshape = ! ReplicationHealthChecker.isOkToProceed();
       
        if (_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, METHOD_NAME,
                             new Object[] {id, version});
        }
        long versionLong = ReplicationUtil.parseLong(version);
        ReplicationState result = this.findSessionViaBroadcast(id, versionLong);
        if (loadCalledDuringReshape && _logger.isLoggable(Level.FINE)) {
            _logger.fine("load(" + id + ", " + version +
                         ") called during reshape returned " + result);
        }
        if (_logger.isLoggable(Level.FINER)) {
            _logger.exiting(CLASS_NAME, METHOD_NAME, result);
        }
        return result;
    }   

    private void updateContainerExtraParam(String id, long time, long version, Object e)
        throws BackingStoreException {
        //FIXME
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return;
        }
        if(_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, "updateContainerExtraParam",
                             new Object[]{id, time, version, e});            
        }
        byte[] containerExtraParamState = null;
        try {
            containerExtraParamState = this.getByteArray(e, isReplicationCompressionEnabled());
        } catch (IOException ex) {
            throw new BackingStoreException("error during serialization of extra parameters", ex);
        }
        ReplicationState transmitState =
            new ReplicationState(_mode,  //mode
                id, //id
                getApplicationId(), //appid
                version,     //version
                time,     //lastaccesstime
                0L,     //maxInactiveInterval
                null,  //extraParam
                null,   //queryResult
                null,  //FIXME instance name
                this.getCommand(UPDATE_LAST_ACCESS_TIME_COMMAND), //command
                null,  //state - not needed
                null,  //trunkState - not needed
                containerExtraParamState); //containerExtraParamState
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
    }


    public Collection findByCriteria(Criteria<V> criteria,
                                     StoreEntryEvaluator<String, V> e) {
        if (e instanceof OldExtraParamEvaluator) {
            return ((OldExtraParamEvaluator) e)._getExtraParamCollectionFromManager();
        }
        _logger.log(Level.WARNING, "JxtaBackingStoreImpl.findByDriteria("
                + e.getClass().getName() + ") called. Returning empty collection");
        return (Collection) Collections.EMPTY_LIST;
    }

    private Object getContainerExtraParamFrom(ReplicationState queryResult)
              throws BackingStoreException {
          /* this logic may apply for EJB do not remove yet
          if(this.getMode() == MODE_SSO) {
              return queryResult.getExtraParam();
          }
           */
          //deserialize containerExtraParams if present
          //note: we assume extra param state is deserializable
          //using the system class loader
          Object containerExtraParams = null;
          byte[] containerExtraParamState = queryResult.getContainerExtraParamsState();
          if(containerExtraParamState != null) {
              try {
                  containerExtraParams
                      = ReplicationState.getObjectValue(containerExtraParamState, isReplicationCompressionEnabled());
              } catch (Exception ex) {
                  throw new BackingStoreException("error during deserialization of extra parameters", ex);
              }
          }
          return containerExtraParams;
      }

    /**
     * Save the value whose Key is id
     * @param id the id
     * @param value The Metadata
     */
    public void save(String id, Metadata value, boolean isNew)
            throws BackingStoreException {
        //health check done in saveSimple and saveComposite
        value.setOwningInstanceName(ReplicationUtil.getInstanceName());
        if (value instanceof SimpleMetadata) {
            SimpleMetadata smd = (SimpleMetadata) value;
            if (smd.getSaveMode() == SimpleMetadata.SAVE_ALL) {
                saveSimple(id, smd);
            } else if (smd.getSaveMode() == SimpleMetadata.SAVE_TIME_STAMP) {
                updateLastAccessTime(id, smd.getLastAccessTime(), smd.getVersion());
            } else if (smd.getSaveMode() == SimpleMetadata. SAVE_EP) {
                updateContainerExtraParam(id, smd.getLastAccessTime(), smd.getVersion(), smd.getExtraParam());
            }
        } else {
            if (value instanceof CompositeMetadata) {
                saveComposite(id, (CompositeMetadata) value);
            }
        }
    }
   
    /**
     * Save the value whose Key is id
     * @param id the id
     * @param value The Metadata
     */
    private void saveSimple(String id, SimpleMetadata value)
        throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("JxtaBackingStore>>saveSimple():id = " + id + " unable to proceed due to health check");
            }            
            return;
        }
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStore>>saveSimple():id = " + id);
        }       
        // FIXME
        /*
        String theUserName = null;
        String theSsoId = null;
        if(MODE_WEB.equals(getMode())) {
            theSsoId = value.getExtraParam();
        } else {
            if(MODE_SSO.equals(getMode())) {
                theUserName = value.getExtraParam();
            }
        }
         */
        Object extraParam = value.getExtraParam();
        String extraParamString
            = ReplicationState.extractExtraParamStringFrom(_mode, extraParam);
       
        ReplicationState transmitState = this.createHttpReplicationState(
            id,
            value.getVersion(),
            value.getLastAccessTime(),
            value.getMaxInactiveInterval(),
            //(String)value.getExtraParam(), //if WEB-ssoid -- if SSO-username
            extraParamString,   //if WEB-ssoid -- if SSO-username
            null,    //FIXME this should be instance name
            value.getState(),
            null,           //trunkState - not used here
            value.getExtraParam()//extraParam
            createMapWith(value.getBeKey()),
            this.getCommand(VALVE_SAVE_COMMAND));
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
        // uncomment to gather timing info
        //_logger.info("saveSimple Time:" + (System.currentTimeMillis() - startTime) + " msecs");
    }

    //TODO: BE_KEY and ORIGINATING_INSTANCE_NAME could be first class members inside ReplicationState?
    private static Map createMapWith(String beKey) {
        Map map = new HashMap();
        map.put(ReplicationState.BEKEY, beKey);
        map.put(ReplicationState.ORIGINATING_INSTANCE_NAME, ReplicationUtil.getInstanceName());

        return map;
    }

    /**
     * return the transmitState
     * @param id the id
     * @param value The Metadata
     * @returns the ReplicationState representing value
     */
    public ReplicationState getSimpleTransmitState(String id, SimpleMetadata value)
        throws BackingStoreException {
        Object extraParam = value.getExtraParam();
        String extraParamString
            = ReplicationState.extractExtraParamStringFrom(_mode, extraParam);

        ReplicationState transmitState = this.createHttpReplicationState(
            id,
            value.getVersion(),
            value.getLastAccessTime(),
            value.getMaxInactiveInterval(),
            //(String)value.getExtraParam(), //if WEB-ssoid -- if SSO-username
            extraParamString,   //if WEB-ssoid -- if SSO-username
            null,    //FIXME this should be instance name
            value.getState(),
            null,           //trunkState - not used here
            value.getExtraParam()//extraParam
            createMapWith(value.getBeKey()),
            this.getCommand(VALVE_SAVE_COMMAND));       
        return transmitState;
    }
   
    /**
     * Save the value whose Key is id
     * @param id the id
     * @param value The Metadata
     */
    private void saveComposite(String id, CompositeMetadata<String> value)
        throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("JxtaBackingStore>>saveComposite():id = " + id + "unable to proceed due to health check");
            }            
            return;
        }       
        /*
        String theUserName = null;
        String theSsoId = null;
        if(MODE_WEB.equals(getMode())) {
            theSsoId = value.getExtraParam();
        } else {
            if(MODE_SSO.equals(getMode())) {
                theUserName = value.getExtraParam();
            }
        }
         */
        byte[] compositeState = null;
        try {
            compositeState = this.getByteArrayFromCollection(value.getEntries());
        } catch (IOException ex) {}
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>saveComposite:trunkState=" + value.getState());
            _logger.fine("JxtaBackingStoreImpl>>saveComposite:attrState=" + compositeState);            
        }     
        ReplicationState transmitState = this.createHttpReplicationState(
            id,
            value.getVersion(),
            value.getLastAccessTime(),
            value.getMaxInactiveInterval(),
            value.getExtraParam(), //if WEB-ssoid -- if SSO-username
            null,    //FIXME this should be instance name
            compositeState,     // in simple case it is value.getState(),
            value.getState(),   // trunkState for composite case
            null,               //containerExtraParam not used here
            createMapWith(value.getBeKey()), //properties
            this.getCommand(COMPOSITE_SAVE_COMMAND));
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());       
    }

    /**
     * Save the value whose Key is id
     * @param id the id
     * @param value The Metadata
     * @returns the ReplicationState representing value
     */
    public ReplicationState getCompositeTransmitState(String id, CompositeMetadata<String> value)
        throws BackingStoreException {
        byte[] compositeState = null;
        try {
            compositeState = this.getByteArrayFromCollection(value.getEntries());
        } catch (IOException ex) {}
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>saveComposite:trunkState=" + value.getState());
            _logger.fine("JxtaBackingStoreImpl>>saveComposite:attrState=" + compositeState);
        }
        ReplicationState transmitState = this.createHttpReplicationState(
            id,
            value.getVersion(),
            value.getLastAccessTime(),
            value.getMaxInactiveInterval(),
            value.getExtraParam(), //if WEB-ssoid -- if SSO-username
            null,    //FIXME this should be instance name
            compositeState,     // in simple case it is value.getState(),
            value.getState(),   // trunkState for composite case
            null,               //containerExtraParam not used here
            createMapWith(value.getBeKey()), //properties
            this.getCommand(COMPOSITE_SAVE_COMMAND));
        return transmitState;
    }
   
    /**
     * Update the last access time for this id.
     * @param id the id for the Metadata
     * @param time the last access time
     */
    public void updateLastAccessTime(String id, long time, long version)
        throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return;
        }
        if(_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, "updateLastAccessTime",
                    new Object[] { id, time, version});          
        }        
        ReplicationState transmitState =
            new ReplicationState(_mode,  //mode
                id, //id
                getApplicationId(), //appid
                version,     //version
                time,     //lastaccesstime
                0L,     //maxInactiveInterval
                null,  //extraParam
                null,   //queryResult
                null,  //FIXME instance name
                this.getCommand(UPDATE_LAST_ACCESS_TIME_COMMAND), //command
                null,  //state - not needed
                null,  //trunkState - not needed
                null)//containerExtraParam state
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
    }
   
    /**
     * Remove the Metadata for the id. After this call, any call to load(id)
     *    must return null
     * @param id the id
     */
    public void remove(String id) throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return;
        }
        if(_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, "remove", id);            
        }

        if(removeCommandAccumator != null) {
            removeCommandAccumator.add(id);
        } else {
        ReplicationState transmitState =
            new ReplicationState(_mode,  //mode
                id, //id
                getApplicationId(), //appid
                0L,     //version
                0L,     //lastaccesstime
                0L,     //maxInactiveInterval
                null,  //extraParam
                null,   //queryResult
                this.getInstanceName()//instanceName
                this.getCommand(REMOVE_COMMAND), //command
                null,  //state - not needed
                null,  //trunkState - not needed
                null); //containerExtraParamState
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
        }

    }
   
    public void sendBulkRemove(List<String> ids) {
        if (!ReplicationHealthChecker.isOkToProceed()) {
            return;
        }
        String id = getApplicationId() + System.currentTimeMillis();
        if (_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, "remove", id);
        }
        byte[] idList = null;
        try {
            idList = ReplicationState.getByteArray(ids);
            ReplicationState transmitState =
                    new ReplicationState(_mode,  //mode
                            id, //id
                            getApplicationId(), //appid
                            0L,     //version
                            0L,     //lastaccesstime
                            0L,     //maxInactiveInterval
                            null,  //extraParam
                            null,   //queryResult
                            this.getInstanceName()//instanceName
                            this.getCommand(REMOVE_COMMAND), //command
                            idList,
                            null,  //trunkState - not needed
                            null); //containerExtraParamState
            //use configurable wait for synchronous replication here
            this.doTransmit(transmitState, isSynchronousReplicationConfigured());
        } catch (Exception ex) {
            _logger.log(Level.WARNING, ex.getMessage(), ex);
        }
    }

    /**
     * Remove the Metadata for the id. After this call, any call to load(id)
     *    must return null
     * @param id the id
     */
    public void remove(String id, String originatingInstanceName, int cycleCount) throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return;
        }
        if(_logger.isLoggable(Level.FINER)) {
            _logger.entering(CLASS_NAME, "remove", id);            
        }
        String cycleCountString = String.valueOf(cycleCount);
        ReplicationState transmitState =
            new ReplicationState(_mode,  //mode
                id, //id
                getApplicationId(), //appid
                0L,     //version
                0L,     //lastaccesstime
                0L,     //maxInactiveInterval
                cycleCountString,  //extraParam is cycleCount
                null,   //queryResult
                originatingInstanceName, // instanceName
                this.getCommand(REMOVE_COMMAND), //command
                null,  //state - not needed
                null,  //trunkState - not needed
                null); //containerExtraParamState
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
    }   
   
    /**
     * Remove all instances that are idle.
     */
    public int removeExpired() throws BackingStoreException {
//        if( !ReplicationHealthChecker.isOkToProceed() ) {
//            return 0;
//        }
//        // FIXME for getting return
//        if(_logger.isLoggable(Level.FINE)) {
//            _logger.fine("JxtaBackingStore>>removeExpired");
//        }
//        ReplicationState transmitState =
//            new ReplicationState(_mode,  //mode
//                getApplicationId(), //id there is not a real id so use appid
//                getApplicationId(), //appid
//                0L,     //version
//                0L,     //lastaccesstime
//                0L,     //maxInactiveInterval
//                null,  //extraParam
//                null,   //queryResult
//                null,  //FIXME instanceName
//                this.getCommand(REMOVE_EXPIRED_COMMAND), //command
//                null,  //state - not needed
//                null,  //trunkState - not needed
//                null);  //containerExtraParamState - not needed
//        //use configurable wait for synchronous replication here
//        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
//
//        return 0; //FIXME

        ReplicationManager rm = getReplicationSessionManager();
        return (rm != null) ? rm.processExpiredSessions() : 0;

    }

    public ReplicationManager getReplicationSessionManager() {
        return sessionManager;
    }

    /**
     * Get the current size of the store
     * @retrun the number of entries in the storee
     */
    public int size() throws BackingStoreException {
        int result = -1;
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return result;
        }       
        ReplicationState transmitState
            = ReplicationState.createQueryState(_mode, getApplicationId(), getApplicationId(), SIZE_COMMAND);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>size:transmittedState=" + transmitState);
        }       
        JxtaReplicationSender sender
            = JxtaReplicationSender.createInstance();
        ReplicationState resultState = sender.sendReplicationState(transmitState);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>size:resultState=" + resultState);
        }       
        if(resultState != null) {
            try {
                result = ((Integer)resultState.getQueryResult()).intValue();
            } catch(Exception ex) {}
        }
        return result;
    }
   
    /**
     * Called when the store is no longer needed. Must clean up or close
     *    any opened resource.
     */
    public void destroy() throws BackingStoreException {
        // deliberate no-op
        if(removeCommandAccumator != null) {
            removeCommandAccumator.stop();
        }
    }
   
    /**
     * Remove all instances that are idle.
     * @param removedIdsData  serialized list of ids to remove
     */
    public void removeIds(long msgID, byte[] removedIdsData) throws BackingStoreException {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return;
        }       
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStore>>removeIds");
        }       
        String messageId = Long.toString(msgID);
        ReplicationState transmitState =
            new ReplicationState(_mode,  //mode
                messageId, //id use passed in msgID
                getApplicationId(), //appid
                0L,     //version
                0L,     //lastaccesstime
                0L,     //maxInactiveInterval
                null,  //extraParam
                null,   //queryResult
                null,  //FIXME instanceName
                this.getCommand(REMOVE_IDS_COMMAND), //command
                removedIdsData,  //state - serialized list of ids to remove
                null,  //trunkState - not needed
                null)//containerExtraParamState - not needed
        //use configurable wait for synchronous replication here
        this.doTransmit(transmitState, isSynchronousReplicationConfigured());
        return;
    }   
   
    //Helper methods
   
    protected ReplicationState createHttpReplicationState(String id,
        long version, long lastAccessTime, long maxInactiveInterval,
        String extraParam, String instanceName,
        byte[] sessionState, byte[] sessionTrunkState,
        Object containerExtraParam, Map properties, String command) throws BackingStoreException {
        byte[] containerExtraParamState = null;
        if(containerExtraParam != null) {
            try {
                containerExtraParamState = getByteArray(containerExtraParam, isReplicationCompressionEnabled());
            } catch (IOException ex) {
                throw new BackingStoreException("error during serialization of extra parameters", ex);
            }
        }
        ReplicationState transmitState =
            new ReplicationState(_mode, //web mode in this case
                id,                 //id
                _appid,       //appid
                version,            //version
                lastAccessTime,     //lastaccesstime
                maxInactiveInterval, //maxInactiveInterval (seconds)
                extraParam,           //extraParam
                null,                   //queryResult
                instanceName,         //instanceName
                command,            //command
                sessionState,      //state
                sessionTrunkState, //sessionTrunkState (for composite case)
                containerExtraParamState)//containerExtraParamState may be needed
        transmitState.setProperties(properties);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>createHttpReplicationState:transmitState = " + transmitState);
        }       
        return transmitState;
    }
   
    public SimpleMetadata getSimpleMetadataFromQueryResult(ReplicationState queryResult)
        throws BackingStoreException {
        Object containerExtraParams = ReplicationState.getContainerExtraParamFrom(
                queryResult, isReplicationCompressionEnabled());
        SimpleMetadata result = SimpleMetadataFactory.createSimpleMetadata(queryResult.getVersion(),
                queryResult.getLastAccess(), queryResult.getMaxInactiveInterval(),
                queryResult.getState(),
                containerExtraParams);       
        return result;
    }
   
    /**
    * Create an byte[] for the object that we can then pass to
    * the ReplicationState.
    *
    * @param obj
    *   The attribute value we are serializing
    *
    */
    protected byte[] getByteArray(Object obj)
      throws IOException {
        return getByteArray(obj, false);
    }   
   
    /**
    * Create an byte[] for the object that we can then pass to
    * the ReplicationState.
    *
    * @param obj
    *   The attribute value we are serializing
    *
    */
    protected byte[] getByteArray(Object obj, boolean compress)
      throws IOException {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        byte[] obs;
        try {
            bos = new ByteArrayOutputStream();
            //use normal ObjectOutputStream if there is a failure during stream creation
            if (compress) {
                oos = new ObjectOutputStream(new GZIPOutputStream(new BufferedOutputStream(bos)));
            } else {
                oos = new ObjectOutputStream(new BufferedOutputStream(bos));
            }           
            oos.writeObject(obj);
            oos.close();
            oos = null;

            obs = bos.toByteArray();
        }
        finally {
            if ( oos != null )  {
                oos.close();
            }
        }

        return obs;
    }
   
    /**
    * Create an byte[] for the session that we can then pass to
    * the HA Store.
    *
    * @param entries
    *   The attribute value we are serializing
    *
    */
    protected byte[] getByteArrayFromCollection(Collection entries)
      throws IOException {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;

        IOUtilsCaller utilsCaller = null;
        byte[] obs;
        try {
            bos = new ByteArrayOutputStream();
            //HERCULES FIXME - for now reverting back
            //need to re-examine EJBUtils and related serialization classes
            //Bug 4832603 : EJB Reference Failover
            /*  was this
            oos = new ObjectOutputStream(new BufferedOutputStream(bos));
             end was this */
              //oos = EJBUtils.getOutputStream(new BufferedOutputStream(bos), true); 
            //end - Bug 4832603
           
            if( (utilsCaller = this.getWebUtilsCaller()) != null) {
                try {
                    oos = utilsCaller.createObjectOutputStream(new BufferedOutputStream(bos), true);
                } catch (Exception ex) {}
            }
            //use normal ObjectOutputStream if there is a failure during stream creation
            if(oos == null) {
                oos = new ObjectOutputStream(new BufferedOutputStream(bos));
            }
            //first write out the entriesSize
            int entriesSize = entries.size();
            oos.writeObject(Integer.valueOf(entriesSize));
            //then write out the entries
            Iterator it = entries.iterator();
            while(it.hasNext()) {
                oos.writeObject(it.next());
            }
            oos.close();
            oos = null;

            obs = bos.toByteArray();
        }
        finally {
            if ( oos != null )  {
                oos.close();
            }
        }

        return obs;
    }
   
    /**
     * get the utility class used to call into services from IOUtils
     */
    protected IOUtilsCaller getWebUtilsCaller() {
        if(webUtilsCaller == null) {
            WebIOUtilsFactory factory = new WebIOUtilsFactory();
            webUtilsCaller = factory.createWebIOUtil();           
        }
        return webUtilsCaller;
    }   
   
    protected ReplicationState doTransmit(ReplicationState transmitState) {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return null;
        }        
        return this.doTransmit(transmitState, true);
    }   

    protected ReplicationState doTransmit(ReplicationState transmitState, boolean wait) {
        if( !ReplicationHealthChecker.isOkToProceed() ) {
            return null;
        }        
        JxtaReplicationSender replicationSender =
                JxtaReplicationSender.createInstance();
        ReplicationState resultState = null;
        if(!isSynchronousReplicationConfigured()) {
            //this call relies on env property to allow dupIds during
            //replication or not
            resultState =
                replicationSender.sendReplicationState(transmitState,
                    wait, isDuplicateIdsSemanticsAllowed());
        } else {
            //for now using non-batch for synchronous
            resultState =
                replicationSender.sendReplicationStateNonBatch(transmitState, true);           
        }
        return resultState;
    }
   

    private ReplicationState findSessionViaBroadcast(String id, long version) throws BackingStoreException {
        //do multi-cast to cluster member and get back state
        String findCommand = this.getCommand(MESSAGE_BROADCAST_QUERY);
         if(_logger.isLoggable(Level.FINE)) {      
            _logger.fine("findCommand=" + findCommand + " id=" + id + " version=" + version);
        }
        ReplicationState state =
            ReplicationState.createBroadcastQueryState(this.getMode(), id, this.getApplicationId(), version, this.getInstanceName(), findCommand);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("JxtaBackingStoreImpl>>findSessionViaBroadcast:queryInputState=" + state);                           
        }        
        JxtaReplicationSender sender
            = JxtaReplicationSender.createInstance();
        ReplicationState queryResult = sender.sendReplicationStateQuery(state);
        if(_logger.isLoggable(Level.FINE)) {      
            _logger.fine("JxtaBackingStoreImpl>>findSessionViaBroadcast:queryResult=" + queryResult);                       
        }              
        Metadata result = null;
        String userOrSsoId = null;        
        if(queryResult != null) {
            if(!_suppressLoadAck) {
                //send acknowledgement of load receipt
                //no response to wait for in this case
                /*
                ReplicationState loadReceivedState =
                    ReplicationState.createBroadcastLoadReceivedState(this.getMode(), id, this.getApplicationId(), version, this.getInstanceName());
                 */
                String loadReceivedCommand = this.getCommand(MESSAGE_BROADCAST_LOAD_RECEIVED);
                ReplicationState loadReceivedState =
                    ReplicationState.createBroadcastLoadReceivedState(this.getMode(), id, this.getApplicationId(), version, this.getInstanceName(), loadReceivedCommand);               
                sender.sendBroadcastQuery(loadReceivedState);
            }
           
/*
            if(!this.isCompositeBackingStore()) {
                result = this.getSimpleMetadataFromQueryResult(queryResult);
            } else {
                result = ReplicationState.createCompositeMetadataFrom(queryResult);
            }
*/
        }
        return queryResult;
    }   

    /**
     * return the name of this instance
     * @returns instanceName
     */   
    public String getInstanceName() {
        return ReplicationUtil.getInstanceName();
    }

    /**
     * return the property associated with aType
     * @returns aType
     */    
    public String getProperty(String aType) {
        //return property if it exists or null
        Properties env = this.getProperties();
        return (String)env.getProperty(aType);
    }
   
    String getMode() {
        return _mode;
    }
   
    public void setMode(String mode) {
        _mode = mode;
    }   
   
    String getApplicationId() {
        return _appid;
    }  
   
    public boolean isCompositeBackingStore() {
        return _isCompositeBackingStore;
    }
   
    public void setCompositeBackingStore(boolean value) {
        _isCompositeBackingStore = value;
    }   
   
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("_mode = " + _mode + "\n");
        sb.append("_appid = " + _appid + "\n");
        sb.append("_idleTimeoutInSeconds = " + _idleTimeoutInSeconds);
        return sb.toString();
    }
   
    public boolean isDuplicateIdsSemanticsAllowed() {
        return _duplicateIdsSemanticsAllowed;
    }   
   
    public void setDuplicateIdsSemanticsAllowed(boolean value) {
        _duplicateIdsSemanticsAllowed = value;
    }
   
    private boolean isSynchronousReplicationConfigured() {
        return ReplicationUtil.isSynchronousReplicationConfigured();
    }
   
    private boolean isReplicationCompressionEnabled() {
        return _replicationCompressionEnabled;
    }   
   
    /**
     * A utility class used to call into services from IOUtils
     */
    private IOUtilsCaller webUtilsCaller = null;    

    protected boolean _duplicateIdsSemanticsAllowed = false;
    protected boolean _replicationCompressionEnabled = false;
    protected boolean _suppressLoadAck = false;
    protected Map _commandMap = null;
    protected Boolean _waitForAckConfigured = null;
    protected Boolean _synchronousConfigured = null;
    private String _mode = null;
    private String _appid = null;
    private int _idleTimeoutInSeconds = 0;
    private boolean _isCompositeBackingStore = false;
    private ReplicationManager sessionManager = null;

    private void setSessionManager(ReplicationManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    private void createExpatHandler() {
        if(sessionManager != null) {
            if(sessionManager instanceof DynamicOwnershipManager) {
                ((DynamicOwnershipManager)sessionManager).__createStoreExpatHandler(this);
            }
        }
    }
   
    @Override
    public Collection synchronizeKeys(Criteria<V> vCriteria,
                                             StoreEntryEvaluator<String, V> eval,
                                             boolean eagerFetch) {
        if(sessionManager != null) {
            if(sessionManager instanceof DynamicOwnershipManager) {
                ((DynamicOwnershipManager)sessionManager).__synchronizeKeys(this);
            }
        }
        return super.synchronizeKeys(vCriteria, eval, eagerFetch);
    }

    class BulkRemove implements CommandAccumulatorHandler {
        public void handle(List list) {
            sendBulkRemove(list);
        }
    }
}
TOP

Related Classes of com.sun.enterprise.ee.web.sessmgmt.JxtaBackingStoreImpl

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.