Package org.jgroups.protocols

Source Code of org.jgroups.protocols.MFC

package org.jgroups.protocols;

import org.jgroups.Address;
import org.jgroups.Event;
import org.jgroups.Message;
import org.jgroups.annotations.MBean;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.ManagedOperation;
import org.jgroups.util.CreditMap;
import org.jgroups.util.Tuple;

import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
* Simple flow control protocol based on a credit system. Each sender has a number of credits (bytes
* to send). When the credits have been exhausted, the sender blocks. Each receiver also keeps track of
* how many credits it has received from a sender. When credits for a sender fall below a threshold,
* the receiver sends more credits to the sender. Works for both unicast and multicast messages.
* <p/>
* Note that this protocol must be located towards the top of the stack, or all down_threads from JChannel to this
* protocol must be set to false ! This is in order to block JChannel.send()/JChannel.down().
* <br/>This is the second simplified implementation of the same model. The algorithm is sketched out in
* doc/FlowControl.txt
* <br/>
* Changes (Brian) April 2006:
* <ol>
* <li>Receivers now send credits to a sender when more than min_credits have been received (rather than when min_credits
* are left)
* <li>Receivers don't send the full credits (max_credits), but rather the actual number of bytes received
* <ol/>
* @author Bela Ban
*/
@MBean(description="Simple flow control protocol based on a credit system")
public class MFC extends FlowControl {

   
   
    /* --------------------------------------------- Fields ------------------------------------------------------ */
   

    /** Maintains credits per member */
    protected CreditMap credits;

   
    /** Last time a credit request was sent. Used to prevent credit request storms */
    protected long last_credit_request=0;

  

    /** Allows to unblock a blocked sender from an external program, e.g. JMX */
    @ManagedOperation(description="Unblock a sender")
    public void unblock() {
        if(log.isTraceEnabled())
            log.trace("unblocking the sender and replenishing all members");
        credits.replenishAll();
    }

    @ManagedOperation(description="Print credits")
    public String printCredits() {
        return super.printCredits() + "\nsenders min credits: " + credits.computeLowestCreditWithAccumulated();
    }

    @ManagedOperation(description="Print sender credits")
    public String printSenderCredits() {
        return credits.toString();
    }

    @ManagedAttribute(description="Number of times flow control blocks sender")
    public int getNumberOfBlockings() {
        return credits.getNumBlockings();
    }

    @ManagedAttribute(description="Average time blocked (in ms) in flow control when trying to send a message")
    public double getAverageTimeBlocked() {
        return credits.getAverageBlockTime();
    }

    protected boolean handleMulticastMessage() {
        return true;
    }

  
    public void init() throws Exception {
        super.init();
        credits=new CreditMap(max_credits);
    }

    public void stop() {
        super.stop();
        credits.clear();
    }

    public void resetStats() {
        super.resetStats();
        credits.reset();
    }

    protected Object handleDownMessage(final Event evt, final Message msg, Address dest, int length) {
        if(dest != null) // 2nd line of defense, not really needed
            return down_prot.down(evt);

        long block_time=max_block_times != null? getMaxBlockTime(length) : max_block_time;
        while(running) {
            boolean rc=credits.decrement(length, block_time);
            if(rc || max_block_times != null || !running)
                break;

            if(needToSendCreditRequest()) {
                List<Tuple<Address,Long>> targets=credits.getMembersWithCreditsLessThan(min_credits);
                for(Tuple<Address,Long> tuple: targets)
                    sendCreditRequest(tuple.getVal1(), Math.min(max_credits, max_credits - tuple.getVal2()));
            }
        }
       
        // send message - either after regular processing, or after blocking (when enough credits are available again)
        return down_prot.down(evt);
    }




    protected synchronized boolean needToSendCreditRequest() {
        long curr_time=System.currentTimeMillis();
        long wait_time=curr_time - last_credit_request;
        if(wait_time >= max_block_time) {
            last_credit_request=curr_time;
            return true;
        }
        return false;
    }
 


    protected void handleCredit(Address sender, long increase) {
        credits.replenish(sender, increase);
        if(log.isTraceEnabled()) {
            StringBuilder sb=new StringBuilder();
            sb.append("received " + increase + " credits from ").append(sender).append(", new credits for " + sender + " : ")
                    .append(credits.get(sender) + ", min_credits=" + credits.getMinCredits());
            log.trace(sb);
        }
    }


    protected void handleViewChange(List<Address> mbrs) {
        super.handleViewChange(mbrs);

        Set<Address> keys=new HashSet<Address>(credits.keys());
        for(Address key: keys) {
            if(!mbrs.contains(key))
                credits.remove(key);
        }

        for(Address key: mbrs)
            credits.putIfAbsent(key);
    }




}
TOP

Related Classes of org.jgroups.protocols.MFC

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.