/** * Invoked upon receiving a MERGE event from the MERGE layer. Starts the merge protocol. See * description of protocol in DESIGN. * * @param views A List of <em>different</em> views detected by the merge protocol */ public void merge(Map<Address, View> views) { if (isMergeInProgress()) { if (log.isTraceEnabled()) log.trace(gms.local_addr + ": merge is already running (merge_id=" + merge_id + ")"); return; } // we need the merge *coordinators* not merge participants because not everyone can lead a merge // ! Collection<Address> coords = Util.determineMergeCoords(views); Collection<Address> merge_participants = Util.determineMergeParticipants(views); Membership tmp = new Membership(coords); // establish a deterministic order, so that coords can elect leader tmp.sort(); Address merge_leader = tmp.elementAt(0); if (log.isDebugEnabled()) log.debug("determining merge leader from " + merge_participants); if (merge_leader.equals(gms.local_addr)) { if (log.isDebugEnabled()) log.debug( "I (" + gms.local_addr + ") will be the leader. Starting the merge task for " + merge_participants); merge_task.start(views); } else { if (log.isDebugEnabled()) log.debug( "I (" + gms.local_addr + ") am not the merge leader, " + "waiting for merge leader (" + merge_leader + ") to initiate merge"); } }
/** Execute when new member join or leave Group */ public void viewAccepted(View v) { memberSize = v.size(); if (mainFrame != null) setTitle(); members.clear(); members.addAll(v.getMembers()); if (v instanceof MergeView) { System.out.println("** " + v); // This is a simple merge function, which fetches the state from the coordinator // on a merge and overwrites all of its own state if (useState && !members.isEmpty()) { Address coord = members.get(0); Address local_addr = channel.getAddress(); if (local_addr != null && !local_addr.equals(coord)) { try { // make a copy of our state first Map<Point, Color> copy = null; if (send_own_state_on_merge) { synchronized (drawPanel.state) { copy = new LinkedHashMap<Point, Color>(drawPanel.state); } } System.out.println("fetching state from " + coord); channel.getState(coord, 5000); if (copy != null) sendOwnState(copy); // multicast my own state so everybody else has it too } catch (Exception e) { e.printStackTrace(); } } } } else System.out.println("** View=" + v); }
public Object down(Message msg) { Address dest = msg.getDest(); boolean multicast = dest == null; if (msg.getSrc() == null) msg.setSrc(localAddress()); if (discard_all) { if (dest == null || dest.equals(localAddress())) loopback(msg); return null; } if (!multicast && drop_down_unicasts > 0) { drop_down_unicasts = Math.max(0, drop_down_unicasts - 1); return null; } if (multicast && drop_down_multicasts > 0) { drop_down_multicasts = Math.max(0, drop_down_multicasts - 1); return null; } if (down > 0) { double r = Math.random(); if (r < down) { if (excludeItself && dest != null && dest.equals(localAddress())) { if (log.isTraceEnabled()) log.trace("excluding itself"); } else { log.trace("dropping message"); num_down++; return null; } } } return down_prot.down(msg); }
/** * Send all fragments as separate messages (with same ID !). Example: * * <pre> * Given the generated ID is 2344, number of fragments=3, message {dst,src,buf} * would be fragmented into: * * [2344,3,0]{dst,src,buf1}, * [2344,3,1]{dst,src,buf2} and * [2344,3,2]{dst,src,buf3} * </pre> */ private void fragment(Message msg) { try { byte[] buffer = msg.getRawBuffer(); List<Range> fragments = Util.computeFragOffsets(msg.getOffset(), msg.getLength(), frag_size); int num_frags = fragments.size(); num_sent_frags.addAndGet(num_frags); if (log.isTraceEnabled()) { Address dest = msg.getDest(); StringBuilder sb = new StringBuilder("fragmenting packet to "); sb.append((dest != null ? dest.toString() : "<all members>")) .append(" (size=") .append(buffer.length); sb.append(") into ") .append(num_frags) .append(" fragment(s) [frag_size=") .append(frag_size) .append(']'); log.trace(sb.toString()); } long frag_id = getNextId(); // used as a seqno for (int i = 0; i < fragments.size(); i++) { Range r = fragments.get(i); // don't copy the buffer, only src, dest and headers. Only copy the headers one time ! Message frag_msg = msg.copy(false, i == 0); frag_msg.setBuffer(buffer, (int) r.low, (int) r.high); FragHeader hdr = new FragHeader(frag_id, i, num_frags); frag_msg.putHeader(this.id, hdr); down_prot.down(new Event(Event.MSG, frag_msg)); } } catch (Exception e) { if (log.isErrorEnabled()) log.error("fragmentation failure", e); } }
/** Checks if a message should be passed up, or not */ protected boolean shouldDropUpMessage( @SuppressWarnings("UnusedParameters") Message msg, Address sender) { if (discard_all && !sender.equals(localAddress())) return true; if (ignoredMembers.contains(sender)) { if (log.isTraceEnabled()) log.trace(localAddress + ": dropping message from " + sender); num_up++; return true; } if (up > 0) { double r = Math.random(); if (r < up) { if (excludeItself && sender.equals(localAddress())) { if (log.isTraceEnabled()) log.trace("excluding myself"); } else { if (log.isTraceEnabled()) log.trace(localAddress + ": dropping message from " + sender); num_up++; return true; } } } return false; }
public void sendGetMembersRequest(String cluster_name, Promise promise, boolean return_views_only) throws Exception { PhysicalAddress physical_addr = (PhysicalAddress) down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr)); PingData data = new PingData(local_addr, null, false, UUID.get(local_addr), Arrays.asList(physical_addr)); PingHeader hdr = new PingHeader(PingHeader.GET_MBRS_REQ, data, cluster_name); hdr.return_view_only = return_views_only; Set<PhysicalAddress> combined_target_members = new HashSet<PhysicalAddress>(initial_hosts); combined_target_members.addAll(dynamic_hosts); for (final Address addr : combined_target_members) { if (addr.equals(physical_addr)) continue; final Message msg = new Message(addr, null, null); msg.setFlag(Message.OOB); msg.putHeader(this.id, hdr); if (log.isTraceEnabled()) log.trace("[FIND_INITIAL_MBRS] sending PING request to " + msg.getDest()); timer.execute( new Runnable() { public void run() { try { down_prot.down(new Event(Event.MSG, msg)); } catch (Exception ex) { if (log.isErrorEnabled()) log.error("failed sending discovery request to " + addr + ": " + ex); } } }); } }
protected void deliver(Message msg, Event evt, SequencerHeader hdr) { Address sender = msg.getSrc(); if (sender == null) { if (log.isErrorEnabled()) log.error(local_addr + ": sender is null, cannot deliver " + "::" + hdr.getSeqno()); return; } long msg_seqno = hdr.getSeqno(); if (sender.equals(local_addr)) { forward_table.remove(msg_seqno); if (hdr.flush_ack) { ack_promise.setResult(msg_seqno); if (ack_mode && !flushing && threshold > 0 && ++num_acks >= threshold) { ack_mode = false; num_acks = 0; } } } if (!canDeliver(sender, msg_seqno)) { if (log.isWarnEnabled()) log.warn(local_addr + ": dropped duplicate message " + sender + "::" + msg_seqno); return; } if (log.isTraceEnabled()) log.trace(local_addr + ": delivering " + sender + "::" + msg_seqno); up_prot.up(evt); delivered_bcasts++; }
/** Checks whether the potential_new_coord would be the new coordinator (2nd in line) */ protected boolean wouldBeNewCoordinator(Address potential_new_coord) { if (potential_new_coord == null) return false; synchronized (members) { if (members.size() < 2) return false; Address new_coord = members.elementAt(1); // member at 2nd place return new_coord != null && new_coord.equals(potential_new_coord); } }
protected void handleView(View view) { view_size = view.size(); Address tmp = Util.pickNext(view.getMembers(), local_addr); if (tmp != null && !tmp.equals(local_addr)) { next = tmp; if (log.isDebugEnabled()) log.debug("next=" + next); } }
// If we're becoming coordinator, we need to handle TMP_VIEW as // an immediate change of view. See JGRP-1452. private void handleTmpView(View v) { List<Address> mbrs = v.getMembers(); if (mbrs.isEmpty()) return; Address new_coord = mbrs.get(0); if (!new_coord.equals(coord) && local_addr != null && local_addr.equals(new_coord)) handleViewChange(v); }
void handleMessage(Message msg) { Event evt; UdpHeader hdr; // discard my own multicast loopback copy if (loopback) { Address dst = msg.getDest(); Address src = msg.getSrc(); if (dst != null && dst.isMulticastAddress() && src != null && local_addr.equals(src)) { if (Trace.debug) { Trace.info("UDP.handleMessage()", "discarded own loopback multicast packet"); } return; } } evt = new Event(Event.MSG, msg); if (Trace.debug) { Trace.info("UDP.handleMessage()", "message is " + msg + ", headers are " + msg.getHeaders()); /* Because Protocol.up() is never called by this bottommost layer, we call up() directly in the observer. * This allows e.g. PerfObserver to get the time of reception of a message */ } if (observer != null) { observer.up(evt, up_queue.size()); } hdr = (UdpHeader) msg.removeHeader(name); if (hdr != null) { /* Discard all messages destined for a channel with a different name */ String ch_name = null; if (hdr.group_addr != null) { ch_name = hdr.group_addr; // Discard if message's group name is not the same as our group name unless the // message is a diagnosis message (special group name DIAG_GROUP) } if (ch_name != null && group_addr != null && !group_addr.equals(ch_name) && !ch_name.equals(Util.DIAG_GROUP)) { if (Trace.trace) { Trace.warn( "UDP.handleMessage()", "discarded message from different group (" + ch_name + "). Sender was " + msg.getSrc()); } return; } } else { Trace.error("UDP.handleMessage()", "message does not have a UDP header"); } passUp(evt); }
public Object down(Event evt) { switch (evt.getType()) { case Event.TMP_VIEW: case Event.VIEW_CHANGE: handleViewChange((View) evt.getArg()); break; case Event.GET_STATE: Address target; StateTransferInfo info = (StateTransferInfo) evt.getArg(); if (info.target == null) { target = determineCoordinator(); } else { target = info.target; if (target.equals(local_addr)) { log.error("%s: cannot fetch state from myself", local_addr); target = null; } } if (target == null) { log.debug("%s: first member (no state)", local_addr); up_prot.up(new Event(Event.GET_STATE_OK, new StateTransferInfo())); } else { Message state_req = new Message(target) .putHeader(this.id, new StateHeader(StateHeader.STATE_REQ)) .setFlag(Message.Flag.DONT_BUNDLE, Message.Flag.OOB, Message.Flag.SKIP_BARRIER); log.debug("%s: asking %s for state", local_addr, target); // suspend sending and handling of message garbage collection gossip messages, // fixes bugs #943480 and #938584). Wake up when state has been received /*if(log.isDebugEnabled()) log.debug("passing down a SUSPEND_STABLE event"); down_prot.down(new Event(Event.SUSPEND_STABLE, new Long(info.timeout)));*/ waiting_for_state_response = true; start = System.currentTimeMillis(); down_prot.down(new Event(Event.MSG, state_req)); } return null; // don't pass down any further ! case Event.CONFIG: Map<String, Object> config = (Map<String, Object>) evt.getArg(); if (config != null && config.containsKey("flush_supported")) { flushProtocolInStack = true; } break; case Event.SET_LOCAL_ADDRESS: local_addr = (Address) evt.getArg(); break; } return down_prot.down(evt); // pass on to the layer below us }
public void connect() { try { channel.connect("TOTAL_TOKEN_DEMO_GROUP"); } catch (ChannelException e) { e.printStackTrace(); } receiverThread = new ReceiverThread(); receiverThread.start(); Address a = channel.getAddress(); if (a != null) setTitle(a.toString()); else setTitle("Not connected"); control.connected(); }
public void sendDiscoveryRequest(String cluster_name, Promise promise, ViewId view_id) throws Exception { PingData data = null; PhysicalAddress physical_addr = (PhysicalAddress) down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr)); if (view_id == null) { List<PhysicalAddress> physical_addrs = Arrays.asList(physical_addr); data = new PingData(local_addr, null, false, UUID.get(local_addr), physical_addrs); } PingHeader hdr = new PingHeader(PingHeader.GET_MBRS_REQ, data, cluster_name); hdr.view_id = view_id; Collection<PhysicalAddress> cluster_members = fetchClusterMembers(cluster_name); if (cluster_members == null) { Message msg = new Message(null); // multicast msg msg.setFlag(Message.OOB); msg.putHeader(getId(), hdr); sendMcastDiscoveryRequest(msg); } else { if (cluster_members.isEmpty()) { // if we don't find any members, return immediately if (promise != null) promise.setResult(null); } else { for (final Address addr : cluster_members) { if (addr.equals(physical_addr)) // no need to send the request to myself continue; final Message msg = new Message(addr, null, null); msg.setFlag(Message.OOB); msg.putHeader(this.id, hdr); if (log.isTraceEnabled()) log.trace("[FIND_INITIAL_MBRS] sending discovery request to " + msg.getDest()); if (!sendDiscoveryRequestsInParallel()) { down_prot.down(new Event(Event.MSG, msg)); } else { timer.execute( new Runnable() { public void run() { try { down_prot.down(new Event(Event.MSG, msg)); } catch (Exception ex) { if (log.isErrorEnabled()) log.error("failed sending discovery request to " + addr + ": " + ex); } } }); } } } } }
@Override public void channelConnected(Channel channel) { // Validate view String localName = channel.getName(); Address localAddress = channel.getAddress(); for (Address address : channel.getView()) { String name = channel.getName(address); if ((name != null) && name.equals(localName) && !address.equals(localAddress)) { channel.close(); throw JGroupsLogger.ROOT_LOGGER.duplicateNodeName( this.factory.getValue().getProtocolStackConfiguration().getEnvironment().getNodeName()); } } }
/** * Send the cookie first, then the our port number. If the cookie doesn't match the receiver's * cookie, the receiver will reject the connection and close it. */ protected void sendLocalAddress(Address local_addr) throws Exception { try { // write the cookie out.write(cookie, 0, cookie.length); // write the version out.writeShort(Version.version); out.writeShort(local_addr.size()); // address size local_addr.writeTo(out); out.flush(); // needed ? updateLastAccessed(); } catch (Exception ex) { server.socket_factory.close(this.sock); throw ex; } }
/** * An event is to be sent down the stack. The layer may want to examine its type and perform some * action on it, depending on the event's type. If the event is a message MSG, then the layer may * need to add a header to it (or do nothing at all) before sending it down the stack using <code> * PassDown</code>. In case of a GET_ADDRESS event (which tries to retrieve the stack's address * from one of the bottom layers), the layer may need to send a new response event back up the * stack using <code>up_prot.up()</code>. The PING protocol is interested in several different * down events, Event.FIND_INITIAL_MBRS - sent by the GMS layer and expecting a GET_MBRS_OK * Event.TMP_VIEW and Event.VIEW_CHANGE - a view change event Event.BECOME_SERVER - called after * client has joined and is fully working group member Event.CONNECT, Event.DISCONNECT. */ @SuppressWarnings("unchecked") public Object down(Event evt) { switch (evt.getType()) { case Event.FIND_INITIAL_MBRS: // sent by GMS layer case Event.FIND_ALL_VIEWS: // sends the GET_MBRS_REQ to all members, waits 'timeout' ms or until 'num_initial_members' // have been retrieved long start = System.currentTimeMillis(); boolean find_all_views = evt.getType() == Event.FIND_ALL_VIEWS; Promise<JoinRsp> promise = (Promise<JoinRsp>) evt.getArg(); List<PingData> rsps = find_all_views ? findAllViews(promise) : findInitialMembers(promise); long diff = System.currentTimeMillis() - start; if (log.isTraceEnabled()) log.trace("discovery took " + diff + " ms: responses: " + Util.printPingData(rsps)); return rsps; case Event.TMP_VIEW: case Event.VIEW_CHANGE: List<Address> tmp; view = (View) evt.getArg(); if ((tmp = view.getMembers()) != null) { synchronized (members) { members.clear(); members.addAll(tmp); } } current_coord = !members.isEmpty() ? members.get(0) : null; is_coord = current_coord != null && local_addr != null && current_coord.equals(local_addr); return down_prot.down(evt); case Event.BECOME_SERVER: // called after client has joined and is fully working group member down_prot.down(evt); is_server = true; return null; case Event.SET_LOCAL_ADDRESS: local_addr = (Address) evt.getArg(); return down_prot.down(evt); case Event.CONNECT: case Event.CONNECT_WITH_STATE_TRANSFER: case Event.CONNECT_USE_FLUSH: case Event.CONNECT_WITH_STATE_TRANSFER_USE_FLUSH: is_leaving = false; group_addr = (String) evt.getArg(); Object ret = down_prot.down(evt); handleConnect(); return ret; case Event.DISCONNECT: is_leaving = true; handleDisconnect(); return down_prot.down(evt); default: return down_prot.down(evt); // Pass on to the layer below us } }
private synchronized void handleViewChange(View view, boolean makeServer) { if (makeServer) initializeNewSymmetricKey(view instanceof MergeView); // if view is a bit broken set me as keyserver List<Address> members = view.getMembers(); if (members == null || members.isEmpty() || members.get(0) == null) { becomeKeyServer(local_addr, false); return; } // otherwise get keyserver from view controller Address tmpKeyServer = view.getMembers().get(0); // I am keyserver - either first member of group or old key server is no more and // I have been voted new controller if (makeServer || (tmpKeyServer.equals(local_addr))) becomeKeyServer(tmpKeyServer, makeServer); else handleNewKeyServer(tmpKeyServer, view instanceof MergeView); }
// @see java.lang.Object#hashCode() @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((address == null) ? 0 : address.hashCode()); result = prime * result + (int) (requestId ^ (requestId >>> 32)); return result; }
@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, UUID.get(addr), phys_addr).coord(addr.equals(local_addr)); list.add(data); } OutputStream out = new FileOutputStream(output_filename); write(list, out); }
/** Returns true if local_addr is member of mbrs, else false */ protected boolean checkSelfInclusion(Vector mbrs) { Object mbr; if (mbrs == null) return false; for (int i = 0; i < mbrs.size(); i++) { mbr = mbrs.elementAt(i); if (mbr != null && local_addr.equals(mbr)) return true; } return false; }
/** * Send the cookie first, then the our port number. If the cookie doesn't match the receiver's * cookie, the receiver will reject the connection and close it. * * @throws IOException */ private void sendLocalAddress(Address local_addr) throws IOException { // write the cookie out.write(cookie, 0, cookie.length); // write the version out.writeShort(Version.version); local_addr.writeTo(out); out.flush(); // needed ? updateLastAccessed(); }
public void suspect(Address mbr) { if (mbr.equals(gms.local_addr)) { if (log.isWarnEnabled()) log.warn("I am the coord and I'm suspected -- will probably leave shortly"); return; } Collection<Request> suspected = new LinkedHashSet<>(1); suspected.add(new Request(Request.SUSPECT, mbr, true)); handleMembershipChange(suspected); }
/** * Acceptor thread. Continuously accept new connections. Create a new thread for each new * connection and put it in conns. When the thread should stop, it is interrupted by the thread * creator. */ public void run() { while (!srv_sock.isClosed() && !Thread.currentThread().isInterrupted()) { TCPConnection conn = null; Socket client_sock = null; try { client_sock = srv_sock.accept(); conn = new TCPConnection(client_sock); Address peer_addr = conn.getPeerAddress(); mapper.getLock().lock(); try { boolean currentConnectionOpen = mapper.hasOpenConnection(peer_addr); boolean replaceWithNewConnection = false; if (currentConnectionOpen) { replaceWithNewConnection = peer_addr.compareTo(local_addr) > 0; } if (!currentConnectionOpen || replaceWithNewConnection) { mapper.removeConnection(peer_addr); mapper.addConnection(peer_addr, conn); conn.start(mapper.getThreadFactory()); // starts handler thread on this socket } else { Util.close(conn); } } finally { mapper.getLock().unlock(); } } catch (SocketException se) { boolean threadExiting = srv_sock.isClosed() || Thread.currentThread().isInterrupted(); if (threadExiting) { break; } else { if (log.isWarnEnabled()) log.warn("Could not accept connection from peer ", se); Util.close(conn); Util.close(client_sock); } } catch (Exception ex) { if (log.isWarnEnabled()) log.warn("Could not read accept connection from peer " + ex); Util.close(conn); Util.close(client_sock); } } if (log.isTraceEnabled()) log.trace(Thread.currentThread().getName() + " terminated"); }
// @see java.lang.Object#equals(java.lang.Object) @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Owner other = (Owner) obj; if (address == null) { if (other.address != null) return false; } else if (!address.equals(other.address)) return false; return requestId == other.requestId; }
/** * Decrements credits bytes from all elements and add new_credits to member (if non null). The * lowest credit needs to be greater than min_credits. Needs to be called with lock held * * @param member The member to which new_credits are added. NOP if null * @param new_credits Number of bytes to add to member. NOP if 0. */ protected void decrementAndAdd(Address member, long new_credits) { boolean replenish = member != null && new_credits > 0; if (accumulated_credits > 0) { for (Map.Entry<Address, Long> entry : this.credits.entrySet()) { entry.setValue(Math.max(0, entry.getValue().longValue() - accumulated_credits)); if (replenish) { Address tmp = entry.getKey(); if (tmp.equals(member)) entry.setValue(Math.min(max_credits, entry.getValue().longValue() + new_credits)); } } accumulated_credits = 0; } else { if (replenish) { Long val = this.credits.get(member); if (val != null) this.credits.put(member, Math.min(max_credits, val.longValue() + new_credits)); } } }
protected Address getReceiver() { try { List<Address> mbrs = channel.getView().getMembers(); System.out.println("pick receiver from the following members:"); int i = 0; for (Address mbr : mbrs) { if (mbr.equals(channel.getAddress())) System.out.println("[" + i + "]: " + mbr + " (self)"); else System.out.println("[" + i + "]: " + mbr); i++; } System.out.flush(); System.in.skip(System.in.available()); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String tmp = reader.readLine().trim(); int index = Integer.parseInt(tmp); return mbrs.get(index); // index out of bounds caught below } catch (Exception e) { System.err.println("UnicastTest.getReceiver(): " + e); return null; } }
/** * Reads the peer's address. First a cookie has to be sent which has to match my own cookie, * otherwise the connection will be refused */ private Address readPeerAddress(Socket client_sock) throws Exception { int timeout = client_sock.getSoTimeout(); client_sock.setSoTimeout(peer_addr_read_timeout); try { // read the cookie first byte[] input_cookie = new byte[cookie.length]; in.readFully(input_cookie, 0, input_cookie.length); if (!matchCookie(input_cookie)) throw new SocketException( "ConnectionMap.Connection.readPeerAddress(): cookie read by " + getLocalAddress() + " does not match own cookie; terminating connection"); // then read the version short version = in.readShort(); if (!Version.isBinaryCompatible(version)) { if (log.isWarnEnabled()) log.warn( new StringBuilder("packet from ") .append(client_sock.getInetAddress()) .append(':') .append(client_sock.getPort()) .append(" has different version (") .append(Version.print(version)) .append(") from ours (") .append(Version.printVersion()) .append("). This may cause problems") .toString()); } Address client_peer_addr = new IpAddress(); client_peer_addr.readFrom(in); updateLastAccessed(); return client_peer_addr; } finally { client_sock.setSoTimeout(timeout); } }
/** * Send all fragments as separate messages (with same ID !). Example: * * <pre> * Given the generated ID is 2344, number of fragments=3, message {dst,src,buf} * would be fragmented into: * <p/> * [2344,3,0]{dst,src,buf1}, * [2344,3,1]{dst,src,buf2} and * [2344,3,2]{dst,src,buf3} * </pre> */ private void fragment(Message msg, long size) { Address dest = msg.getDest(), src = msg.getSrc(); long frag_id = curr_id.getAndIncrement(); // used as seqnos int num_frags; try { // write message into a byte buffer and fragment it ByteArrayDataOutputStream dos = new ByteArrayDataOutputStream((int) (size + 50)); msg.writeTo(dos); byte[] buffer = dos.buffer(); byte[][] fragments = Util.fragmentBuffer(buffer, frag_size, dos.position()); num_frags = fragments.length; num_sent_frags += num_frags; if (log.isTraceEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("fragmenting packet to ") .append(dest != null ? dest.toString() : "<all members>") .append(" (size=") .append(buffer.length) .append(") into ") .append(num_frags) .append(" fragment(s) [frag_size=") .append(frag_size) .append(']'); log.trace(sb.toString()); } for (int i = 0; i < num_frags; i++) { Message frag_msg = new Message(dest, src, fragments[i]); FragHeader hdr = new FragHeader(frag_id, i, num_frags); frag_msg.putHeader(this.id, hdr); Event evt = new Event(Event.MSG, frag_msg); down_prot.down(evt); } } catch (Exception e) { log.error(Util.getMessage("ExceptionOccurredTryingToFragmentMessage"), e); } }
/** * Removes all members from a given view which don't have us in their view * (https://jira.jboss.org/browse/JGRP-1061). Example: * * <pre> * A: AB * B: AB * C: ABC * </pre> * * becomes * * <pre> * A: AB * B: AB * C: C // A and B don't have C in their views * </pre> * * @param map A map of members and their associated views */ public static void sanitizeViews(Map<Address, View> map) { if (map == null) return; for (Map.Entry<Address, View> entry : map.entrySet()) { Address key = entry.getKey(); Collection<Address> members = new ArrayList<Address>(entry.getValue().getMembers()); boolean modified = false; for (Iterator<Address> it = members.iterator(); it.hasNext(); ) { Address val = it.next(); if (val.equals(key)) // we can always talk to ourself ! continue; View view = map.get(val); final Collection<Address> tmp_mbrs = view != null ? view.getMembers() : null; if (tmp_mbrs != null && !tmp_mbrs.contains(key)) { it.remove(); modified = true; } } if (modified) { View old_view = entry.getValue(); entry.setValue(new View(old_view.getVid(), members)); } } }