protected Object installView(byte[] buf, int offset, int length) { try { ViewData data=Util.streamableFromByteBuffer(ViewData::new, buf, offset, length); if(data.uuids != null) NameCache.add(data.uuids); remote_view=data.remote_view; if(global_view == null || (data.global_view != null &&!global_view.equals(data.global_view))) { global_view=data.global_view; synchronized(this) { if(data.global_view.getViewId().getId() > global_view_id) global_view_id=data.global_view.getViewId().getId(); } if(present_global_views) return up_prot.up(new Event(Event.VIEW_CHANGE, global_view)); } } catch(Exception e) { log.error(Util.getMessage("FailedInstallingView"), e); } return null; }
public void readFrom(DataInput in) throws Exception { view_id=new ViewId(); view_id.readFrom(in); ref_view_id=new ViewId(); ref_view_id.readFrom(in); left_members=Util.readAddresses(in); new_members=Util.readAddresses(in); }
/** Adds received INFO to views hashmap */ protected void addInfo(Address sender, ViewId view_id, String logical_name, PhysicalAddress physical_addr) { if(logical_name != null && sender instanceof UUID) NameCache.add(sender, logical_name); if(physical_addr != null) down(new Event(Event.ADD_PHYSICAL_ADDRESS, new Tuple<>(sender, physical_addr))); synchronized(views) { ViewId existing=views.get(sender); if(existing == null || existing.compareTo(view_id) < 0) views.put(sender, view_id); } }
protected View generateGlobalView(View local_view, View remote_view, boolean merge) { List<View> views=new ArrayList<>(2); if(local_view != null) views.add(local_view); if(remote_view != null) views.add(remote_view); Collections.sort(views, (v1, v2) -> { ViewId vid1=v1.getViewId(), vid2=v2.getViewId(); Address creator1=vid1.getCreator(), creator2=vid2.getCreator(); int rc=creator1.compareTo(creator2); if(rc != 0) return rc; long id1=vid1.getId(), id2=vid2.getId(); return id1 > id2 ? 1 : id1 < id2? -1 : 0; }); List<Address> combined_members=new ArrayList<>(); for(View view: views) combined_members.addAll(view.getMembers()); long new_view_id; synchronized(this) { new_view_id=global_view_id++; } Address view_creator=combined_members.isEmpty()? local_addr : combined_members.get(0); if(merge) return new MergeView(view_creator, new_view_id, combined_members, views); else return new View(view_creator, new_view_id, combined_members); }
ViewId vid=new_view.getViewId(); List<Address> mbrs=new_view.getMembers(); ltime=Math.max(vid.getId(), ltime); // compute the logical time, regardless of whether the view is accepted if(view != null && vid.compareToIDs(view.getViewId()) <= 0) return; log.warn("%s: not member of view %s; discarding it", local_addr, new_view.getViewId()); return; log.debug("%s: installing view %s", local_addr, new_view); view_event=new Event(Event.VIEW_CHANGE, new_view); down_prot.down(view_event); // needed e.g. by failure detector or UDP up_prot.up(view_event); List<Address> tmp_mbrs=new_view.getMembers();
public Object up(Message msg) { GmsHeader hdr=msg.getHeader(this.id); if(hdr == null) return up_prot.up(msg); if (viewId != null && new_view.getViewId().compareToIDs(viewId) <= 0) return null; if(new_view instanceof DeltaView) { try { log.trace("%s: received delta view %s", local_addr, new_view); new_view=createViewFromDeltaView(view,(DeltaView)new_view); if(!new_view.containsMember(coord)) { Digest digest=(Digest)down_prot.down(new Event(Event.GET_DIGEST, local_addr)); if(digest != null) { Message get_digest_rsp=new Message(msg.getSrc()) if(view_id != null) { ViewId my_view_id=this.view != null? this.view.getViewId() : null; if(my_view_id != null && my_view_id.compareToIDs(view_id) <= 0) return null; // my view-id doesn't differ from sender's view-id; no need to send view if(log.isErrorEnabled()) log.error(Util.getMessage("GmsHeaderWithType"), hdr.type);
protected void handleStabilityMessage(final Digest stable_digest, final Address sender, final ViewId view_id) { if(stable_digest == null) { if(log.isErrorEnabled()) log.error(Util.getMessage("StabilityDigestIsNull")); return; log.trace("%s: STABLE message is ignored: initialized=%b, suspended=%b", local_addr, initialized, suspended); return; if(!view_id.equals(this.view.getViewId())) { log.trace("%s: discarded STABILITY message with different view-id %s (my view-id=%s)", local_addr, view_id, view); down_prot.down(new Event(Event.STABLE, stable_digest)); // pass STABLE down, so NAKACK{2} can purge stable messages
Address coord; int rc; ViewId vid=new_view.getVid(); Vector mbrs=new_view.getMembers(); rc=vid.compareTo(view_id); if(rc <= 0) { if(log.isWarnEnabled() && rc < 0) // only scream if view is smaller, silently discard same views ltime=Math.max(vid.getId(), ltime); // compute Lamport logical time if(impl != null) impl.handleExit(); up_prot.up(new Event(Event.EXIT)); view=new View(new_view.getVid(), new_view.getMembers()); else view=new_view; view_id=vid.copy(); Event view_event=new Event(Event.VIEW_CHANGE, new_view.clone()); up_prot.up(view_event); down_prot.down(view_event); // needed e.g. by failure detector or UDP
void addMember(Address mbr) { synchronized(members) { if(mbr != null && !members.contains(mbr)) { Object tmp; View new_view; members.addElement(mbr); tmp=members.clone(); if(log.isTraceEnabled()) log.trace("added " + mbr + ", members=" + tmp); new_view=new View(new ViewId(local_addr, vid++), (Vector)tmp); up_prot.up(new Event(Event.VIEW_CHANGE, new_view)); down_prot.down(new Event(Event.VIEW_CHANGE, new_view)); } } }
View tmp_view=tmp_data.getView(); if(tmp_view != null) { ViewId tmp_vid=tmp_view.getViewId(); if(tmp_vid != null) logical_time=Math.max(logical_time, tmp_vid.getId()); // compute the new view id (max of all vids +1) sub_mbrships.add(new ArrayList<>(tmp_view.getMembers())); logical_time=Math.max(logical_time, v.getViewId().getId()); Address creator=v.getCreator(); if(creator != null && !merged_mbrs.contains(creator)) return null; log.trace("%s: consolidated view=%s\nconsolidated digest=%s", gms.local_addr, new_view, new_digest); return new MergeData(gms.local_addr, new_view, new_digest);
private void handleView(View v, Address sender) { Vector members=v.getMembers(); if(!members.contains(local_addr)) { if(log.isWarnEnabled()) log.warn("discarding view as I (" + local_addr + ") am not member of view (" + v + ")"); return; } ViewId vid=v.getVid(); int rc=vid.compareTo(my_vid); if(rc > 0) { // foreign view is greater than my own view; update my own view ! if(log.isTraceEnabled()) log.trace("view from " + sender + " (" + vid + ") is greater than my own view (" + my_vid + ");" + " will update my own view"); Message view_change=new Message(local_addr, local_addr, null); org.jgroups.protocols.pbcast.GMS.GmsHeader hdr; hdr=new org.jgroups.protocols.pbcast.GMS.GmsHeader(org.jgroups.protocols.pbcast.GMS.GmsHeader.VIEW, v); view_change.putHeader(GMS.name, hdr); up_prot.up(new Event(Event.MSG, view_change)); num_views_adjusted++; } }
protected View createViewFromDeltaView(View current_view, DeltaView delta_view) { if(current_view == null || delta_view == null) throw new IllegalStateException("current view (" + current_view + ") or delta view (" + delta_view + ") is null"); ViewId current_view_id=current_view.getViewId(), delta_ref_view_id=delta_view.getRefViewId(), delta_view_id=delta_view.getViewId(); if(!current_view_id.equals(delta_ref_view_id)) throw new IllegalStateException("the view-id of the delta view ("+delta_ref_view_id+") doesn't match the " + "current view-id ("+current_view_id+"); discarding delta view " + delta_view); List<Address> current_mbrs=current_view.getMembers(); List<Address> left_mbrs=Arrays.asList(delta_view.getLeftMembers()); List<Address> new_mbrs=Arrays.asList(delta_view.getNewMembers()); List<Address> new_mbrship=computeNewMembership(current_mbrs,new_mbrs,left_mbrs,Collections.emptyList()); return new View(delta_view_id, new_mbrship); }
@ManagedOperation(description="Inject a view (example of view string format: A=A/B/C;B=B/C;C=C)") public synchronized void injectView(String newView) { try { log.info("Received request to inject view %s", newView); String[] perNode = newView.split(NODE_VIEWS_SEPARATOR); String thisNodeAddress = getProtocolStack().getChannel().getAddressAsString(); log.info("[channel: %s] Injecting a new view: %s", thisNodeAddress, nodeView); long viewId = getProtocolStack().getChannel().getView().getViewId().getId()+1; List<Address> nodes = new ArrayList<>(); for( Map.Entry<Address, String> entry : NameCache.getContents().entrySet() ) { if( nodeName.equals(entry.getValue()) ){ log.debug("[channel: %s] Found name: <%s> for address: <%s>", entry.getValue(), entry.getKey().toString()); nodes.add( entry.getKey() ); break; View view = new View( nodes.get(0), viewId, nodes);
@Override public void installView(NetView v) { this.view = v; if (this.jgAddress.getVmViewId() < 0) { this.jgAddress.setVmViewId(this.localAddress.getVmViewId()); } List<JGAddress> mbrs = new ArrayList<>(v.size()); mbrs.addAll(v.getMembers().stream().map(JGAddress::new).collect(Collectors.toList())); ViewId vid = new ViewId(new JGAddress(v.getCoordinator()), v.getViewId()); View jgv = new View(vid, new ArrayList<>(mbrs)); logger.trace("installing view into JGroups stack: {}", jgv); this.myChannel.down(new Event(Event.VIEW_CHANGE, jgv)); addressesWithIoExceptionsProcessed.clear(); if (encrypt != null) { encrypt.installView(v); } synchronized (scheduledMcastSeqnos) { for (DistributedMember mbr : v.getCrashedMembers()) { scheduledMcastSeqnos.remove(mbr); } for (DistributedMember mbr : v.getShutdownMembers()) { scheduledMcastSeqnos.remove(mbr); } } }
public void writeTo(DataOutput out) throws Exception { super.writeTo(out); // write subgroups int len=subgroups != null? subgroups.length : 0; out.writeShort(len); if(len == 0) return; for(View v: subgroups) { int index=get(v.getCreator()); out.writeShort(index); // if we don't find the member, write the addres (https://issues.jboss.org/browse/JGRP-1707) if(index < 0) Util.writeAddress(v.getCreator(), out); out.writeLong(v.getViewId().getId()); int num_mbrs=v.size(); out.writeShort(num_mbrs); for(Address mbr: v) { index=get(mbr); out.writeShort(index); if(index < 0) Util.writeAddress(mbr, out); } } }
/** * Computes the next view. Returns a copy that has {@code leavers} and * {@code suspected_mbrs} removed and {@code joiners} added. */ public View getNextView(Collection<Address> joiners, Collection<Address> leavers, Collection<Address> suspected_mbrs) { synchronized(members) { ViewId view_id=view != null? view.getViewId() : null; if(view_id == null) { log.error(Util.getMessage("ViewidIsNull")); return null; // this should *never* happen ! } long vid=Math.max(view_id.getId(), ltime) + 1; ltime=vid; List<Address> mbrs=computeNewMembership(tmp_members.getMembers(), joiners, leavers, suspected_mbrs); Address new_coord=!mbrs.isEmpty()? mbrs.get(0) : local_addr; View v=new View(new_coord, vid, mbrs); // Update membership (see DESIGN for explanation): tmp_members.set(mbrs); // Update joining list (see DESIGN for explanation) if(joiners != null) joiners.stream().filter(tmp_mbr -> !joining.contains(tmp_mbr)).forEach(joining::add); // Update leaving list (see DESIGN for explanations) if(leavers != null) leavers.stream().filter(addr -> !leaving.contains(addr)).forEach(leaving::add); if(suspected_mbrs != null) suspected_mbrs.stream().filter(addr -> !leaving.contains(addr)).forEach(leaving::add); return v; } }
/** * Drops messages to/from other members and then closes the channel. Note that this member won't get excluded from * the view until failure detection has kicked in and the new coord installed the new view */ public static void shutdown(JChannel ch) throws Exception { DISCARD discard=new DISCARD(); discard.setLocalAddress(ch.getAddress()); discard.setDiscardAll(true); ProtocolStack stack=ch.getProtocolStack(); TP transport=stack.getTransport(); stack.insertProtocol(discard,ProtocolStack.Position.ABOVE,transport.getClass()); //abruptly shutdown FD_SOCK just as in real life when member gets killed non gracefully FD_SOCK fd=ch.getProtocolStack().findProtocol(FD_SOCK.class); if(fd != null) fd.stopServerSocket(false); View view=ch.getView(); if(view != null) { ViewId vid=view.getViewId(); List<Address> members=Collections.singletonList(ch.getAddress()); ViewId new_vid=new ViewId(ch.getAddress(),vid.getId() + 1); View new_view=new View(new_vid,members); // inject view in which the shut down member is the only element GMS gms=stack.findProtocol(GMS.class); gms.installView(new_view); } Util.close(ch); }
if (currentView!=null&¤tView.getView().getViewId().equals(header.newViewId)) { update.setObject(new MissingIndexesMessage(Collections.EMPTY_LIST, Collections.EMPTY_LIST)); down_prot.down(new Event(Event.MSG, update)); if (!newViewThread.getCausalView().getViewId().equals(header.newViewId)) return;
public void viewAccepted(View view) { if(bridge_view != null && bridge_view.getViewId().equals(view.getViewId())) return; int prev_members=bridge_view != null? bridge_view.size() : 0; bridge_view=view; switch(view.size()) { case 1: // the remote cluster disappeared, remove all of its addresses from the view if(prev_members > 1 && view.getCoord().equals(bridge.getAddress())) { remote_view=null; View new_global_view=generateGlobalView(local_view, null); sendViewOnLocalCluster(null, new_global_view, false, null); } break; case 2: startRemoteViewFetcher(); break; default: // System.err.println("View size of > 2 is invalid: view=" + view); break; } } }