package org.jgroups.tests;
import org.jgroups.*;
import org.jgroups.conf.ClassConfigurator;
import org.jgroups.protocols.*;
import org.jgroups.protocols.pbcast.GMS;
import org.jgroups.protocols.pbcast.NAKACK2;
import org.jgroups.protocols.pbcast.STABLE;
import org.jgroups.stack.ProtocolStack;
import org.jgroups.util.MutableDigest;
import org.jgroups.util.Util;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
import java.util.*;
/**
* Tests a merge between asymmetric partitions where an isolated coord is still seen by others.
* Example : {A,B,C,D} and {A}.
*
*/
@Test(groups=Global.FUNCTIONAL,sequential=true)
public class MergeTest4 {
protected JChannel a,b,c,d,e,f,g,h,i,j,s,t,u,v;
protected static final Method stopInfoSender, startInfoSender;
protected static final short merge_id=ClassConfigurator.getProtocolId(MERGE3.class);
static {
try {
stopInfoSender=MERGE3.class.getDeclaredMethod("stopInfoSender");
startInfoSender=MERGE3.class.getDeclaredMethod("startInfoSender");
stopInfoSender.setAccessible(true);
startInfoSender.setAccessible(true);
}
catch(NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
@BeforeMethod
void setUp() throws Exception {
a=createChannel("A", true);
b=createChannel("B", true);
c=createChannel("C", true);
d=createChannel("D", true);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b, c, d);
enableInfoSender(false, a, b, c, d); // stops INFO sending in MERGE3
}
@AfterMethod void tearDown() throws Exception {Util.close(v,u,t,s,j,i,h,g,f,e,d,c,b,a);}
/**
* Tests a simple split: {A,B} and {C,D} need to merge back into one subgroup. Checks how many MergeViews are installed
*/
public void testSplitInTheMiddle() throws Exception {
View v1=View.create(a.getAddress(), 10, a.getAddress(), b.getAddress());
View v2=View.create(c.getAddress(), 10, c.getAddress(), d.getAddress());
injectView(v1, a,b);
injectView(v2, c,d);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b);
Util.waitUntilAllChannelsHaveSameView(10000, 500, c, d);
for(JChannel ch: Arrays.asList(a,b,c,d))
System.out.println(ch.getName() + ": " + ch.getView());
Address merge_leader_one=new Membership().add(a.getAddress(), b.getAddress()).sort().elementAt(0);
Address merge_leader_two=new Membership().add(c.getAddress(), d.getAddress()).sort().elementAt(0);
for(int x=0; x < 20; x++) {
if(a.getView().size() == 4 && b.getView().size() == 4 && c.getView().size() == 4 && d.getView().size() == 4)
break;
for(JChannel ch: Arrays.asList(a,b,c,d)) {
MERGE3 merge=ch.getProtocolStack().findProtocol(MERGE3.class);
merge.sendInfo(); // multicasts an INFO msg to everybody else
}
for(JChannel ch: Arrays.asList(findChannel(merge_leader_one), findChannel(merge_leader_two))) {
MERGE3 merge=ch.getProtocolStack().findProtocol(MERGE3.class);
merge.checkInconsistencies();
}
Util.sleep(1000);
}
for(JChannel ch: Arrays.asList(a,b,c,d))
System.out.println(ch.getName() + ": " + ch.getView());
for(JChannel ch: Arrays.asList(a,b,c,d))
assert ch.getView().size() == 4 : "view of " + ch.getName() + ": " + ch.getView();
}
/**
* Tests a simple split: {A,B} and {C,D} need to merge back into one subgroup. Checks how many MergeViews are installed
*/
public void testSplitInTheMiddle2() throws Exception {
View v1=View.create(a.getAddress(), 10, a.getAddress(), b.getAddress());
View v2=View.create(c.getAddress(), 10, c.getAddress(), d.getAddress());
injectView(v1, a,b);
injectView(v2, c,d);
enableInfoSender(false, a,b,c,d);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b);
Util.waitUntilAllChannelsHaveSameView(10000, 500, c, d);
enableInfoSender(false, a,b,c,d);
for(JChannel ch: Arrays.asList(a,b,c,d))
System.out.println(ch.getName() + ": " + ch.getView());
System.out.println("\nEnabling INFO sending in merge protocols to merge subclusters");
enableInfoSender(true, a, b, c, d);
Util.waitUntilAllChannelsHaveSameView(30000, 1000, a, b, c, d);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(a,b,c,d)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(a,b,c,d)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 4;
assert ((MergeView)mv).getSubgroups().size() == 2;
}
for(JChannel ch: Arrays.asList(a,b,c,d)) {
View view=ch.getView();
assert view.size() == 4 : "view should have 4 members: " + view;
}
}
public void testMergeWithAsymetricViewsCoordIsolated() throws Exception {
// Isolate the coord
Address coord = a.getView().getCreator();
System.out.println("Isolating coord: " + coord);
List<Address> members = new ArrayList<>();
members.add(coord);
View coord_view=new View(coord, 4, members);
System.out.println("coord_view: " + coord_view);
JChannel coord_channel = findChannel(coord);
System.out.println("coord_channel: " + coord_channel.getAddress());
MutableDigest digest=new MutableDigest(coord_view.getMembersRaw());
NAKACK2 nakack=coord_channel.getProtocolStack().findProtocol(NAKACK2.class);
digest.merge(nakack.getDigest(coord));
GMS gms=coord_channel.getProtocolStack().findProtocol(GMS.class);
gms.installView(coord_view, digest);
System.out.println("gms.getView() " + gms.getView());
System.out.println("Views are:");
for(JChannel ch: Arrays.asList(a,b,c,d))
System.out.println(ch.getAddress() + ": " + ch.getView());
JChannel merge_leader=findChannel(coord);
MyReceiver receiver=new MyReceiver();
merge_leader.setReceiver(receiver);
System.out.println("merge_leader: " + merge_leader.getAddressAsString());
System.out.println("Injecting MERGE event into merge leader " + merge_leader.getAddress());
Map<Address,View> merge_views=new HashMap<>(4);
merge_views.put(a.getAddress(), a.getView());
merge_views.put(b.getAddress(), b.getView());
merge_views.put(c.getAddress(), c.getView());
merge_views.put(d.getAddress(), d.getView());
gms=merge_leader.getProtocolStack().findProtocol(GMS.class);
gms.up(new Event(Event.MERGE, merge_views));
Util.waitUntilAllChannelsHaveSameView(10000, 1000, a, b, c, d);
System.out.println("Views are:");
for(JChannel ch: Arrays.asList(a,b,c,d)) {
View view=ch.getView();
System.out.println(ch.getAddress() + ": " + view);
assert view.size() == 4;
}
MergeView merge_view=receiver.getView();
System.out.println("merge_view = " + merge_view);
assert merge_view.size() == 4;
assert merge_view.getSubgroups().size() == 2;
for(View view: merge_view.getSubgroups())
assert contains(view, a.getAddress()) || contains(view, b.getAddress(), c.getAddress(), d.getAddress());
}
/**
* Tests a merge between ViewIds of the same coord, e.g. A|6, A|7, A|8, A|9
*/
public void testViewsBySameCoord() throws Exception {
View v1=View.create(a.getAddress(), 6, a.getAddress(),b.getAddress(),c.getAddress(),d.getAddress()); // {A,B,C,D}
View v2=View.create(a.getAddress(), 7, a.getAddress(),b.getAddress(),c.getAddress()); // {A,B,C}
View v3=View.create(a.getAddress(), 8, a.getAddress(),b.getAddress()); // {A,B}
View v4=View.create(a.getAddress(), 9, a.getAddress()); // {A}
Util.close(b,c,d); // not interested in those...
MERGE3 merge=a.getProtocolStack().findProtocol(MERGE3.class);
for(View view: Arrays.asList(v1,v2,v4,v3)) {
MERGE3.MergeHeader hdr=MERGE3.MergeHeader.createInfo(view.getViewId(), null, null);
Message msg=new Message(null).src(a.getAddress()).putHeader(merge.getId(), hdr);
merge.up(msg);
}
merge.checkInconsistencies(); // no merge will happen
Util.waitUntilAllChannelsHaveSameView(10000, 500, a);
System.out.println("A's view: " + a.getView());
assert a.getView().size() == 1;
assert a.getView().containsMember(a.getAddress());
}
/**
* Tests A|6, A|7, A|8 and B|7, B|8, B|9 -> we should have a subviews in MergeView consisting of
* only 2 elements: A|5 and B|5
*/
public void testMultipleViewsBySameMembers() throws Exception {
View a1=View.create(a.getAddress(), 6, a.getAddress(),b.getAddress(),c.getAddress(),d.getAddress()); // {A,B,C,D}
View a2=View.create(a.getAddress(), 7, a.getAddress(),b.getAddress(),c.getAddress()); // {A,B,C}
View a3=View.create(a.getAddress(), 8, a.getAddress(),b.getAddress()); // {A,B}
View a4=View.create(a.getAddress(), 9, a.getAddress()); // {A}
View b1=View.create(b.getAddress(), 7, b.getAddress(), c.getAddress(), d.getAddress());
View b2=View.create(b.getAddress(), 8, b.getAddress(), c.getAddress());
View b3=View.create(b.getAddress(), 9, b.getAddress());
Util.close(c,d); // not interested in those...
// A and B cannot communicate:
discard(true, a,b);
// inject view A|6={A} into A and B|5={B} into B
injectView(a4, a);
injectView(b3, b);
assert a.getView().equals(a4);
assert b.getView().equals(b3);
List<Message> merge_msgs=new ArrayList<>();
for(View view: Arrays.asList(a3,a4,a2,a1)) {
MERGE3.MergeHeader hdr=MERGE3.MergeHeader.createInfo(view.getViewId(), null, null);
Message msg=new Message(null).src(a.getAddress()).putHeader(merge_id, hdr);
merge_msgs.add(msg);
}
for(View view: Arrays.asList(b2,b3,b1)) {
MERGE3.MergeHeader hdr=MERGE3.MergeHeader.createInfo(view.getViewId(), null, null);
Message msg=new Message(null).src(b.getAddress()).putHeader(merge_id, hdr);
merge_msgs.add(msg);
}
// A and B can communicate again
discard(false, a,b);
injectMergeEvents(merge_msgs, a,b);
checkInconsistencies(a,b); // merge will happen between A and B
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b);
System.out.println("A's view: " + a.getView() + "\nB's view: " + b.getView());
assert a.getView().size() == 2;
assert a.getView().containsMember(a.getAddress());
assert a.getView().containsMember(b.getAddress());
assert a.getView().equals(b.getView());
for(View merge_view: Arrays.asList(getViewFromGMS(a), getViewFromGMS(b))) {
System.out.println(merge_view);
assert merge_view instanceof MergeView;
List<View> subviews=((MergeView)merge_view).getSubgroups();
assert subviews.size() == 2;
}
}
/**
* Takes a membership of 10, e.g. {A,B,C,D,E,F,G,H,I,J}, creates multiple partitions (e.g. {A,B,C}, {D}, {E,F,G,H}, {I,J}),
* and merges them back into one cluster. Asserts that there's only 1 MergeView
*/
public void testMultipleSplits() throws Exception {
e=createChannel("E", true);
f=createChannel("F", true);
g=createChannel("G", true);
h=createChannel("H", true);
i=createChannel("I", true);
j=createChannel("J", true);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b, c, d, e, f, g, h, i, j);
enableInfoSender(false, a,b,c,d,e,f,g,h,i,j); // stops INFO sending in MERGE3
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j))
System.out.println(ch.getName() + ": " + ch.getView());
List<View> partitions=createPartitions(4, a,b,c,d,e,f,g,h,i,j);
// Install views
for(View partition: partitions) {
for(Address mbr: partition.getMembersRaw()) {
JChannel ch=findChannel(mbr);
injectView(partition, ch);
}
}
System.out.printf("\n%d partitions:\n", partitions.size());
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j))
System.out.println(ch.getName() + ": " + ch.getView());
System.out.println("\nEnabling INFO sending in merge protocols to merge subclusters");
enableInfoSender(true, a,b,c,d,e,f,g,h,i,j);
Util.waitUntilAllChannelsHaveSameView(30000, 1000, a, b, c, d, e, f, g, h, i, j);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 10;
assert ((MergeView)mv).getSubgroups().size() == partitions.size();
}
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j)) {
View view=ch.getView();
assert view.size() == 10 : "view should have 10 members: " + view;
}
}
/**
* A: {A,B}
* B: {A,B}
* C: {C}
* C receives INFO from B only
*/
public void testMergeWithIncompleteInfos() throws Exception {
Util.close(d);
enableInfoSender(false, a,b,c);
View one=View.create(a.getAddress(), 10, a.getAddress(),b.getAddress());
View two=View.create(c.getAddress(), 10, c.getAddress());
injectView(one, a,b);
injectView(two, c);
enableInfoSender(false, a,b,c);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b);
Util.waitUntilAllChannelsHaveSameView(10000, 500, c);
System.out.printf("\nPartitions:\n");
for(JChannel ch: Arrays.asList(a,b,c))
System.out.println(ch.getName() + ": " + ch.getView());
MERGE3.MergeHeader hdr=MERGE3.MergeHeader.createInfo(one.getViewId(), null, null);
Message msg=new Message(null).src(b.getAddress()).putHeader(merge_id, hdr); // B sends the INFO message to C
MERGE3 merge=c.getProtocolStack().findProtocol(MERGE3.class);
merge.up(msg);
enableInfoSender(true,a,b,c);
System.out.println("\nEnabling INFO sending in merge protocols to merge subclusters");
Util.waitUntilAllChannelsHaveSameView(30000, 1000, a, b, c);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(a,b,c)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(a,b,c)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 3;
assert ((MergeView)mv).getSubgroups().size() == 2;
}
for(JChannel ch: Arrays.asList(a,b,c)) {
View view=ch.getView();
assert view.size() == 3 : "view should have 3 members: " + view;
}
}
/** Tests the scenario described by Karim in https://issues.jboss.org/browse/JGRP-1876 */
public void testJGRP_1876() throws Exception {
e=createChannel("E", true);
f=createChannel("F", true);
g=createChannel("G", true);
h=createChannel("H", true);
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b, c, d, e, f, g, h);
enableInfoSender(false, a,b,c,d,e,f,g,h); // stops INFO sending in MERGE3
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h))
System.out.println(ch.getName() + ": " + ch.getView());
View v1=View.create(a.getAddress(), 10, a.getAddress(), b.getAddress(), c.getAddress(), d.getAddress());
View v2=View.create(a.getAddress(), 9, a.getAddress(), b.getAddress(), c.getAddress(), d.getAddress(), e.getAddress(), f.getAddress());
View v3=View.create(g.getAddress(), 8, g.getAddress(), h.getAddress());
injectView(v1, a,b,c,d);
injectView(v2, e,f);
injectView(v3, g,h);
enableInfoSender(false, a,b,c,d,e,f,g,h); // stops INFO sending in MERGE3
Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b, c, d);
for(int x=0; x < 10; x++) { // can't use waitUntilAllChannelsHaveSameSize() as the channel list's length != view !
if(e.getView().size() == v2.size() && f.getView().size() == v2.size())
break;
Util.sleep(500);
}
assert e.getView().size() == v2.size() : "E's view: " + e.getView();
assert f.getView().size() == v2.size() : "F's view: " + f.getView();
Util.waitUntilAllChannelsHaveSameView(10000, 500, g, h);
System.out.printf("\nPartitions:\n");
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h))
System.out.println(ch.getName() + ": " + ch.getView());
enableInfoSender(true,a,b,c,d,e,f,g,h);
System.out.println("\nEnabling INFO sending in merge protocols to merge subclusters");
Util.waitUntilAllChannelsHaveSameView(30000, 1000, a, b, c, d, e, f, g, h);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 8;
assert ((MergeView)mv).getSubgroups().size() == 3;
}
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h)) {
View view=ch.getView();
assert view.size() == 8 : "view should have 8 members: " + view;
}
}
/** Tests the scenario described by Dan in https://issues.jboss.org/browse/JGRP-1876 */
public void testJGRP_1876_Dan() throws Exception {
Util.close(d,c,b,a);
s=createChannel("S", true);
t=createChannel("T", true);
u=createChannel("U", true);
v=createChannel("V", true);
Util.waitUntilAllChannelsHaveSameView(10000, 500, s, t, u, v);
enableInfoSender(false, s,t,u,v); // stops INFO sending in MERGE3
for(JChannel ch: Arrays.asList(s,t,u,v))
System.out.println(ch.getName() + ": " + ch.getView());
View v1=View.create(s.getAddress(), 10, s.getAddress());
View v2=View.create(t.getAddress(), 10, t.getAddress());
View v3=View.create(u.getAddress(), 11, u.getAddress(), v.getAddress());
injectView(v1, s);
injectView(v2, t);
injectView(v3, u,v);
enableInfoSender(false, s,t,u,v); // stops INFO sending in MERGE3
Util.waitUntilAllChannelsHaveSameView(10000, 500, s);
Util.waitUntilAllChannelsHaveSameView(10000, 500, t);
Util.waitUntilAllChannelsHaveSameView(10000, 500, u, v);
System.out.printf("\nPartitions:\n");
for(JChannel ch: Arrays.asList(s,t,u,v))
System.out.println(ch.getName() + ": " + ch.getView());
enableInfoSender(true,s,t,u,v);
System.out.println("\nEnabling INFO sending in merge protocols to merge subclusters");
Util.waitUntilAllChannelsHaveSameView(30000, 1000, s, t, u, v);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(s,t,u,v)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(s,t,u,v)) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 4;
assert ((MergeView)mv).getSubgroups().size() == 3;
}
for(JChannel ch: Arrays.asList(s,t,u,v)) {
View view=ch.getView();
assert view.size() == 4 : "view should have 4 members: " + view;
}
}
/** Tests the scenario described by Dan in https://issues.jboss.org/browse/JGRP-1876; INFO messages are injected */
public void testJGRP_1876_Dan2() throws Exception {
Util.close(d,c,b,a);
s=createChannel("S", false);
t=createChannel("T", false);
u=createChannel("U", false);
v=createChannel("V", false);
for(JChannel ch: Arrays.asList(s,t,u,v))
ch.getProtocolStack().removeProtocol(MERGE3.class);
s.connect("MergeTest4");
t.connect("MergeTest4");
u.connect("MergeTest4");
v.connect("MergeTest4");
Util.waitUntilAllChannelsHaveSameView(10000, 500, s, t, u, v);
for(JChannel ch: Arrays.asList(s,t,u,v))
System.out.println(ch.getName() + ": " + ch.getView());
View v1=View.create(s.getAddress(), 10, s.getAddress());
View v2=View.create(t.getAddress(), 10, t.getAddress());
View v3=View.create(u.getAddress(), 11, u.getAddress(), v.getAddress());
injectView(v1, s);
injectView(v2, t);
injectView(v3, u, v);
Util.waitUntilAllChannelsHaveSameView(10000, 500, s);
Util.waitUntilAllChannelsHaveSameView(10000, 500, t);
Util.waitUntilAllChannelsHaveSameView(10000, 500, u, v);
System.out.printf("\nPartitions:\n");
for(JChannel ch: Arrays.asList(s,t,u,v))
System.out.println(ch.getName() + ": " + ch.getView());
System.out.println("\nInjecting MERGE events into GMS to merge subclusters");
Map<Address,View> different_views=new HashMap<>();
different_views.put(s.getAddress(), v1);
different_views.put(t.getAddress(), v2);
different_views.put(v.getAddress(), v3);
Collection<Address> coords=Util.determineActualMergeCoords(different_views);
Address merge_leader=new Membership().add(coords).sort().elementAt(0);
System.out.printf("--> coords=%s, merge_leader=%s\n", coords, merge_leader);
GMS gms=findChannel(merge_leader).getProtocolStack().findProtocol(GMS.class);
gms.up(new Event(Event.MERGE, different_views));
Util.waitUntilAllChannelsHaveSameView(30000, 1000, s, t, u, v);
System.out.println("\nResulting views:");
for(JChannel ch: Arrays.asList(s,t,u,v)) {
gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
System.out.println(mv);
}
for(JChannel ch: Arrays.asList(s,t,u,v)) {
gms=ch.getProtocolStack().findProtocol(GMS.class);
View mv=gms.view();
assert mv instanceof MergeView;
assert mv.size() == 4;
assert ((MergeView)mv).getSubgroups().size() == 3;
}
for(JChannel ch: Arrays.asList(s,t,u,v)) {
View view=ch.getView();
assert view.size() == 4 : "view should have 4 members: " + view;
}
}
/** Creates a list of randomly generated partitions, each having a max size of max_partition_size */
protected List<View> createPartitions(int max_partition_size, JChannel ... channels) {
long view_id=1;
for(JChannel ch: channels)
view_id=Math.max(view_id, ch.getView().getViewId().getId());
List<View> partitions=new ArrayList<>();
List<Address> tmp=new ArrayList<>();
for(JChannel ch: channels)
tmp.add(ch.getAddress());
while(!tmp.isEmpty()) {
int num_to_remove=(int)Util.random(max_partition_size);
List<Address> part=new ArrayList<>(max_partition_size);
for(int x=0; x < num_to_remove && !tmp.isEmpty(); x++)
part.add(tmp.remove(0));
partitions.add(new View(part.get(0), view_id+1, part));
}
return partitions;
}
protected static boolean contains(View view, Address ... members) {
List<Address> mbrs=view.getMembers();
for(Address member: members)
if(!mbrs.contains(member))
return false;
return true;
}
protected static class MyReceiver extends ReceiverAdapter {
protected MergeView view;
public MergeView getView() {return view;}
@Override public void viewAccepted(View view) {
if(view instanceof MergeView)
this.view=(MergeView)view;
}
}
protected JChannel createChannel(String name, boolean connect) throws Exception {
JChannel retval=new JChannel(new SHARED_LOOPBACK(),
new SHARED_LOOPBACK_PING(),
new MERGE3().setValue("min_interval", 3000).setValue("max_interval", 4000).setValue("check_interval", 7000),
new NAKACK2().setValue("use_mcast_xmit",false)
.setValue("log_discard_msgs",false).setValue("log_not_found_msgs",false),
new UNICAST3(),
new STABLE().setValue("max_bytes",50000),
new GMS().setValue("print_local_addr",false)
.setValue("join_timeout", 100)
.setValue("leave_timeout", 100)
.setValue("merge_timeout",5000)
.setValue("log_view_warnings",false)
.setValue("view_ack_collection_timeout",50)
.setValue("log_collect_msgs",false))
.name(name);
if(connect)
retval.connect("MergeTest4");
return retval;
}
protected JChannel findChannel(Address mbr) {
for(JChannel ch: Arrays.asList(a,b,c,d,e,f,g,h,i,j,s,t,u,v)) {
if(ch != null && ch.getAddress() != null && ch.getAddress().equals(mbr))
return ch;
}
return null;
}
protected void injectMergeEvents(List<Message> msgs, JChannel ... channels) {
for(JChannel ch: channels) {
MERGE3 merge=ch.getProtocolStack().findProtocol(MERGE3.class);
msgs.forEach(merge::up);
}
}
protected void discard(boolean flag, JChannel ... channels) throws Exception {
for(JChannel ch: channels) {
ProtocolStack stack=ch.getProtocolStack();
DISCARD discard=stack.findProtocol(DISCARD.class);
if(discard == null)
stack.insertProtocol(discard=new DISCARD(), ProtocolStack.Position.ABOVE, stack.getTransport().getClass());
discard.setDiscardAll(flag);
}
}
protected void injectView(View view, JChannel ... channels) {
for(JChannel ch: channels) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
gms.installView(view);
}
}
protected void checkInconsistencies(JChannel ... channels) {
for(JChannel ch: channels) {
MERGE3 merge=ch.getProtocolStack().findProtocol(MERGE3.class);
merge.checkInconsistencies();
}
}
protected View getViewFromGMS(JChannel ch) {
GMS gms=ch.getProtocolStack().findProtocol(GMS.class);
return gms.view();
}
protected List<Address> getMembers(JChannel ... channels) {
List<Address> members=new ArrayList<>(channels.length);
for(JChannel ch: channels)
members.add(ch.getAddress());
return members;
}
protected void enableInfoSender(boolean enable, JChannel... channels) throws Exception {
for(JChannel ch: channels) {
MERGE3 merge=ch.getProtocolStack().findProtocol(MERGE3.class);
Method meth=enable? startInfoSender : stopInfoSender;
meth.invoke(merge);
}
}
@Test(enabled=false)
public static void main(String[] args) throws Exception {
MergeTest4 test=new MergeTest4();
test.setUp();
test.testMergeWithAsymetricViewsCoordIsolated();
test.tearDown();
}
}