/** * Creates a byte[] representation of the PingData, but DISCARDING the view it contains. * @param data the PingData instance to serialize. * @return */ protected byte[] serializeWithoutView(PingData data) { final PingData clone = new PingData(data.getAddress(), data.isServer(), data.getLogicalName(), data.getPhysicalAddr()).coord(data.isCoord()); try { return Util.streamableToByteBuffer(clone); } catch(Exception e) { log.error(Util.getMessage("ErrorSerializingPingData"), e); return null; } }
protected void readFrom(DataInput in, boolean read_type) throws Exception { if(read_type) type=GossipType.values()[in.readByte()]; group=Bits.readString(in); addr=Util.readAddress(in); sender=Util.readAddress(in); if(type != GossipType.MESSAGE) { logical_name=Bits.readString(in); short len=in.readShort(); if(len > 0) { ping_data=new ArrayList<>(len); for(int i=0; i < len; i++) { PingData data=new PingData(); data.readFrom(in); ping_data.add(data); } } physical_addr=(PhysicalAddress)Util.readAddress(in); } length=in.readInt(); if(length > 0) { buffer=new byte[length]; in.readFully(buffer, offset=0, length); } }
/** Returns all members whose PingData is flagged as coordinator */ private static List<Address> getCoords(Iterable<PingData> mbrs) { if(mbrs == null) return null; List<Address> coords=null; for(PingData mbr: mbrs) { if(mbr.isCoord()) { if(coords == null) coords=new ArrayList<>(); if(!coords.contains(mbr.getAddress())) coords.add(mbr.getAddress()); } } return coords; }
protected void handleDiscoveryResponse(PingData data, Address sender) { // add physical address (if available) to transport's cache Address logical_addr=data.getAddress() != null? data.getAddress() : sender; addDiscoveryResponseToCaches(logical_addr, data.getLogicalName(), data.getPhysicalAddr()); boolean overwrite=Objects.equals(logical_addr, sender); addResponse(data, overwrite); }
protected void write(List<PingData> list, OutputStream out) throws Exception { try { for(PingData data: list) { String logical_name=data.getLogicalName(); Address addr=data.getAddress(); PhysicalAddress phys_addr=data.getPhysicalAddr(); if(logical_name == null || addr == null || phys_addr == null) continue; out.write(logical_name.getBytes()); out.write(WHITESPACE); out.write(addressAsString(addr).getBytes()); out.write(WHITESPACE); out.write(phys_addr.toString().getBytes()); out.write(WHITESPACE); out.write(data.isCoord()? String.format("T%n").getBytes() : String.format("F%n").getBytes()); } } finally { Util.close(out); } }
public static List<PingData> getDiscoveryResponsesFor(String cluster_name) { if(cluster_name == null) return null; Map<Address,SHARED_LOOPBACK> mbrs=routing_table.get(new AsciiString(cluster_name)); List<PingData> rsps=new ArrayList<>(mbrs != null? mbrs.size() : 0); if(mbrs != null) { for(Map.Entry<Address,SHARED_LOOPBACK> entry: mbrs.entrySet()) { Address addr=entry.getKey(); SHARED_LOOPBACK slp=entry.getValue(); PingData data=new PingData(addr, slp.isServer(), NameCache.get(addr), null).coord(slp.isCoord()); rsps.add(data); } } return rsps; }
if(responses.isEmpty()) { PhysicalAddress physical_addr=(PhysicalAddress)down(new Event(Event.GET_PHYSICAL_ADDRESS,local_addr)); PingData coord_data=new PingData(local_addr, true, NameCache.get(local_addr), physical_addr).coord(is_coord); write(Collections.singletonList(coord_data), cluster_name); return; PingData data=responses.findResponseFrom(local_addr); if(data != null && data.getPhysicalAddr().equals(phys_addr)) { if(data.isCoord() && initial_discovery) responses.clear(); else && !initial_discovery && is_coord && (data == null || !data.isCoord()) && !isInfoWriterRunning()) {
Address logical_addr=data != null? data.getAddress() : msg.src(); addDiscoveryResponseToCaches(logical_addr, data.getLogicalName(), data.getPhysicalAddr()); discoveryRequestReceived(msg.getSrc(), data.getLogicalName(), data.getPhysicalAddr()); addResponse(data, false); Collection<? extends Address> mbrs=data != null? data.mbrs() : null; boolean drop_because_of_rank=use_ip_addrs && max_rank_to_reply > 0 && hdr.initialDiscovery() && Util.getRank(view, local_addr) > max_rank_to_reply; if(drop_because_of_rank || (mbrs != null && !mbrs.contains(local_addr)))
protected void handleGetMembersRequest(Address sender, DataInput in) { GossipData req=readRequest(in, GossipType.GET_MBRS); if(req == null) return; GossipData rsp=new GossipData(GossipType.GET_MBRS_RSP, req.getGroup(), null); Map<Address,Entry> members=address_mappings.get(req.getGroup()); if(members != null) { for(Map.Entry<Address,Entry> entry : members.entrySet()) { Address logical_addr=entry.getKey(); PhysicalAddress phys_addr=entry.getValue().phys_addr; String logical_name=entry.getValue().logical_name; PingData data=new PingData(logical_addr, true, logical_name, phys_addr); rsp.addPingData(data); } } ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(rsp.serializedSize()); try { rsp.writeTo(out); server.send(sender, out.buffer(), 0, out.position()); } catch(Exception ex) { log.error("failed sending %d to %s: %s", GossipType.GET_MBRS_RSP, sender, ex); } }
protected void sendInfoMessage(PingData data) { if(data == null) return; Address target=data.getAddress(); if(local_addr.equals(target)) return; Address dest=data.getPhysicalAddr(); if(dest == null) { log.warn("%s: physical address for %s not found; dropping INFO message to %s", local_addr, target, target); return; } MergeHeader hdr=createInfo(); Message info=new Message(dest).setFlag(Message.Flag.INTERNAL).putHeader(getId(), hdr); down_prot.down(info); }
@Override public void members(List<PingData> mbrs) { PhysicalAddress own_physical_addr=(PhysicalAddress)down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr)); PingData data=new PingData(local_addr, false, org.jgroups.util.NameCache.get(local_addr), own_physical_addr); PingHeader hdr=new PingHeader(PingHeader.GET_MBRS_REQ).clusterName(cluster_name); Set<PhysicalAddress> physical_addrs=mbrs.stream().filter(ping_data -> ping_data != null && ping_data.getPhysicalAddr() != null) .map(PingData::getPhysicalAddr).collect(Collectors.toSet()); for(PhysicalAddress physical_addr: physical_addrs) { if(physical_addr != null && own_physical_addr.equals(physical_addr)) // no need to send the request to myself continue; // the message needs to be DONT_BUNDLE, see explanation above final Message msg=new Message(physical_addr).setFlag(Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE, Message.Flag.OOB) .putHeader(this.id, hdr).setBuffer(marshal(data)); log.trace("%s: sending discovery request to %s", local_addr, msg.getDest()); down_prot.down(msg); } }
public boolean containsResponseFrom(Address mbr) { if(mbr == null) return false; for(int i=0; i < index; i++) { if(ping_rsps[i] != null && mbr.equals(ping_rsps[i].getAddress())) return true; } return false; }
public static String printPingData(List<PingData> rsps) { StringBuilder sb=new StringBuilder(); if(rsps != null) { int total=rsps.size(); int servers=0, clients=0, coords=0; for(PingData rsp : rsps) { if(rsp.isCoord()) coords++; if(rsp.isServer()) servers++; else clients++; } sb.append(total + " total (" + servers + " servers (" + coords + " coord), " + clients + " clients)"); } return sb.toString(); }
protected int[] numResponses() { lock.lock(); try { int[] num={0,0}; for(int i=0; i < index; i++) { PingData data=ping_rsps[i]; num[0]++; if(data.isCoord()) num[1]++; } return num; } finally { lock.unlock(); } }
public void writeTo(DataOutput out) throws Exception { out.writeByte(type.ordinal()); Bits.writeString(group, out); Util.writeAddress(addr, out); Util.writeAddress(sender, out); if(type != GossipType.MESSAGE) { Bits.writeString(logical_name, out); out.writeShort(ping_data != null? ping_data.size() : 0); if(ping_data != null) for(PingData data : ping_data) data.writeTo(out); Util.writeAddress(physical_addr, out); } out.writeInt(buffer != null? length : 0); if(buffer != null) out.write(buffer, offset, length); }
protected void readResponse(GetResponse rsp, List<Address> mbrs, Responses responses) { if(rsp.object == null) return; byte[] buf=rsp.object.data; List<PingData> list; if(buf != null && buf.length > 0) { try { list=read(new ByteArrayInputStream(buf)); if(list != null) { for(PingData data : list) { if(mbrs == null || mbrs.contains(data.getAddress())) responses.addResponse(data, data.isCoord()); if(local_addr != null && !local_addr.equals(data.getAddress())) addDiscoveryResponseToCaches(data.getAddress(), data.getLogicalName(), data.getPhysicalAddr()); } } } catch(Throwable e) { log.error(Util.getMessage("FailedUnmarshallingResponse"), e); } } }
@ManagedOperation(description="Reads logical-physical address mappings and logical name mappings from a " + "file (or URL) and adds them to the local caches") public void addToCache(String filename) throws Exception { InputStream in=ConfiguratorFactory.getConfigStream(filename); List<PingData> list=read(in); if(list != null) for(PingData data: list) addDiscoveryResponseToCaches(data.getAddress(), data.getLogicalName(), data.getPhysicalAddr()); }
@ManagedOperation(description="Reads data from local caches and dumps them to a file") public void dumpCache(String output_filename) throws Exception { Map<Address,PhysicalAddress> cache_contents= (Map<Address,PhysicalAddress>)down_prot.down(new Event(Event.GET_LOGICAL_PHYSICAL_MAPPINGS, false)); List<PingData> list=new ArrayList<>(cache_contents.size()); for(Map.Entry<Address,PhysicalAddress> entry: cache_contents.entrySet()) { Address addr=entry.getKey(); PhysicalAddress phys_addr=entry.getValue(); PingData data=new PingData(addr, true, NameCache.get(addr), phys_addr).coord(addr.equals(local_addr)); list.add(data); } OutputStream out=new FileOutputStream(output_filename); write(list, out); }
public void findMembers(final List<Address> members, final boolean initial_discovery, Responses responses) { try { readAll(members, cluster_name, responses); if(responses.isEmpty()) { PhysicalAddress physical_addr=(PhysicalAddress)down(new Event(Event.GET_PHYSICAL_ADDRESS,local_addr)); PingData coord_data=new PingData(local_addr, true, NameCache.get(local_addr), physical_addr).coord(is_coord); write(Collections.singletonList(coord_data), cluster_name); return; } PhysicalAddress phys_addr=(PhysicalAddress)down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr)); PingData data=responses.findResponseFrom(local_addr); // the logical addr *and* IP address:port have to match if(data != null && data.getPhysicalAddr().equals(phys_addr)) { if(data.isCoord() && initial_discovery) responses.clear(); else ; // use case #1 if we have predefined files: most members join but are not coord } else { sendDiscoveryResponse(local_addr, phys_addr, NameCache.get(local_addr), null, false); } } finally { responses.done(); } }