All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebeaninternal.server.cluster.mcast.McastPacketControl Maven / Gradle / Ivy

/**
 * Copyright (C) 2009 Authors
 * 
 * This file is part of Ebean.
 * 
 * Ebean is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *  
 * Ebean is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Ebean; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  
 */
package com.avaje.ebeaninternal.server.cluster.mcast;

import java.io.DataInput;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.avaje.ebeaninternal.server.cluster.Packet;
import com.avaje.ebeaninternal.server.cluster.PacketMessages;

/**
 * Helps co-ordinate Packet information between the McastListener and the
 * McastClusterManager.
 * 
 * @author rbygrave
 */
public class McastPacketControl {

    private static final Logger logger = Logger.getLogger(McastPacketControl.class.getName());

    private final String localSenderHostPort;

    private final McastClusterManager owner;

    private final HashSet groupMembers = new HashSet();

    private final OutgoingPacketsAcked outgoingPacketsAcked = new OutgoingPacketsAcked();

    private final IncomingPacketsProcessed incomingPacketsProcessed;

    public McastPacketControl(McastClusterManager owner, String localSenderHostPort, int maxResendIncoming) {
        this.owner = owner;
        this.localSenderHostPort = localSenderHostPort;
        this.incomingPacketsProcessed = new IncomingPacketsProcessed(maxResendIncoming);
    }

    /**
     * Handle special case where cluster doesn't have any members and we don't
     * get any responses. Need to tell the sender side that the group size is 0.
     */
    protected void onListenerTimeout() {
        if (groupMembers.size() == 0) {
            owner.fromListenerTimeoutNoMembers();
        }
    }

    protected void processMessagesPacket(String senderHostPort, Packet header, DataInput dataInput, 
            long totalPacketsReceived, long totalBytesReceived, long totalTransEventsReceived) throws IOException {

        PacketMessages packetMessages = PacketMessages.forRead(header);
        packetMessages.read(dataInput);
        List messages = packetMessages.getMessages();

        if (logger.isLoggable(Level.FINER)) {
            logger.finer("INCOMING Messages " + messages);
        }
        // messages are for all nodes in the cluster so
        // we need to filter looking for messages pertaining
        // to this (senderHostPort)

        MessageControl control = null;
        MessageAck ack = null;
        MessageResend resend = null;

        // filter for relevant messages to this node
        for (int i = 0; i < messages.size(); i++) {
            Message message = messages.get(i);
            if (message.isControlMessage()) {
                // any 'control' message is interesting
                control = (MessageControl) message;

            } else if (localSenderHostPort.equals(message.getToHostPort())) {
                if (message instanceof MessageAck) {
                    ack = (MessageAck) message;
                } else if (message instanceof MessageResend) {
                    resend = (MessageResend) message;
                } else {
                    logger.log(Level.SEVERE, "Expecting a MessageAck or MessageResend but got a "
                            + message.getClass().getName());
                }
            }
        }

        if (control != null) {
            if (control.getControlType() == MessageControl.TYPE_LEAVE) {
                groupMembers.remove(senderHostPort);
                logger.info("Cluster member leaving [" + senderHostPort + "] " + groupMembers.size()
                        + " other members left");
                outgoingPacketsAcked.removeMember(senderHostPort);
                incomingPacketsProcessed.removeMember(senderHostPort);
            } else {
                groupMembers.add(senderHostPort);
            }
        }

        long newMin = 0;
        if (ack != null) {
            newMin = outgoingPacketsAcked.receivedAck(senderHostPort, ack);
        }

        if (newMin > 0 || control != null || resend != null) {
            int groupSize = groupMembers.size();
            // synchronised on the managerThread
            owner.fromListener(newMin, control, resend, groupSize, 
                    totalPacketsReceived, totalBytesReceived, totalTransEventsReceived);
        }
    }

    /**
     * Return true if we should process this packet. Return false if we have
     * already processed the packet.
     */
    public boolean isProcessPacket(String memberKey, long packetId) {

        return incomingPacketsProcessed.isProcessPacket(memberKey, packetId);
    }

    public AckResendMessages getAckResendMessages(IncomingPacketsLastAck lastAck) {

        return incomingPacketsProcessed.getAckResendMessages(lastAck);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy