--- C:\dev\jgroups\Branch_2_4\JGroups\src\org\jgroups\protocols\FC.java	Wed Apr 18 00:15:16 2007
+++ C:\dev\jgroups\Branch_2_4\JGroups\src\org\jgroups\protocols\FC2.java	Wed Apr 18 00:21:01 2007
@@ -25,9 +25,9 @@
  * <br/>This is the second simplified implementation of the same model. The algorithm is sketched out in
  * doc/FlowControl.txt
  * @author Bela Ban
- * @version $Id: FC.java,v 1.53.2.2 2007/04/18 05:15:16 bstansberry Exp $
+ * @version $Id: FC2.java,v 1.1.2.1 2007/04/18 05:18:08 bstansberry Exp $
  */
-public class FC extends Protocol {
+public class FC2 extends Protocol {
 
     /** HashMap<Address,Long>: keys are members, values are credits left. For each send, the
      * number of credits is decremented by the message size */
@@ -74,7 +74,7 @@
     /** the lowest credits of any destination (sent_msgs) */
     private long lowest_credit=max_credits;
 
-    /** Lock to be used with the Condvar below */
+    /** Lock to be used with the CondVar below */
     final Sync lock=new ReentrantLock();
 
     /** Mutex to block on down() */
@@ -374,15 +374,12 @@
                     switch(hdr.type) {
                     case FcHeader.REPLENISH:
                         num_credit_responses_received++;
-                        handleCredit(msg.getSrc());
+                        handleCredit(msg.getSrc(), (Number) msg.getObject());
                         break;
                     case FcHeader.CREDIT_REQUEST:
                         num_credit_requests_received++;
                         Address sender=msg.getSrc();
-                        if(trace)
-                            log.trace("received credit request from " + sender + ": sending credits");
-                        received.put(sender, max_credits_constant);
-                        sendCredit(sender);
+                        handleCreditRequest(sender);
                         break;
                     default:
                         log.error("header type " + hdr.type + " not known");
@@ -399,6 +396,7 @@
             handleViewChange(((View)evt.getArg()).getMembers());
             break;
         }
+        
         passUp(evt);
     }
 
@@ -539,21 +537,23 @@
     }
 
 
-    private void handleCredit(Address sender) {
+    private void handleCredit(Address sender, Number increase) {
         if(sender == null) return;
         StringBuffer sb=null;
 
         if(Util.acquire(lock)) {
             try {
-                if(trace) {
                     Long old_credit=(Long)sent.get(sender);
+                Long new_credit = new Long(old_credit.longValue() + increase.longValue());
+                
+                if(trace) {
                     sb=new StringBuffer();
                     sb.append("received credit from ").append(sender).append(", old credit was ").
-                            append(old_credit).append(", new credits are ").append(max_credits).
+                            append(old_credit).append(", new credits are ").append(new_credit).
                             append(".\nCreditors before are: ").append(creditors);
                 }
 
-                sent.put(sender, max_credits_constant);
+                sent.put(sender, new_credit);
                 lowest_credit=computeLowestCredit(sent);
                 if(creditors.size() > 0) {  // we are blocked because we expect credit from one or more members
                     creditors.remove(sender);
@@ -596,17 +596,55 @@
         if(length == 0)
             return; // no effect
 
-        if(decrementCredit(received, src, length) <= min_credits) {
+        long remaining_cred = decrementCredit(received, src, length);
+        
+        if(remaining_cred <= min_credits) {
             received.put(src, max_credits_constant);
-            if(trace) log.trace("sending replenishment message to " + src);
-            sendCredit(src);
+            long credit_response= max_credits - remaining_cred;
+            if(trace) log.trace("sending " + credit_response + " replenishment credits to " + src);
+            sendCredit(src, credit_response);
         }
     }
 
+    private void handleCreditRequest(Address sender) {
+       if(sender == null) return;
 
+       if(Util.acquire(lock)) {
+           long credit_response = 0;
+           try {
+               Long old_credit=(Long)received.get(sender);
+               if (old_credit != null) {
+                  credit_response = max_credits - old_credit.longValue();
+               }
 
-    private void sendCredit(Address dest) {
-        Message  msg=new Message(dest, null, null);
+               if (credit_response > 0) {
+                  if(trace)
+                     log.trace("received credit request from " + sender + 
+                           ": sending " + credit_response + " credits");
+                 received.put(sender, max_credits_constant);
+               }
+               else if (trace) {
+                  log.trace("received credit request from " + sender + " but have no credits available");
+               }
+           }
+           finally {
+               Util.release(lock);
+           }
+           
+           if (credit_response > 0)
+              sendCredit(sender, credit_response);
+       }
+   }
+
+
+
+    private void sendCredit(Address dest, long credit) {
+        Number number;
+        if (credit < Integer.MAX_VALUE)
+           number = new Integer((int) credit);
+        else
+           number = new Long(credit);
+        Message  msg=new Message(dest, null, number);
         msg.putHeader(name, REPLENISH_HDR);
         passDown(new Event(Event.MSG, msg));
         num_credit_responses_sent++;
@@ -686,7 +724,6 @@
                 // keep it simple and just clear the last_credit_request Map
                 // at worst we get an extra credit request
                 last_credit_request.clear();
-                
             }
             finally {
                 Util.release(lock);
