package org.jgroups.protocols.pbcast; import org.jgroups.Address; import org.jgroups.Global; import org.jgroups.View; import org.jgroups.ViewId; import org.jgroups.util.Digest; import org.jgroups.util.MutableDigest; import org.jgroups.util.Streamable; import org.jgroups.util.Util; import java.io.DataInput; import java.io.DataOutput; import java.util.ArrayList; import java.util.List; /** * Result of a JOIN request (sent by the GMS client). Instances of this class are immutable. */ public class JoinRsp implements Streamable { private View view=null; private Digest digest=null; /** only set if JOIN failed, e.g. in AUTH */ private String fail_reason=null; protected static final byte VIEW_PRESENT = 1 << 0; protected static final byte DIGEST_PRESENT = 1 << 1; protected static final byte FAIL_REASON_PRESENT = 1 << 2; public JoinRsp() { } public JoinRsp(View v, Digest d) { view=v; digest=d; } public JoinRsp(String fail_reason) { this.fail_reason=fail_reason; } public View getView() { return view; } public Digest getDigest() { return digest; } public String getFailReason() { return fail_reason; } public void setFailReason(String r) { fail_reason=r; } public void writeTo(DataOutput out) throws Exception { byte flags=0; if(view != null) flags|=VIEW_PRESENT; if(digest != null) flags|=DIGEST_PRESENT; if(fail_reason != null) flags|=FAIL_REASON_PRESENT; out.writeByte(flags); // 1. View: viewId int size=0; if(view != null) { view.getViewId().writeTo(out); size=view.size(); // 2. View: members out.writeShort(size); // we'll never have more than a couple of 1000 members ! for(Address mbr: view) Util.writeAddress(mbr, out); } // 3. Digest if(digest != null && view != null) { // if digest is present, view *has* to be present ! for(Address mbr: view) { long[] seqnos=digest.get(mbr); if(seqnos == null) seqnos=new long[]{-1, -1}; Util.writeLongSequence(seqnos[0], seqnos[1], out); } } // 4. fail_reason if(fail_reason != null) out.writeUTF(fail_reason); } public void readFrom(DataInput in) throws Exception { byte flags=in.readByte(); int size=0; List<Address> members=null; if((flags & VIEW_PRESENT) == VIEW_PRESENT) { // 1. View: viewId ViewId vid=new ViewId(); vid.readFrom(in); // 2. View: members size=in.readShort(); members=new ArrayList<Address>(size); for(int i=0; i < size; i++) { Address mbr=Util.readAddress(in); members.add(mbr); } view=new View(vid, members); } // 3. Digest if(members != null && (flags & DIGEST_PRESENT) == DIGEST_PRESENT) { MutableDigest tmp=new MutableDigest(size); for(int i=0; i < size; i++) { Address mbr=members.get(i); long[] seqnos=Util.readLongSequence(in); if(seqnos[0] == -1 && seqnos[1] == -1) continue; tmp.add(mbr, seqnos[0], seqnos[1], false); } digest=tmp; } // 4. fail_reason if((flags & FAIL_REASON_PRESENT) == FAIL_REASON_PRESENT) fail_reason=in.readUTF(); } public int serializedSize() { int retval=Global.BYTE_SIZE; // 'flags' byte if(view != null) { retval+=view.getVid().serializedSize(); retval+=Global.SHORT_SIZE; // size for(Address mbr: view) retval+=Util.size(mbr); } if(digest != null) { for(Digest.DigestEntry entry: digest) retval+=Util.size(entry.getHighestDeliveredSeqno(), entry.getHighestReceivedSeqno()); } if(fail_reason != null) retval+=fail_reason.length() +2; return retval; } public String toString() { StringBuilder sb=new StringBuilder(); sb.append("view: "); if(view == null) sb.append("<null>"); else sb.append(view); sb.append(", digest: "); if(digest == null) sb.append("<null>"); else sb.append(digest); if(fail_reason != null) sb.append(", fail reason: ").append(fail_reason); return sb.toString(); } }