org.jgroups.protocols.relay.RelayHeader Maven / Gradle / Ivy
package org.jgroups.protocols.relay;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.Header;
import org.jgroups.util.Bits;
import org.jgroups.util.Headers;
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;
/**
* Header for {@link RELAY2} and {@link RELAY3}
* @author Bela Ban
* @since 5.2.15
*/
public class RelayHeader extends Header {
public static final byte DATA = 1;
public static final byte SITE_UNREACHABLE = 2; // final_dest is a SiteMaster
public static final byte MBR_UNREACHABLE = 3; // sent back when a given member is not part of the local cluster
public static final byte SITES_UP = 4;
public static final byte SITES_DOWN = 5;
public static final byte TOPO_REQ = 6;
public static final byte TOPO_RSP = 7; // View is the payload of the response message (site: hdr.sites)
protected byte type;
protected Address final_dest;
protected Address original_sender;
protected Set sites; // used with SITES_UP/SITES_DOWN/TOPO_RSP
// used to record sites to which this msg was already sent (https://issues.redhat.com/browse/JGRP-1519)
protected Set visited_sites;
// used with TOPO_REQ: when set, return the entire cache, otherwise only information about the local members
protected boolean return_entire_cache;
// marshalled headers (https://issues.redhat.com/browse/JGRP-2729),
// changed in https://issues.redhat.com/browse/JGRP-2744
protected Header[] original_hdrs;
protected short original_flags;
public RelayHeader() {
}
public RelayHeader(byte type) {
this.type=type;
}
public RelayHeader(byte type, Address final_dest, Address original_sender) {
this(type);
this.final_dest=final_dest;
this.original_sender=original_sender;
}
public short getMagicId() {return 80;}
public Supplier extends Header> create() {return RelayHeader::new;}
public byte getType() {return type;}
public Address getFinalDest() {return final_dest;}
public RelayHeader setFinalDestination(Address d) {final_dest=d; return this;}
public Address getOriginalSender() {return original_sender;}
public RelayHeader setOriginalSender(Address s) {original_sender=s; return this;}
public Set getSites() {return sites != null? new HashSet<>(sites) : null;}
public boolean hasSites() {return sites != null && !sites.isEmpty();}
public boolean returnEntireCache() {return return_entire_cache;}
public RelayHeader returnEntireCache(boolean b) {return_entire_cache=b; return this;}
public Header[] originalHeaders() {return original_hdrs;}
public RelayHeader originalHeaders(Header[] hdrs) {original_hdrs=hdrs; return this;}
public short originalFlags() {return original_flags;}
public RelayHeader originalFlags(short fl) {original_flags=fl; return this;}
public String getSite() {
if(sites == null || sites.isEmpty())
return null;
Iterator it=sites.iterator();
return it.hasNext()? it.next() : null;
}
public RelayHeader addToSites(Collection s) {
if(s != null) {
if(this.sites == null)
this.sites=new HashSet<>(s.size());
this.sites.addAll(s);
}
assertNonNullSites();
return this;
}
public RelayHeader addToSites(String ... s) {
if(s != null && s.length > 0) {
if(this.sites == null)
this.sites=new HashSet<>();
this.sites.addAll(Arrays.asList(s));
}
assertNonNullSites();
return this;
}
public RelayHeader addToVisitedSites(String s) {
if(visited_sites == null)
visited_sites=new HashSet<>();
visited_sites.add(s);
return this;
}
public RelayHeader addToVisitedSites(Collection list) {
if(list == null || list.isEmpty())
return this;
for(String s: list)
addToVisitedSites(s);
return this;
}
public boolean hasVisitedSites() {return visited_sites != null && !visited_sites.isEmpty();}
public Set getVisitedSites() {return visited_sites;}
public RelayHeader copy() {
RelayHeader hdr=new RelayHeader(type, final_dest, original_sender)
.addToSites(this.sites)
.addToVisitedSites(visited_sites).returnEntireCache(return_entire_cache)
.originalHeaders(this.original_hdrs).originalFlags(this.original_flags);
assertNonNullSites();
hdr.assertNonNullSites();
return hdr;
}
@Override
public int serializedSize() {
assertNonNullSites();
return Global.BYTE_SIZE*2 + Util.size(final_dest) + Util.size(original_sender) +
sizeOf(sites) + sizeOf(visited_sites) +
Short.BYTES /* num headers */ + Headers.marshalledSize(original_hdrs)
+ Short.BYTES; // orig-flags
}
@Override
public void writeTo(DataOutput out) throws IOException {
out.writeByte(type);
out.writeBoolean(return_entire_cache);
Util.writeAddress(final_dest, out);
Util.writeAddress(original_sender, out);
out.writeInt(sites == null? 0 : sites.size());
if(sites != null) {
for(String s: sites)
Bits.writeString(s, out);
}
out.writeInt(visited_sites == null? 0 : visited_sites.size());
if(visited_sites != null) {
for(String s: visited_sites)
Bits.writeString(s, out);
}
assertNonNullSites();
Headers.writeHeaders(original_hdrs, out);
out.writeShort(original_flags);
}
@Override
public void readFrom(DataInput in) throws IOException, ClassNotFoundException {
type=in.readByte();
return_entire_cache=in.readBoolean();
final_dest=Util.readAddress(in);
original_sender=Util.readAddress(in);
int num_elements=in.readInt();
if(num_elements > 0) {
sites=new HashSet<>(num_elements);
for(int i=0; i < num_elements; i++)
sites.add(Bits.readString(in));
}
num_elements=in.readInt();
if(num_elements > 0) {
visited_sites=new HashSet<>(num_elements);
for(int i=0; i < num_elements; i++)
visited_sites.add(Bits.readString(in));
}
assertNonNullSites();
original_hdrs=Headers.readHeaders(in);
original_flags=in.readShort();
}
public String toString() {
return String.format("%s [final dest=%s, original sender=%s%s%s]",
typeToString(type), final_dest, original_sender,
sites == null || sites.isEmpty()? "" : String.format(", sites=%s", sites),
visited_sites == null || visited_sites.isEmpty()? "" :
String.format(", visited=%s", visited_sites));
}
protected static String typeToString(byte type) {
switch(type) {
case DATA: return "DATA";
case SITE_UNREACHABLE: return "SITE_UNREACHABLE";
case MBR_UNREACHABLE: return "MBR_UNREACHABLE";
case SITES_UP: return "SITES_UP";
case SITES_DOWN: return "SITES_DOWN";
case TOPO_REQ: return "TOPO_REQ";
case TOPO_RSP: return "TOPO_RSP";
default: return "";
}
}
protected static int sizeOf(Collection list) {
int retval=Global.INT_SIZE; // number of elements
if(list != null) {
for(String s: list)
retval+=Bits.sizeUTF(s) + 1; // presence bytes
}
return retval;
}
protected void assertNonNullSites() {
if(type == SITES_UP || type == SITES_DOWN) {
if(sites == null)
throw new IllegalStateException(String.format("sites cannot be null with type %s\n", type));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy