Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed ArrayOutOfBoundsException in FD_SOCK (https://issues.jboss.org/…

  • Loading branch information...
commit 1bda0216c6c750bee79f1d38168b0869641436c4 1 parent 9316177
Bela Ban authored January 24, 2012

Showing 1 changed file with 51 additions and 58 deletions. Show diff stats Hide diff stats

  1. 109  src/org/jgroups/protocols/FD_SOCK.java
109  src/org/jgroups/protocols/FD_SOCK.java
@@ -6,14 +6,12 @@
6 6
 import org.jgroups.stack.IpAddress;
7 7
 import org.jgroups.stack.Protocol;
8 8
 import org.jgroups.util.*;
  9
+import org.jgroups.util.ThreadFactory;
9 10
 
10 11
 import java.io.*;
11 12
 import java.net.*;
12 13
 import java.util.*;
13  
-import java.util.concurrent.ConcurrentMap;
14  
-import java.util.concurrent.Future;
15  
-import java.util.concurrent.RejectedExecutionException;
16  
-import java.util.concurrent.TimeUnit;
  14
+import java.util.concurrent.*;
17 15
 
18 16
 
19 17
 /**
@@ -93,11 +91,11 @@
93 91
     /* --------------------------------------------- Fields ------------------------------------------------------ */
94 92
 
95 93
     
96  
-    private final List<Address> members=new ArrayList<Address>(11); // list of group members (updated on VIEW_CHANGE)
  94
+    private volatile List<Address> members=new ArrayList<Address>(11); // volatile eliminates the lock
97 95
 
98  
-    protected final Set<Address> suspected_mbrs=new HashSet<Address>();
  96
+    protected final Set<Address>   suspected_mbrs=new CopyOnWriteArraySet<Address>();
99 97
 
100  
-    private final List<Address> pingable_mbrs=new ArrayList<Address>(11);
  98
+    private final List<Address>    pingable_mbrs=new CopyOnWriteArrayList<Address>();
101 99
 
102 100
     volatile boolean srv_sock_sent=false; // has own socket been broadcast yet ?
103 101
     /** Used to rendezvous on GET_CACHE and GET_CACHE_RSP */
@@ -132,9 +130,9 @@ public FD_SOCK() {
132 130
     @ManagedAttribute(description="Member address")
133 131
     public String getLocalAddress() {return local_addr != null? local_addr.toString() : "null";}
134 132
     @ManagedAttribute(description="List of cluster members")
135  
-    public String getMembers() {return members != null? members.toString() : "null";}
  133
+    public String getMembers() {return members.toString();}
136 134
     @ManagedAttribute(description="List of pingable members of a cluster")
137  
-    public String getPingableMembers() {return pingable_mbrs != null? pingable_mbrs.toString() : "null";}
  135
+    public String getPingableMembers() {return pingable_mbrs.toString();}
138 136
     @ManagedAttribute(description="Ping destination")
139 137
     public String getPingDest() {return ping_dest != null? ping_dest.toString() : "null";}
140 138
     @ManagedAttribute(description="Number of suspect event generated")
@@ -317,31 +315,28 @@ public Object down(Event evt) {
317 315
                 View v=(View) evt.getArg();
318 316
                 final List<Address> new_mbrs=v.getMembers();
319 317
 
320  
-                synchronized(this) {
321  
-                    members.clear();
322  
-                    members.addAll(new_mbrs);
323  
-                    suspected_mbrs.retainAll(new_mbrs);
324  
-                    cache.keySet().retainAll(members); // remove all entries in 'cache' which are not in the new membership
325  
-                    bcast_task.adjustSuspectedMembers(members);
326  
-                    pingable_mbrs.clear();
327  
-                    pingable_mbrs.addAll(members);
328  
-                    if(log.isDebugEnabled()) log.debug("VIEW_CHANGE received: " + members);
329  
-
330  
-                    if(members.size() > 1) {
331  
-                        if(isPingerThreadRunning()) {
332  
-                            Address tmp_ping_dest=determinePingDest();
333  
-                            boolean hasNewPingDest = ping_dest != null && tmp_ping_dest != null && !ping_dest.equals(tmp_ping_dest);
334  
-                            if(hasNewPingDest) {
335  
-                                interruptPingerThread(); // allows the thread to use the new socket
336  
-                            }
  318
+                members=new_mbrs;  // volatile write will ensure all reads after this see the new membership
  319
+                suspected_mbrs.retainAll(new_mbrs);
  320
+                cache.keySet().retainAll(new_mbrs); // remove all entries in 'cache' which are not in the new membership
  321
+                bcast_task.adjustSuspectedMembers(new_mbrs);
  322
+                pingable_mbrs.clear();
  323
+                pingable_mbrs.addAll(new_mbrs);
  324
+                if(log.isDebugEnabled()) log.debug("VIEW_CHANGE received: " + new_mbrs);
  325
+
  326
+                if(new_mbrs.size() > 1) {
  327
+                    if(isPingerThreadRunning()) {
  328
+                        Address tmp_ping_dest=determinePingDest();
  329
+                        boolean hasNewPingDest = ping_dest != null && tmp_ping_dest != null && !ping_dest.equals(tmp_ping_dest);
  330
+                        if(hasNewPingDest) {
  331
+                            interruptPingerThread(); // allows the thread to use the new socket
337 332
                         }
338  
-                        else
339  
-                            startPingerThread(); // only starts if not yet running
340  
-                    }
341  
-                    else {
342  
-                        ping_dest=null;
343  
-                        stopPingerThread();
344 333
                     }
  334
+                    else
  335
+                        startPingerThread(); // only starts if not yet running
  336
+                }
  337
+                else {
  338
+                    ping_dest=null;
  339
+                    stopPingerThread();
345 340
                 }
346 341
                 break;
347 342
 
@@ -450,14 +445,11 @@ void suspect(Set<Address> suspects) {
450 445
             return;
451 446
 
452 447
         final List<Address> eligible_mbrs=new ArrayList<Address>();
453  
-        synchronized(this) {
454  
-            for(Address suspect: suspects) {
455  
-                suspect_history.add(suspect);
456  
-                suspected_mbrs.add(suspect);
457  
-            }
458  
-            eligible_mbrs.addAll(members);
459  
-            eligible_mbrs.removeAll(suspected_mbrs);
460  
-        }
  448
+        for(Address suspect: suspects)
  449
+            suspect_history.add(suspect);
  450
+        suspected_mbrs.addAll(suspects);
  451
+        eligible_mbrs.addAll(members);
  452
+        eligible_mbrs.removeAll(suspected_mbrs);
461 453
 
462 454
         // Check if we're coord, then send up the stack
463 455
         if(local_addr != null && !eligible_mbrs.isEmpty()) {
@@ -790,8 +782,9 @@ private Address determinePingDest() {
790 782
     }
791 783
 
792 784
 
793  
-    Address determineCoordinator() {
794  
-        return !members.isEmpty()? members.get(0) : null;
  785
+    protected Address determineCoordinator() {
  786
+        List<Address> tmp=members;
  787
+        return !tmp.isEmpty()? tmp.get(0) : null;
795 788
     }
796 789
 
797 790
 
@@ -1123,7 +1116,7 @@ public void run() {
1123 1116
      * any longer. Then the task terminates.
1124 1117
      */
1125 1118
     private class BroadcastTask implements Runnable {
1126  
-        final Set<Address> suspected_mbrs=new HashSet<Address>();
  1119
+        final Set<Address>    suspects=new HashSet<Address>();
1127 1120
         Future<?>             future;
1128 1121
 
1129 1122
 
@@ -1131,8 +1124,8 @@ public void run() {
1131 1124
         public void addSuspectedMember(Address mbr) {
1132 1125
             if(mbr == null) return;
1133 1126
             if(!members.contains(mbr)) return;
1134  
-            synchronized(suspected_mbrs) {
1135  
-                if(suspected_mbrs.add(mbr))
  1127
+            synchronized(suspects) {
  1128
+                if(suspects.add(mbr))
1136 1129
                     startTask();
1137 1130
             }
1138 1131
         }
@@ -1140,9 +1133,9 @@ public void addSuspectedMember(Address mbr) {
1140 1133
 
1141 1134
         public void removeSuspectedMember(Address suspected_mbr) {
1142 1135
             if(suspected_mbr == null) return;
1143  
-            synchronized(suspected_mbrs) {
1144  
-                suspected_mbrs.remove(suspected_mbr);
1145  
-                if(suspected_mbrs.isEmpty()) {
  1136
+            synchronized(suspects) {
  1137
+                suspects.remove(suspected_mbr);
  1138
+                if(suspects.isEmpty()) {
1146 1139
                     stopTask();
1147 1140
                 }
1148 1141
             }
@@ -1150,8 +1143,8 @@ public void removeSuspectedMember(Address suspected_mbr) {
1150 1143
 
1151 1144
 
1152 1145
         public void removeAll() {
1153  
-            synchronized(suspected_mbrs) {
1154  
-                suspected_mbrs.clear();
  1146
+            synchronized(suspects) {
  1147
+                suspects.clear();
1155 1148
                 stopTask();
1156 1149
             }
1157 1150
         }
@@ -1182,11 +1175,11 @@ private void stopTask() {
1182 1175
          */
1183 1176
         public void adjustSuspectedMembers(List<Address> new_mbrship) {
1184 1177
             if(new_mbrship == null || new_mbrship.isEmpty()) return;
1185  
-            synchronized(suspected_mbrs) {
1186  
-                boolean modified=suspected_mbrs.retainAll(new_mbrship);
  1178
+            synchronized(suspects) {
  1179
+                boolean modified=suspects.retainAll(new_mbrship);
1187 1180
                 if(log.isTraceEnabled() && modified)
1188  
-                    log.trace("adjusted suspected_mbrs: " + suspected_mbrs);
1189  
-                if(suspected_mbrs.isEmpty())
  1181
+                    log.trace("adjusted suspected_mbrs: " + suspects);
  1182
+                if(suspects.isEmpty())
1190 1183
                     stopTask();
1191 1184
             }
1192 1185
         }
@@ -1197,17 +1190,17 @@ public void run() {
1197 1190
             FdHeader hdr;
1198 1191
 
1199 1192
             if(log.isTraceEnabled())
1200  
-                log.trace("broadcasting SUSPECT message (suspected_mbrs=" + suspected_mbrs + ") to group");
  1193
+                log.trace("broadcasting SUSPECT message (suspected_mbrs=" + suspects + ") to group");
1201 1194
 
1202  
-            synchronized(suspected_mbrs) {
1203  
-                if(suspected_mbrs.isEmpty()) {
  1195
+            synchronized(suspects) {
  1196
+                if(suspects.isEmpty()) {
1204 1197
                     stopTask();
1205 1198
                     if(log.isTraceEnabled()) log.trace("task done (no suspected members)");
1206 1199
                     return;
1207 1200
                 }
1208 1201
 
1209 1202
                 hdr=new FdHeader(FdHeader.SUSPECT);
1210  
-                hdr.mbrs=new HashSet<Address>(suspected_mbrs);
  1203
+                hdr.mbrs=new HashSet<Address>(suspects);
1211 1204
             }
1212 1205
             suspect_msg=new Message();       // mcast SUSPECT to all members
1213 1206
             suspect_msg.setFlag(Message.OOB);

0 notes on commit 1bda021

Please sign in to comment.
Something went wrong with that request. Please try again.