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

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

/*
* 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.
*/
/*
* PipeWrapper.java
* generic class that wraps a pipe
*
* Created on March 6, 2006, 4:45 PM
*
*/

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

import java.io.IOException;
import java.security.AccessController;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.logging.LogDomains;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.MessageElement;
import net.jxta.endpoint.OutgoingMessageEvent;
import net.jxta.endpoint.OutgoingMessageEventListener;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.util.JxtaBiDiPipe;
import net.jxta.util.PipeEventListener;

import com.sun.enterprise.web.ServerConfigLookup;
import org.apache.catalina.Globals;

/**
*
* @author lwhite
*/
public class PipeWrapper extends AbstractPipeWrapper implements PipeMsgListener, PipeEventListener, OutgoingMessageEventListener, PipePoolElement {
   
    private final static String SenderMessage = "pipe_tutorial";
    private final static String MESSAGE_MODE =
        ReplicationState.MESSAGE_MODE;
    private final static String BULK_MESSAGE_MODE =
        ReplicationState.BULK_MESSAGE_MODE;   
    private final static String MESSAGE_ID =
        ReplicationState.MESSAGE_ID;
   
    final static String MESSAGE_ACK_REQUIRED =
        ReplicationState.MESSAGE_ACK_REQUIRED;
    final static String MESSAGE_ACK_LIST_PROPERTY =
        ReplicationState.MESSAGE_ACK_LIST_PROPERTY;
    public final static String MESSAGE_SEND_START_TIME =
        ReplicationState.MESSAGE_SEND_START_TIME;
    public final static String BULK_MESSAGE_ID =
        ReplicationState.BULK_MESSAGE_ID;
    private final static String ID = ReplicationState.ID;
    private final static int PIPE_QUEUE_CAPACITY = 20;
    private final static Level TRACE_LEVEL = Level.FINE;
   
    /**
     * The logger to use for logging ALL web container related messages.
     */
    private final static Logger _logger
        = LogDomains.getLogger(LogDomains.WEB_LOGGER);
    private static final Logger _pipelogger = ReplicationUtil.getPipeLogger();
   
    /** Creates a new instance of PipeWrapper */
    public PipeWrapper(String name, String senderOrReceiver,
            String partnerInstanceName, JxtaBiDiPipe pipe) {
        _name = name;
        _senderOrReceiver = senderOrReceiver;
        _partnerInstanceName = partnerInstanceName;
        _pipe = pipe;
        //pipe.setMessageListener(this);
    }
   
    /**
     *  This is the PipeListener interface. Expect a call to this method
     *  When a message is received.
     *  when we get a message, print out the message on the console
     *
     *@param  event  message event
     */
    public void pipeMsgEvent(PipeMsgEvent event) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("PipeWrapper>>pipeMsgEvent");
        }       
        Message msg = null;
        try {
            // grab the message from the event
            msg = event.getMessage();
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("PipeWrapper>>pipeMsgEvent:msg=" + msg);
            }            
            if (msg == null) {
                if(_logger.isLoggable(Level.FINE)) {
                    _logger.fine("Received an empty message, returning");
                }               
                return;
            }

            // get the message element named SenderMessage
            MessageElement msgElement = msg.getMessageElement(SenderMessage, SenderMessage);
            MessageElement idMsgElement = msg.getMessageElement(MESSAGE_ID, MESSAGE_ID);
            MessageElement bulkMsgElement = msg.getMessageElement(BULK_MESSAGE_MODE, BULK_MESSAGE_MODE);
//            if (_logger.isLoggable(Level.FINE)) {
//                _logger.fine("msgElement=" + msgElement +
//                             " idMsgElement=" + idMsgElement +
//                             " bulkMsgElement=" + bulkMsgElement);
//            }            

            // Get message
           
            if (msgElement != null) {
                this.processStartupMessage(msg, msgElement);
            } else if (bulkMsgElement != null) {
                processBulkMessage(msg, bulkMsgElement);
            } else {
                if (idMsgElement != null) {
                    this.processIdMessage(msg, idMsgElement);
                } else {
                    //this shouldn't happen
                }
            }           
        } catch (Exception e) {
            // FIXME evaluate log level
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE,
                            "Exception occurred processing pipeMsgEvent msg=" + msg,
                            e);
            }
            return;
        }
    }   
   
    private void processStartupMessage(Message msg, MessageElement msgElement) {
        // Get message
        if (msgElement.toString() == null) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("null msg received");
            }
        } else {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("Message  :"+ msgElement.toString());
            }
            //put comment start back here
            //send back response if it isn't already a response
            if( !(msgElement.toString()).startsWith("RETURN_MSG_COMMAND")) {
                Message returnMsg = new Message();
                String returnData = "ReturnMessage  :"+ msgElement.toString();
                returnMsg.addMessageElement(SenderMessage,
                                      new StringMessageElement(SenderMessage,
                                                               returnData,
                                                               null));
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("SendingResponse :" + returnData);
                }

                //pipe.sendMessage(returnMsg);
                /* don't send return message during startup -
                 *pools not initialized yet
                JxtaReplicationSender jxtaReplicationSender =
                    JxtaReplicationSender.createInstance();
                jxtaReplicationSender.sendOverPipe(returnMsg);
                 */
               
            }

            //end send back response
             //put comment end back here
            //count ++;
        }
    }

    private void checkSendImmediateAck(Message msg) {
        //do not proceed unless waitForFastAck not configured or health
        //check message which must always be acked
        if(isWaitForFastAckConfigured() && !ReplicationState.isHCMessage(msg)) {
            return;
        }
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("<<checkSendImmediateAck:isVoidReturnMessage=" + ReplicationState.isVoidMethodReturnMessage(msg));
            _logger.fine("<<checkSendImmediateAck:isAckRequiredForMessage=" + ReplicationState.isAckRequiredForMessage(msg));
        }
        if(ReplicationState.isHCMessage(msg)) {
            String acceptSidePipeName
                = ReplicationState.getExtraParamFromMessage(msg);
            if (_pipelogger.isLoggable(Level.FINE)) {
                _pipelogger.fine("PipeWrapper - HC Message recd - name: " + this.getName() + " acceptSidePipeName: " + acceptSidePipeName);
            }
            setReceivedHCMessage(true);
            /*
            synchronized(this) {
                this.notify();
            }
             */           
        }       
        if (ReplicationState.isVoidMethodReturnMessage(msg)
            && ReplicationState.isAckRequiredForMessage(msg)) {
            //send immediate ack
            Message ackMsg = ReplicationState.createAckMessageFrom(msg);
            JxtaBiDiPipe thePipe = this.getPipe();
//            long tempStart = 0L;
//            if (_logger.isLoggable(Level.FINE)) {
//                tempStart = System.currentTimeMillis();
//            }
            //FIXME - we are trying this w/o synchronization
            //synchronized(thePipe) {
                try {
                    thePipe.sendMessage(ackMsg);
                } catch (IOException ex) {
                    // FIXME evaluate logging level
                    if(_pipelogger.isLoggable(Level.FINE)) {
                        _pipelogger.log(Level.FINE, "Exception sending immediate ack message", ex);
                    }
                }
            //}
//            if (_logger.isLoggable(LevelFINE)) {
//                long duration = System.currentTimeMillis() - tempStart;
//                if(duration > 30) {
//                    _logger.fine("sending ack took " + duration + " msecs");
//                }
//            }
        }
    }
       
    private void checkSendImmediateBulkAck(Message msg, List<ReplicationState> states) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("<<checkSendImmediateBulkAck:isVoidReturnMessage=" + ReplicationState.isVoidMethodReturnMessage(msg));
            _logger.fine("<<checkSendImmediateBulkAck:isAckRequiredForMessage=" + ReplicationState.isAckRequiredForMessage(msg));
        }       
       if (ReplicationState.isVoidMethodReturnMessage(msg)
            && ReplicationState.isAckRequiredForMessage(msg)) {
            //FIXME send immediate ack
            Message ackMsg = ReplicationState.createBulkAckMessageFrom(msg, states);
            JxtaBiDiPipe thePipe = this.getPipe();
//            long tempStart = 0L;
//            if (_logger.isLoggable(Level.FINE)) {
//                tempStart = System.currentTimeMillis();
//            }
            //FIXME - we are trying this w/o synchronization
            //synchronized(thePipe) {
                try {
                    thePipe.sendMessage(ackMsg);
                } catch (IOException ex) {
                    // FIXME evaluate logging level
                    if(_pipelogger.isLoggable(Level.FINE)) {
                        _pipelogger.log(Level.FINE, "PipeWrapper:IOException sending ack message", ex);
                    }
                }
            //}
//            if (_logger.isLoggable(LevelFINE)) {
//                long duration = System.currentTimeMillis() - tempStart;
//                if(duration > 30) {
//                    _logger.fine("sending ack took " + duration + " msecs");
//                }
//            }
        }
    }           
   
    private void processBulkMessage(Message msg, MessageElement idMsgElement) {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, ">>PipeWrapper:  processBulkMessage...");
        }
        //_logger.log(Level.INFO, ">>PipeWrapper:  processBulkMessage...");
        printMessageReceiptStats(msg);
        ReplicationMessageRouter receiver = null;
        if (Globals.IS_SECURITY_ENABLED) {
            receiver = (ReplicationMessageRouter)
                AccessController.doPrivileged(
                    new PrivilegedGetReplicationMessageRouter());
        } else {
            receiver = ReplicationMessageRouter.createInstance();
        }        
        //check if this is a return bulk message and act accordingly
        //System.out.println("<<processBulkMessage:isVoidReturnMessage=" + ReplicationState.isVoidMethodReturnMessage(msg));
        //System.out.println("<<processBulkMessage:isAckRequiredForMessage=" + ReplicationState.isAckRequiredForMessage(msg));
        //System.out.println("<<processBulkMessage:isResponseMessage=" + ReplicationState.isResponseMessage(msg));
        if(!ReplicationState.isAckRequiredForMessage(msg)
            && !ReplicationState.isVoidMethodReturnMessage(msg)
            && ReplicationState.isResponseMessage(msg)) {
            List<String> ackIds = ReplicationState.extractAckIdsListFromMessage(msg);
            //iterate and deliver acks to each id in ackIds list and return
            processAcks(ackIds, receiver);
            return;
        }
        //send ack if required      
        List<ReplicationState> states = ReplicationState.extractBulkReplicationStatesFromMessage(msg);
        if(!isWaitForFastAckConfigured()) {
            this.checkSendImmediateBulkAck(msg, states);
        }
        //_logger.log(Level.INFO, ">>PipeWrapper:  states size = " + states.size());        
        for (ReplicationState state : states) {
            if (_logger.isLoggable(TRACE_LEVEL)) {
                _logger.log(TRACE_LEVEL, "<<PipeWrapper:  receiving id: " + state.getId() + "[ver:" + state.getVersion() + "]");
            }
            receiver.processMessage(state);            
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "<<PipeWrapper:  processBulkMessage complete...");
        }
    }
   
    private void processAcks(List<String> acksList, ReplicationMessageRouter receiver) {
        //_logger.log(Level.INFO, ">>PipeWrapper:processAcks:  acksList size = " + acksList.size());
        for(int i=0; i<acksList.size(); i++) {
            //_logger.log(Level.INFO,"processAcks:nextIdToAck:" + acksList.get(i));
            ReplicationState nextState = new ReplicationState(acksList.get(i));
            receiver.processResponse(nextState);
        }
    }
   
    private void processIdMessage(Message msg, MessageElement idMsgElement) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("PipeWrapper>>processIdMessage");
        }        
        printIdMessageReceiptStats(msg);
        if (idMsgElement.toString() == null) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("PipeWrapper>>processIdMessage:null id msg received");
            }           
            return;
        }
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("PipeWrapper:ID Message id:"+ idMsgElement.toString());
        }       
        this.checkSendImmediateAck(msg);
        ReplicationState state = this.createReplicationState(msg);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("PipeWrapper>>processIdMessage:incomingState=" + state);
        }       

        //System.out.println("PipeWrapper>>processIdMessage:incomingState=" + state);
        ReplicationMessageRouter receiver = null;
        if (Globals.IS_SECURITY_ENABLED) {
            receiver = (ReplicationMessageRouter)
                AccessController.doPrivileged(
                    new PrivilegedGetReplicationMessageRouter());
        } else {
            receiver = ReplicationMessageRouter.createInstance();
        }               
        receiver.processMessage(state);       
       
    }
   
    public boolean isWaitForFastAckConfigured() {
        if(_waitForFastAckConfigured == null) {
            ServerConfigLookup lookup = new ServerConfigLookup();
            boolean waitForFastAckProp = lookup.getWaitForFastAckPropertyFromConfig();
            _waitForFastAckConfigured = new Boolean(waitForFastAckProp);
            //System.out.println("isWaitForFastAckConfigured = " + _waitForFastAckConfigured.booleanValue());
        }
        return _waitForFastAckConfigured.booleanValue();
    }   
   
    /**
     * is wait_for_fast_ack_property = "true"
     */
    private Boolean _waitForFastAckConfigured = null;   
   
    private ReplicationState createReplicationState(Message msg) {
        return ReplicationState.createReplicationState(msg);
    }
   
    public void cleanup() {
        this.cleanup(true);
    }
   
    public synchronized void cleanup(boolean doClose) {
        if(this.isPipeClosed()) {
            return;
        }
        //disable listener - we do not want this event
        //since we are closing
        _pipe.setPipeEventListener(null);
        if(_pipelogger.isLoggable(Level.FINE)) {
            _pipelogger.log(Level.FINE, "PipeWrapper>>cleanup called for " + _name,
                    new Throwable("Diagnostic Message: PipeWrapper.cleanup()"));
        }        
        if(doClose) {
            try {
                _pipe.close();
                if(_pipelogger.isLoggable(Level.FINE)) {
                    _pipelogger.fine("PipeWrapper>>_pipe.close() called for " + _name);
                }               
            } catch (Throwable t) {
                // FIXME evaluate log level
                if(_pipelogger.isLoggable(Level.FINE)) {
                    _pipelogger.log(Level.FINE, "PipeWrapper:exception closing pipe during cleanup for " + _name, t);
                }               
            }
        }
        setPipeClosed(true);
        _pipe = null;
        _name = null;
    }   
   
    public void pipeEvent(int event) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("PipeWrapper:in pipeEvent: event=" + event);
        }       
        if(event == JxtaBiDiPipe.PIPE_CLOSED_EVENT) {
            if(_pipelogger.isLoggable(Level.FINE)) {
                _pipelogger.fine("handling pipe event pipe closed:is this end closed:" + isPipeClosed());           
                _pipelogger.fine("handling pipe event pipe closed:pipeWrapper:" + this);               
            }            
            //you close your side's pipe too if not already closed
            synchronized(this) {
                if(!isPipeClosed()) {
                    cleanup();
                }
            }
            String partnerInstanceName = this.getPartnerInstanceName();
            ReplicationHealthChecker healthChecker
                = ReplicationHealthChecker.getInstance();
            //only process where it is our
            //replicate from partner - which means this is
            //a receiver pipe - this case will be handled
            //as pending in PlannedShutdownEventNotificationHandler
            if(this.isReceiver()) {
                PlannedShutdownNotificationEventHandler.checkAndDoShutdownFor(partnerInstanceName);
            }           
           
            /*
             * Discontinued treating pipe close as an event to trigger reshape.
             *
            //if not deliberately stopping then health is bad and
            //we must reinitialize pipes
            if(!ReplicationHealthChecker.isStopping()) {
                String partnerInstanceName = this.getPartnerInstanceName();
                if(_pipelogger.isLoggable(Level.FINE)) {
                    _pipelogger.fine("PipeWrapper close event causing pipes reInit:partnerInstance: " + partnerInstanceName);
                }
                JxtaReplicationReceiver jxtaReplicationReceiver
                    = (JxtaReplicationReceiver) ReplicationHealthChecker.getReplicationReceiver();
                if(_pipelogger.isLoggable(Level.FINE)) {
                    _pipelogger.fine("PipeWrapper:about to call reInit: jxtaReplicationReceiver: " + jxtaReplicationReceiver + "_senderOrReceiver=" + _senderOrReceiver);
                }
                if (_pipelogger.isLoggable(TRACE_LEVEL)) {
                    _pipelogger.log(TRACE_LEVEL, "PipeWrapper:about to call reInit: jxtaReplicationReceiver: " + jxtaReplicationReceiver + "_senderOrReceiver=" + _senderOrReceiver);
                }
                ReplicationHealthChecker healthChecker
                    = ReplicationHealthChecker.getInstance();
                healthChecker.removeIfExtraInstance(partnerInstanceName);               
                jxtaReplicationReceiver.reInit(getSenderOrReceiver(), partnerInstanceName);
            }         
            */         
        }
    }
   
    JxtaBiDiPipe getPipe() {
        return _pipe;
    }
   
    public String getName() {
        return _name;
    }
   
    public void setName(String aName) {
        _name = aName;
    }   
   
    public synchronized boolean isPipeClosed() {
        return _pipeClosed;
    }   
   
    public synchronized boolean isBound() {
  if (isPipeClosed() || _pipe == null) {
      return false;
        }
        return _pipe.isBound();

    }

    private synchronized void setPipeClosed(boolean value) {
        _pipeClosed = value;
    }
   
    public String toString() {
        StringBuffer sb = new StringBuffer(100);
        sb.append(super.toString());
        sb.append("isPipeClosed=" + isPipeClosed() + "\n");
        sb.append("_pipe=" + _pipe + "\n");
        return sb.toString();      
    }
   
    //begin mimic OutgoingMessageEventListener code
    //but without event just use the message directly
   
   /**
    * The message identified by the event was successfully sent. Successfully
    * sending a message is not a guarantee that it will be successfully
    * received by the destination.
    * @param sentMessage the sent message directly
    */
    public void messageSendSucceeded(Message sentMessage) {

        if (_logger.isLoggable(Level.FINER)) {
            _logger.entering("PipeWrapper", "messageSendSuccedded", sentMessage);
        }
        decrementQueuedMessageCount();
        //Message sentMessage = (Message)event.getSource();
        String ackRequiredString = (String)sentMessage.getMessageProperty(MESSAGE_ACK_REQUIRED);       
        printFastAckStats(sentMessage, true);           
        if(ackRequiredString.equalsIgnoreCase("Y")) {
            //_logger.fine("doing fast ack...");
            //for bulk case
            MessageElement bulkMsgElement = sentMessage.getMessageElement(BULK_MESSAGE_MODE, BULK_MESSAGE_MODE);
            if(bulkMsgElement != null) {
                doFastBulkAcksFor(sentMessage, bulkMsgElement);
            } else {
                //for non bulk case
                MessageElement idMsgElement = sentMessage.getMessageElement(MESSAGE_ID, MESSAGE_ID);
                if(idMsgElement != null) {
                    doFastAckFor(sentMessage, idMsgElement);
                }
            }
        }

    }
   
   /**
    * The message identified by the event could not be sent.
    * <p/>
    * The cause of the failure, if any, is available from
    * {@link OutgoingMessageEvent#getFailure()}. Failures while sending
    * messages have several causes :
    * <p/>
    * <ul>
    * <li>An {@link java.io.IOException} means that the messenger cannot
    * send the message and the messenger will accept no further messages
    * to be sent.</li>
    * <p/>
    * <li>A {@link java.lang.RuntimeException} mean that the message was
    * not sent, but retries may or may not be possible based upon the
    * status returned by {@link Messenger#isClosed()}.</li>
    * <p/>
    * <li><code>null</code> means that the message was not sent, but may
    * be retried. Usually the failure is due to local resource limits
    * being exceeded. Attempts may be made to later resend the message,
    * usually after waiting for congestion to clear.</li>
    * </ul>
    * @param sentMessage the message that was not able to be sent
    */
    public void messageSendFailed(Message sentMessage) {
        printFastAckStats(sentMessage, false);
        decrementQueuedMessageCount();
    }   
   
    //begin OutgoingMessageEventListener code
   
   /**
    * The message identified by the event could not be sent.
    * <p/>
    * The cause of the failure, if any, is available from
    * {@link OutgoingMessageEvent#getFailure()}. Failures while sending
    * messages have several causes :
    * <p/>
    * <ul>
    * <li>An {@link java.io.IOException} means that the messenger cannot
    * send the message and the messenger will accept no further messages
    * to be sent.</li>
    * <p/>
    * <li>A {@link java.lang.RuntimeException} mean that the message was
    * not sent, but retries may or may not be possible based upon the
    * status returned by {@link Messenger#isClosed()}.</li>
    * <p/>
    * <li><code>null</code> means that the message was not sent, but may
    * be retried. Usually the failure is due to local resource limits
    * being exceeded. Attempts may be made to later resend the message,
    * usually after waiting for congestion to clear.</li>
    * </ul>
    * @param event the event
    */
    public void messageSendFailed(OutgoingMessageEvent event) {
        Message sentMessage = (Message)event.getSource();
        printFastAckStats(sentMessage, false);
        decrementQueuedMessageCount();
    }

   /**
    * The message identified by the event was successfully sent. Successfully
    * sending a message is not a guarantee that it will be successfully
    * received by the destination.
    * @param event the event
    */
    public void messageSendSucceeded(OutgoingMessageEvent event) {

        //System.out.println("messageSendSucceeded");
        decrementQueuedMessageCount();
        Message sentMessage = (Message)event.getSource();
        String ackRequiredString = (String)sentMessage.getMessageProperty(MESSAGE_ACK_REQUIRED);       
        printFastAckStats(sentMessage, true);           
        if(ackRequiredString.equalsIgnoreCase("Y")) {
            //System.out.println("doing fast ack...");
            //for bulk case
            MessageElement bulkMsgElement = sentMessage.getMessageElement(BULK_MESSAGE_MODE, BULK_MESSAGE_MODE);
            if(bulkMsgElement != null) {
                doFastBulkAcksFor(sentMessage, bulkMsgElement);
            } else {
                //for non bulk case
                MessageElement idMsgElement = sentMessage.getMessageElement(MESSAGE_ID, MESSAGE_ID);
                if(idMsgElement != null) {
                    doFastAckFor(sentMessage, idMsgElement);
                }
            }
        }

    }
   
    private void doFastBulkAcksFor(Message sentMessage, MessageElement bulkMsgElement) {
        //System.out.println("doFastBulkAcksFor...");
        if(ReplicationState.isHCMessage(sentMessage)) {
            if (_logger.isLoggable(TRACE_LEVEL)) {
                _logger.log(TRACE_LEVEL, "HC message do not do fast ack for this...");
            }
            return;
        }
        //fast ack the bulk message itself
        processResponse(sentMessage);
        ReplicationMessageRouter receiver = null;
        if (Globals.IS_SECURITY_ENABLED) {
            receiver = (ReplicationMessageRouter)
                AccessController.doPrivileged(
                    new PrivilegedGetReplicationMessageRouter());
        } else {
            receiver = ReplicationMessageRouter.createInstance();
        }        
        List ackIdsList = (List)sentMessage.getMessageProperty(MESSAGE_ACK_LIST_PROPERTY);
        //System.out.println("doFastBulkAcksFor:ackIdsList size = " + ackIdsList.size());
        //iterate and deliver acks to each id in ackIds list and return
        processAcks(ackIdsList, receiver);       
    }
   
    private void doFastAckFor(Message sentMessage, MessageElement bulkMsgElement) {
        //System.out.println("doFastAckFor...");
        if(ReplicationState.isHCMessage(sentMessage)) {
            if (_logger.isLoggable(TRACE_LEVEL)) {
                _logger.log(TRACE_LEVEL, "HC message do not do fast ack for this...");
            }
            return;
        }
        processResponse(sentMessage);       
    }
   
    //utility methods for measurements
   
    private void printFastAckStats(Message sentMessage, boolean succeeded) {
        if(!this.getReplicationMeasurementEnabled()) {
            return;
        }
        boolean useLong = true;
        int measurementInterval = this.getReplicationMeasurementInterval();
        long id = -1L;
        String stringId = "";
        MessageElement idMsgElement =
            sentMessage.getMessageElement(MESSAGE_ID, MESSAGE_ID);
        if(idMsgElement != null) {
            try {
                id = (Long.decode(idMsgElement.toString())).longValue();
            } catch (NumberFormatException ex) {
                useLong = false;
                stringId = idMsgElement.toString();
            }           
            //System.out.println("messageSendSucceeded: bulkId = " + id);
        }
        if(useLong) {
            stringId = ""+id;
        }       
        if(useLong && (id == -1 || id % measurementInterval != 0)) {
            return;
        }       
        String sendStartTimeString = (String)sentMessage.getMessageProperty(MESSAGE_SEND_START_TIME);      
        long sendStartTime =
            (Long.decode(sendStartTimeString)).longValue();
        String prefix = "messageSendSucceeded: id = ";
        if(!succeeded) {
            prefix = "messageSendFailed: id = ";
        }
        _logger.log(Level.INFO, prefix + stringId + " fastAckTime = "
            + (System.currentTimeMillis() - sendStartTime) + " to partner: " + getPartnerInstanceName());       
    }

    private void printMessageReceiptStats(Message receivedMessage) {
        if(!this.getReplicationMeasurementEnabled()) {
            return;
        }
        int measurementInterval = this.getReplicationMeasurementInterval();
        long id = -1L;
        MessageElement idMsgElement =
            receivedMessage.getMessageElement(MESSAGE_ID, MESSAGE_ID);
        if(idMsgElement != null) {
            id = (Long.decode(idMsgElement.toString())).longValue();
            //System.out.println("messageReceived: bulkId = " + id);
        }
        if(id % measurementInterval != 0) {
            return;
        }
        //get send start time for measurements
        long sendStartTime = -1L;
        MessageElement sendStartMsgElement =
            receivedMessage.getMessageElement(MESSAGE_SEND_START_TIME, MESSAGE_SEND_START_TIME);
        if(sendStartMsgElement != null) {
            sendStartTime =
                (Long.decode(sendStartMsgElement.toString())).longValue();
            if(sendStartTime > 0L) {
                //System.out.println("message receipt time: " + (System.currentTimeMillis() - sendStartTime));
            }
        }
        _logger.log(Level.INFO, "messageReceiptSucceeded: bulkId = " + id + " receiptTime = "
            + (System.currentTimeMillis() - sendStartTime) + " from partner: " + getPartnerInstanceName());      
    }
   
    private void printIdMessageReceiptStats(Message receivedMessage) {
        if(!this.getReplicationMeasurementEnabled()) {
            return;
        }
        String id = "";
        MessageElement idMsgElement =
            receivedMessage.getMessageElement(MESSAGE_ID, MESSAGE_ID);
        if(idMsgElement != null) {
            id = idMsgElement.toString();
        }
        //get send start time for measurements
        long sendStartTime = -1L;
        MessageElement sendStartMsgElement =
            receivedMessage.getMessageElement(MESSAGE_SEND_START_TIME, MESSAGE_SEND_START_TIME);
        if(sendStartMsgElement != null) {
            sendStartTime =
                (Long.decode(sendStartMsgElement.toString())).longValue();
        }
        _logger.log(Level.INFO, "messageReceiptSucceeded: id = " + id + " receiptTime = "
            + (System.currentTimeMillis() - sendStartTime));        
    }   
   
    Boolean _replicationMeasurementEnabled = null;
    private boolean getReplicationMeasurementEnabled() {
        if(_replicationMeasurementEnabled == null) {
            ServerConfigLookup lookup = new ServerConfigLookup();
            _replicationMeasurementEnabled
                = new Boolean(lookup.getReplicationMeasurementEnabledFromConfig());                       
        }
        return _replicationMeasurementEnabled.booleanValue();
    }

    int _replicationMeasurementInterval = -1;
    private int getReplicationMeasurementInterval() {
        if(_replicationMeasurementInterval == -1) {
            ServerConfigLookup lookup = new ServerConfigLookup();
            _replicationMeasurementInterval
                = lookup.getReplicationMeasurementIntervalFromConfig();                       
        }
        return _replicationMeasurementInterval;
    }   
   
    //end utility methods for diagnostics        
      
    public void processResponse(Message sentMessage) {
        ReplicationState sentState = createReplicationState(sentMessage);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("IN" + this.getClass().getName() + ">>processResponse");           
        }       
        ReplicationResponseRepository.putEntry(sentState);
    }  
  
   //end OutgoingMessageEventListener code
   
    public boolean isPipeOverStressed() {
        return (_locallyQueuedMessages.get() > (PIPE_QUEUE_CAPACITY - 2));
    }
   
    int incrementQueuedMessageCount() {
        return _locallyQueuedMessages.incrementAndGet();
    }   
   
    int decrementQueuedMessageCount() {
        return _locallyQueuedMessages.decrementAndGet();
    }
   
    boolean hasReceivedHCMessage() {
        return _receivedHCMessage;
    }
   
    void setReceivedHCMessage(boolean value) {
        _receivedHCMessage = value;
    }   
   
    private JxtaBiDiPipe _pipe = null;
    private String _name = null;
    private boolean _pipeClosed = false;
    private final AtomicInteger _locallyQueuedMessages = new AtomicInteger(0);
    private boolean _receivedHCMessage = false;

   
}
TOP

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

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.