Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jgroups;
import org.jgroups.annotations.Immutable;
import org.jgroups.util.ArrayIterator;
import org.jgroups.util.SizeStreamable;
import org.jgroups.util.Util;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* A view is a local representation of the current membership of a group. Only one view is installed
* in a channel at a time. Views contain the address of its creator, an ID and a list of member
* addresses. These addresses are ordered, and the first address is always the coordinator of the
* view. This way, each member of the group knows who the new coordinator will be if the current one
* crashes or leaves the group. The views are sent between members using the VIEW_CHANGE event
*
* @since 2.0
* @author Bela Ban
*/
@Immutable
public class View implements Comparable, SizeStreamable, Iterable, Constructable {
/**
* A view is uniquely identified by its ViewID. The view id contains the creator address and a
* Lamport time. The Lamport time is the highest timestamp seen or sent from a view. if a view
* change comes in with a lower Lamport time, the event is discarded.
*/
protected ViewId view_id;
/**
* An array containing all the members of the view. This array is always ordered, with the
* coordinator being the first member. The second member will be the new coordinator if the
* current one disappears or leaves the group.
*/
protected Address[] members;
protected static final boolean suppress_view_size=Boolean.getBoolean(Global.SUPPRESS_VIEW_SIZE);
/**
* Creates an empty view, should not be used, only used by (de-)serialization
*/
public View() {
}
/**
* Creates a new view
*
* @param view_id The view id of this view (can not be null)
* @param members Contains a list of all the members in the view, can be empty but not null.
*/
public View(ViewId view_id, Collection members) {
this.view_id=view_id;
if(members == null)
throw new IllegalArgumentException("members cannot be null");
this.members=new Address[members.size()];
int index=0;
for(Address member: members)
this.members[index++]=member;
}
/**
* Creates a new view.
* @param view_id The new view-id
* @param members The members. Note that the parameter is not copied.
*/
public View(ViewId view_id, Address[] members) {
this.view_id=view_id;
this.members=members;
if(members == null)
throw new IllegalArgumentException("members cannot be null");
}
/**
* Creates a new view
*
* @param creator The creator of this view (can not be null)
* @param id The lamport timestamp of this view
* @param members Contains a list of all the members in the view, can be empty but not null.
*/
public View(Address creator, long id, List members) {
this(new ViewId(creator, id), members);
}
public static View create(Address coord, long id, Address ... members) {
return new View(new ViewId(coord, id), members);
}
public static View create(Address coord, long id, Collection members) {
return new View(new ViewId(coord, id), members);
}
public Supplier extends View> create() {
return View::new;
}
/**
* Returns the view ID of this view
* if this view was created with the empty constructur, null will be returned
* @return the view ID of this view
*/
public ViewId getViewId() {return view_id;}
/**
* Returns the creator of this view
* if this view was created with the empty constructur, null will be returned
* @return the creator of this view in form of an Address object
*/
public Address getCreator() {return view_id.getCreator();}
public Address getCoord() {return members.length > 0? members[0] : null;}
/**
* Returns the member list
* @return an immutable list of the members
*/
public List getMembers() {
return Collections.unmodifiableList(Arrays.asList(members));
}
/** Returns the underlying array. The caller must not modify the contents. Should not be used by
* application code ! This method may be removed at any time, so don't use it !
*/
public Address[] getMembersRaw() {
return members;
}
/**
* Returns true if this view contains a certain member
* @param mbr - the address of the member,
* @return true if this view contains the member, false if it doesn't
*/
public boolean containsMember(Address mbr) {
if(mbr == null || members == null)
return false;
for(Address member: members)
if(Objects.equals(member, mbr))
return true;
return false;
}
/** Returns true if all mbrs are elements of this view, false otherwise */
public boolean containsMembers(Address ... mbrs) {
if(mbrs == null || members == null)
return false;
for(Address mbr: mbrs) {
if(!containsMember(mbr))
return false;
}
return true;
}
public int compareTo(View o) {
return view_id.compareTo(o.view_id);
}
public boolean equals(Object obj) {
return obj instanceof View && (this == obj || compareTo((View)obj) == 0);
}
public boolean deepEquals(View other) {
return this == other || equals(other) && Arrays.equals(members, other.members);
}
public int hashCode() {
return view_id.hashCode();
}
/**
* Returns the number of members in this view
* @return the number of members in this view 0..n
*/
public int size() {
return members.length;
}
public String toString() {
StringBuilder sb=new StringBuilder(64);
sb.append(view_id);
if(members != null) {
if(!suppress_view_size)
sb.append(" (").append(members.length).append(")");
sb.append(" [").append(Util.printListWithDelimiter(members,", ",Util.MAX_LIST_PRINT_SIZE)).append("]");
}
return sb.toString();
}
@Override
public void writeTo(DataOutput out) throws IOException {
view_id.writeTo(out);
Util.writeAddresses(members,out);
}
@Override
public void readFrom(DataInput in) throws IOException, ClassNotFoundException {
view_id=new ViewId();
view_id.readFrom(in);
members=Util.readAddresses(in);
}
@Override
public int serializedSize() {
return (int)(view_id.serializedSize() + Util.size(members));
}
/**
* Returns a list of members which left from view one to two
* @param one
* @param two
*/
public static List leftMembers(View one, View two) {
if(one == null || two == null)
return null;
List retval=new ArrayList<>(one.getMembers());
retval.removeAll(two.getMembers());
return retval;
}
public static List newMembers(View old, View new_view) {
if(old == null || new_view == null)
return null;
List retval=new ArrayList<>(new_view.getMembers());
retval.removeAll(old.getMembers());
return retval;
}
/**
* Returns the difference between 2 views from and to. It is assumed that view 'from' is logically prior to view 'to'.
* @param from The first view
* @param to The second view
* @return an array of 2 Address arrays: index 0 has the addresses of the joined member, index 1 those of the left members
*/
public static Address[][] diff(final View from, final View to) {
if(to == null)
throw new IllegalArgumentException("the second view cannot be null");
if(from == to)
return new Address[][]{{},{}};
if(from == null) {
Address[] joined=new Address[to.size()];
int index=0;
for(Address addr: to.getMembers())
joined[index++]=addr;
return new Address[][]{joined,{}};
}
Address[] joined=null, left=null;
int num_joiners=0, num_left=0;
// determine joiners
for(Address addr: to)
if(!from.containsMember(addr))
num_joiners++;
if(num_joiners > 0) {
joined=new Address[num_joiners];
int index=0;
for(Address addr: to)
if(!from.containsMember(addr))
joined[index++]=addr;
}
// determine leavers
for(Address addr: from)
if(!to.containsMember(addr))
num_left++;
if(num_left > 0) {
left=new Address[num_left];
int index=0;
for(Address addr: from)
if(!to.containsMember(addr))
left[index++]=addr;
}
return new Address[][]{joined != null? joined : new Address[]{}, left != null? left : new Address[]{}};
}
public static String printDiff(Address[][] diff) {
if(diff == null)
return "";
Address[] joined=diff[0], left=diff[1];
if(joined.length == 0 && left.length == 0)
return "";
if(joined.length > 0 && left.length > 0)
return String.format("(%s joined, %s left)", Util.print(joined), Util.print(left));
if(joined.length > 0)
return String.format("(%s joined)", Util.print(joined));
if(left.length > 0)
return String.format("(%s left)", Util.print(left));
return "";
}
/** Returns true if all views are the same. Uses the view IDs for comparison */
public static boolean sameViews(View ... views) {
ViewId first_view_id=views[0].getViewId();
return Stream.of(views).allMatch(v -> v.getViewId().equals(first_view_id));
}
public static boolean sameViews(Collection views) {
ViewId first_view_id=views.iterator().next().getViewId();
return views.stream().allMatch(v -> v.getViewId().equals(first_view_id));
}
/** Checks if two views have the same members regardless of order. E.g. {A,B,C} and {B,A,C} returns true */
public static boolean sameMembers(View v1, View v2) {
if(v1 == v2)
return true;
if(v1.size() != v2.size())
return false;
Address[][] diff=diff(v1, v2);
return diff[0].length == 0 && diff[1].length == 0;
}
/** Checks if two views have the same members observing order. E.g. {A,B,C} and {B,A,C} returns false,
* {A,C,B} and {A,C,B} returns true */
public static boolean sameMembersOrdered(View v1, View v2) {
return Arrays.equals(v1.getMembersRaw(), v2.getMembersRaw());
}
public Iterator iterator() {
return new ArrayIterator(this.members);
}
}