public static void testWriteView() throws Exception { List<Address> members = new ArrayList<>(); View v; Address a1 = Util.createRandomAddress(); Address a2 = Util.createRandomAddress(); Address a4 = Util.createRandomAddress(); ViewId vid = new ViewId(a1, 12345); members.add(a1); members.add(a2); members.add(a4); v = new View(vid, members); ByteArrayOutputStream outstream = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(outstream); Util.writeGenericStreamable(v, dos); Util.writeStreamable(v, dos); dos.close(); byte[] buf = outstream.toByteArray(); ByteArrayInputStream instream = new ByteArrayInputStream(buf); DataInputStream dis = new DataInputStream(instream); View v2 = (View) Util.readGenericStreamable(dis); Assert.assertEquals(v, v2); v2 = (View) Util.readStreamable(View.class, dis); Assert.assertEquals(v, v2); }
public List<Integer> providedUpServices() { List<Integer> ret = new ArrayList<Integer>(3); ret.add(Event.FIND_INITIAL_MBRS); ret.add(Event.FIND_ALL_VIEWS); ret.add(Event.GET_PHYSICAL_ADDRESS); return ret; }
public static void testNewMembers() { final Address a = Util.createRandomAddress(), b = Util.createRandomAddress(), c = Util.createRandomAddress(), d = Util.createRandomAddress(), e = Util.createRandomAddress(); List<Address> old = new ArrayList<>(); List<Address> new_list = new ArrayList<>(); old.add(a); old.add(b); old.add(c); new_list.add(b); new_list.add(a); new_list.add(c); new_list.add(d); new_list.add(e); System.out.println("old: " + old); System.out.println("new: " + new_list); List<Address> new_nodes = Util.newMembers(old, new_list); System.out.println("new_nodes = " + new_nodes); assert new_nodes.size() == 2 : "list should have d and e"; assert new_nodes.contains(d); assert new_nodes.contains(e); }
public static void testAll() { List<String> l = new ArrayList<>(); l.add("one"); l.add("two"); l.add("one"); System.out.println("-- list is " + l); assert !(Util.all(l, "one")); l.remove("two"); System.out.println("-- list is " + l); assert Util.all(l, "one"); }
public void up(MessageBatch batch) { if (batch.dest() == null) { // not a unicast batch up_prot.up(batch); return; } int size = batch.size(); Map<Short, List<Message>> msgs = new TreeMap<Short, List<Message>>(); // map of messages, keyed by conn-id for (Message msg : batch) { if (msg == null || msg.isFlagSet(Message.Flag.NO_RELIABILITY)) continue; UnicastHeader hdr = (UnicastHeader) msg.getHeader(id); if (hdr == null) continue; batch.remove(msg); // remove the message from the batch, so it won't be passed up the stack if (hdr.type != UnicastHeader.DATA) { try { handleUpEvent(msg.getSrc(), hdr); } catch (Throwable t) { // we cannot let an exception terminate the processing of this batch log.error(local_addr + ": failed handling event", t); } continue; } List<Message> list = msgs.get(hdr.conn_id); if (list == null) msgs.put(hdr.conn_id, list = new ArrayList<Message>(size)); list.add(msg); } if (!msgs.isEmpty()) handleBatchReceived(batch.sender(), msgs); // process msgs: if (!batch.isEmpty()) up_prot.up(batch); }
protected List<PingData> read(InputStream in) { List<PingData> retval = null; try { while (true) { try { String name_str = Util.readToken(in); String uuid_str = Util.readToken(in); String addr_str = Util.readToken(in); String coord_str = Util.readToken(in); if (name_str == null || uuid_str == null || addr_str == null || coord_str == null) break; UUID uuid = null; try { long tmp = Long.valueOf(uuid_str); uuid = new UUID(0, tmp); } catch (Throwable t) { uuid = UUID.fromString(uuid_str); } PhysicalAddress phys_addr = new IpAddress(addr_str); boolean is_coordinator = coord_str.trim().equals("T") || coord_str.trim().equals("t"); if (retval == null) retval = new ArrayList<>(); retval.add(new PingData(uuid, true, name_str, phys_addr).coord(is_coordinator)); } catch (Throwable t) { log.error(Util.getMessage("FailedReadingLineOfInputStream"), t); } } return retval; } finally { Util.close(in); } }
/** * Computes the next view. Returns a copy that has <code>old_mbrs</code> and <code>suspected_mbrs * </code> removed and <code>new_mbrs</code> added. */ public View getNextView( Collection<Address> new_mbrs, Collection<Address> old_mbrs, Collection<Address> suspected_mbrs) { synchronized (members) { ViewId view_id = view != null ? view.getViewId() : null; if (view_id == null) { log.error("view_id is null"); return null; // this should *never* happen ! } long vid = Math.max(view_id.getId(), ltime) + 1; ltime = vid; Membership tmp_mbrs = tmp_members.copy(); // always operate on the temporary membership tmp_mbrs.remove(suspected_mbrs); tmp_mbrs.remove(old_mbrs); tmp_mbrs.add(new_mbrs); List<Address> mbrs = tmp_mbrs.getMembers(); Address new_coord = local_addr; if (!mbrs.isEmpty()) new_coord = mbrs.get(0); 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 (new_mbrs != null) { for (Address tmp_mbr : new_mbrs) { if (!joining.contains(tmp_mbr)) joining.add(tmp_mbr); } } // Update leaving list (see DESIGN for explanations) if (old_mbrs != null) { for (Address addr : old_mbrs) { if (!leaving.contains(addr)) leaving.add(addr); } } if (suspected_mbrs != null) { for (Address addr : suspected_mbrs) { if (!leaving.contains(addr)) leaving.add(addr); } } return v; } }
/** * Add a new channel listener to be notified on the channel's state change. * * @return true if the listener was added or false if the listener was already in the list. */ public boolean addChannelListener(ChannelListener l) { synchronized (additionalChannelListeners) { if (additionalChannelListeners.contains(l)) { return false; } additionalChannelListeners.add(l); return true; } }
public static void testPickRandomElement() { List<Integer> v = new ArrayList<>(); for (int i = 0; i < 10; i++) { v.add(i); } Integer el; for (int i = 0; i < 10000; i++) { el = Util.pickRandomElement(v); assert el >= 0 && el < 10; } }
protected void _handleMergeRequest( Address sender, MergeId merge_id, Collection<? extends Address> mbrs) throws Exception { boolean success = matchMergeId(merge_id) || setMergeId(null, merge_id); if (!success) throw new Exception( "merge " + this.merge_id + " is already in progress, received merge-id=" + merge_id); /* Clears the view handler queue and discards all JOIN/LEAVE/MERGE requests until after the MERGE */ // gms.getViewHandler().suspend(); if (log.isTraceEnabled()) log.trace( gms.local_addr + ": got merge request from " + sender + ", merge_id=" + merge_id + ", mbrs=" + mbrs); // merge the membership of the current view with mbrs List<Address> members = new LinkedList<Address>(); if (mbrs != null) { // didn't use a set because we didn't want to change the membership order at this // time (although not incorrect) for (Address mbr : mbrs) { if (!members.contains(mbr)) members.add(mbr); } } ViewId tmp_vid = gms.getViewId(); if (tmp_vid != null) tmp_vid = tmp_vid.copy(); if (tmp_vid == null) throw new Exception("view ID is null; cannot return merge response"); View view = new View(tmp_vid, new ArrayList<Address>(members)); // [JGRP-524] - FLUSH and merge: flush doesn't wrap entire merge process // [JGRP-770] - Concurrent startup of many channels doesn't stabilize // [JGRP-700] - FLUSH: flushing should span merge /*if flush is in stack, let this coordinator flush its cluster island */ if (gms.flushProtocolInStack && !gms.startFlush(view)) throw new Exception("flush failed"); // we still need to fetch digests from all members, and not just return our own digest // (https://issues.jboss.org/browse/JGRP-948) Digest digest = fetchDigestsFromAllMembersInSubPartition(members, merge_id); if (digest == null || digest.size() == 0) throw new Exception( "failed fetching digests from subpartition members; dropping merge response"); sendMergeResponse(sender, view, digest, merge_id); }
public static void testReadLine() throws IOException { final String input = " hello world\nthis is \r\n just an example\r\nthis is line 2 \r\n"; String line; InputStream in = new BufferedInputStream(new ByteArrayInputStream(input.getBytes())); List<String> list = new ArrayList<>(4); for (int i = 0; i < 4; i++) { line = Util.readLine(in); System.out.println("line = \"" + line + "\""); list.add(line); } assert list.size() == 4; }
/** * Merge all MergeData. All MergeData elements should be disjunct (both views and digests). * However, this method is prepared to resolve duplicate entries (for the same member). * Resolution strategy for views is to merge only 1 of the duplicate members. Resolution * strategy for digests is to take the higher seqnos for duplicate digests. * * <p>After merging all members into a Membership and subsequent sorting, the first member of * the sorted membership will be the new coordinator. This method has a lock on merge_rsps. * * @param merge_rsps A list of MergeData items. Elements with merge_rejected=true were removed * before. Is guaranteed not to be null and to contain at least 1 member. */ private MergeData consolidateMergeData(List<MergeData> merge_rsps) { long logical_time = 0; // for new_vid List<View> subgroups = new ArrayList<View>(11); // contains a list of Views, each View is a subgroup Collection<Collection<Address>> sub_mbrships = new ArrayList<Collection<Address>>(); for (MergeData tmp_data : merge_rsps) { View tmp_view = tmp_data.getView(); if (tmp_view != null) { ViewId tmp_vid = tmp_view.getVid(); if (tmp_vid != null) { // compute the new view id (max of all vids +1) logical_time = Math.max(logical_time, tmp_vid.getId()); } // merge all membership lists into one (prevent duplicates) sub_mbrships.add(new ArrayList<Address>(tmp_view.getMembers())); subgroups.add(tmp_view.copy()); } } // determine the new digest Digest new_digest = consolidateDigests(merge_rsps, merge_rsps.size()); if (new_digest == null) return null; // remove all members from the new member list that are not in the digest Collection<Address> digest_mbrs = new_digest.getMembers(); for (Collection<Address> coll : sub_mbrships) coll.retainAll(digest_mbrs); List<Address> merged_mbrs = gms.computeNewMembership(sub_mbrships); // the new coordinator is the first member of the consolidated & sorted membership list Address new_coord = merged_mbrs.isEmpty() ? null : merged_mbrs.get(0); if (new_coord == null) return null; // should be the highest view ID seen up to now plus 1 ViewId new_vid = new ViewId(new_coord, logical_time + 1); // determine the new view MergeView new_view = new MergeView(new_vid, merged_mbrs, subgroups); if (log.isTraceEnabled()) log.trace( gms.local_addr + ": consolidated view=" + new_view + "\nconsolidated digest=" + new_digest); return new MergeData(gms.local_addr, new_view, new_digest); }
public static void testLeftMembers2() { final Address a = Util.createRandomAddress(), b = Util.createRandomAddress(), c = Util.createRandomAddress(), d = Util.createRandomAddress(); List<Address> v1 = new ArrayList<>(); v1.add(a); v1.add(b); v1.add(c); v1.add(d); List<Address> v2 = new ArrayList<>(); v2.add(c); v2.add(d); v2.add(a); v2.add(b); View one = new View(new ViewId(a, 1), v1), two = new View(new ViewId(b, 2), v2); List<Address> left = View.leftMembers(one, two); System.out.println("left = " + left); assert left != null; assert left.isEmpty(); }
public static void testPickNext() { List<Integer> list = new ArrayList<>(10); for (int i = 0; i < 10; i++) list.add(i); Integer num = Util.pickNext(list, 5); System.out.println("number next to 5: " + num); assert num != null; assert num.equals(6); num = Util.pickNext(list, 9); System.out.println("number next to 9: " + num); assert num != null; assert num.equals(0); num = Util.pickNext(list, 11); assert num == null; }
@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); }
protected void startStack(String cluster_name) throws Exception { /*make sure the channel is not closed*/ checkClosed(); /*make sure we have a valid channel name*/ if (cluster_name == null) log.debug("cluster_name is null, assuming unicast channel"); else this.cluster_name = cluster_name; if (socket_factory != null) prot_stack.getTopProtocol().setSocketFactory(socket_factory); prot_stack.startStack( cluster_name, local_addr); // calls start() in all protocols, from top to bottom /*create a temporary view, assume this channel is the only member and is the coordinator*/ List<Address> t = new ArrayList<>(1); t.add(local_addr); my_view = new View(local_addr, 0, t); // create a dummy view TP transport = prot_stack.getTransport(); transport.registerProbeHandler(probe_handler); }
public void run() { long end_time, wait_time; List<Request> requests = new LinkedList<Request>(); while (Thread.currentThread().equals(thread) && !suspended) { try { boolean keepGoing = false; end_time = System.currentTimeMillis() + max_bundling_time; do { Request firstRequest = (Request) queue.remove(INTERVAL); // throws a TimeoutException if it runs into timeout requests.add(firstRequest); if (!view_bundling) break; if (queue.size() > 0) { Request nextReq = (Request) queue.peek(); keepGoing = view_bundling && firstRequest.canBeProcessedTogether(nextReq); } else { wait_time = end_time - System.currentTimeMillis(); if (wait_time > 0) queue.waitUntilClosed( wait_time); // misnomer: waits until element has been added or q closed keepGoing = queue.size() > 0 && firstRequest.canBeProcessedTogether((Request) queue.peek()); } } while (keepGoing && System.currentTimeMillis() < end_time); try { process(requests); } finally { requests.clear(); } } catch (QueueClosedException e) { break; } catch (TimeoutException e) { break; } catch (Throwable catchall) { Util.sleep(50); } } }
protected void handleMessage(Message msg) throws Exception { Address dest = msg.getDest(); long len; List tmp; len = msg.size(); // todo: use msg.getLength() instead of msg.getSize() if (len > max_bundle_size) { throw new Exception( "UDP.BundlingOutgoingPacketHandler.handleMessage(): " + "message size (" + len + ") is greater than UDP fragmentation size. " + "Set the fragmentation/bundle size in FRAG and UDP correctly"); } if (total_bytes + len >= max_bundle_size) { if (Trace.trace) { Trace.info( "UDP.BundlingOutgoingPacketHandler.handleMessage()", "sending " + total_bytes + " bytes"); } bundleAndSend(); // send all pending message and clear table total_bytes = 0; } synchronized (msgs) { tmp = (List) msgs.get(dest); if (tmp == null) { tmp = new List(); msgs.put(dest, tmp); } tmp.add(msg); total_bytes += len; } if (!timer_running) { // first message to be bundled startTimer(); } }
public void addResponse(PingData rsp, boolean overwrite) { if (rsp == null) return; promise.getLock().lock(); try { if (overwrite) ping_rsps.remove(rsp); // https://jira.jboss.org/jira/browse/JGRP-1179 int index = ping_rsps.indexOf(rsp); if (index == -1) { ping_rsps.add(rsp); promise.getCond().signalAll(); } else if (rsp.isCoord()) { PingData pr = ping_rsps.get(index); // Check if the already existing element is not server if (!pr.isCoord()) { ping_rsps.set(index, rsp); promise.getCond().signalAll(); } } } finally { promise.getLock().unlock(); } }
protected <T> GroupRequest<T> cast( final Collection<Address> dests, Message msg, RequestOptions options, boolean block_for_results, FutureListener<RspList<T>> listener) throws Exception { if (msg.getDest() != null && !(msg.getDest() instanceof AnycastAddress)) throw new IllegalArgumentException("message destination is non-null, cannot send message"); if (options != null) { msg.setFlag(options.getFlags()).setTransientFlag(options.getTransientFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); } List<Address> real_dests; // we need to clone because we don't want to modify the original if (dests != null) { real_dests = new ArrayList<Address>(); for (Address dest : dests) { if (dest instanceof SiteAddress || this.members.contains(dest)) { if (!real_dests.contains(dest)) real_dests.add(dest); } } } else real_dests = new ArrayList<Address>(members); // if local delivery is off, then we should not wait for the message from the local member. // therefore remove it from the membership Channel tmp = channel; if ((tmp != null && tmp.getDiscardOwnMessages()) || msg.isTransientFlagSet(Message.TransientFlag.DONT_LOOPBACK)) { if (local_addr == null) local_addr = tmp != null ? tmp.getAddress() : null; if (local_addr != null) real_dests.remove(local_addr); } if (options != null && options.hasExclusionList()) { Address[] exclusion_list = options.exclusionList(); for (Address excluding : exclusion_list) real_dests.remove(excluding); } // don't even send the message if the destination list is empty if (log.isTraceEnabled()) log.trace("real_dests=" + real_dests); if (real_dests.isEmpty()) { if (log.isTraceEnabled()) log.trace("destination list is empty, won't send message"); return null; } if (options != null) { boolean async = options.getMode() == ResponseMode.GET_NONE; if (options.getAnycasting()) { if (async) async_anycasts.incrementAndGet(); else sync_anycasts.incrementAndGet(); } else { if (async) async_multicasts.incrementAndGet(); else sync_multicasts.incrementAndGet(); } } GroupRequest<T> req = new GroupRequest<T>(msg, corr, real_dests, options); if (listener != null) req.setListener(listener); if (options != null) { req.setResponseFilter(options.getRspFilter()); req.setAnycasting(options.getAnycasting()); } req.setBlockForResults(block_for_results); req.execute(); return req; }
/** * Get the view and digest and send back both (MergeData) in the form of a MERGE_RSP to the * sender. If a merge is already in progress, send back a MergeData with the merge_rejected field * set to true. * * @param sender The address of the merge leader * @param merge_id The merge ID * @param mbrs The set of members from which we expect responses */ public void handleMergeRequest( Address sender, MergeId merge_id, Collection<? extends Address> mbrs) { boolean success = matchMergeId(merge_id) || setMergeId(null, merge_id); if (!success) { if (log.isWarnEnabled()) log.warn(gms.local_addr + ": merge is already in progress"); sendMergeRejectedResponse(sender, merge_id); return; } /* Clears the view handler queue and discards all JOIN/LEAVE/MERGE requests until after the MERGE */ gms.getViewHandler().suspend(merge_id); if (log.isDebugEnabled()) log.debug( gms.local_addr + ": got merge request from " + sender + ", merge_id=" + merge_id + ", mbrs=" + mbrs); // merge the membership of the current view with mbrs List<Address> members = new LinkedList<Address>(); if (mbrs != null) { // didn't use a set because we didn't want to change the membership order at this // time (although not incorrect) for (Address mbr : mbrs) { if (!members.contains(mbr)) members.add(mbr); } } ViewId tmp_vid = gms.view_id != null ? gms.view_id.copy() : null; if (tmp_vid == null) { log.warn("view ID is null; cannot return merge response"); sendMergeRejectedResponse(sender, merge_id); return; } View view = new View(tmp_vid, new Vector<Address>(members)); // [JGRP-524] - FLUSH and merge: flush doesn't wrap entire merge process // [JGRP-770] - Concurrent startup of many channels doesn't stabilize // [JGRP-700] - FLUSH: flushing should span merge /*if flush is in stack, let this coordinator flush its cluster island */ boolean successfulFlush = gms.startFlush(view); if (!successfulFlush) { sendMergeRejectedResponse(sender, merge_id); if (log.isWarnEnabled()) log.warn( gms.local_addr + ": flush failed; sending merge rejected message to " + sender + ", merge_id=" + merge_id); cancelMerge(merge_id); return; } Digest digest = fetchDigestsFromAllMembersInSubPartition(members); if (digest.size() == 0) { log.error("failed fetching digests from subpartition members; dropping merge response"); return; } sendMergeResponse(sender, view, digest, merge_id); }
/** * Sets the new {@link AddressGenerator}. New addresses will be generated using the new generator. * This should <em>not</em> be done while a channel is connected, but before connecting. * * @param address_generator * @since 2.12 */ public void addAddressGenerator(AddressGenerator address_generator) { if (address_generator == null) return; if (address_generators == null) address_generators = new ArrayList<>(3); address_generators.add(address_generator); }
@SuppressWarnings("unchecked") public void testObjectToFromByteBuffer() throws Exception { byte[] buf; Address addr = Util.createRandomAddress(), addr2; List<String> list = new ArrayList<>(), list2; list.add("Bela"); list.add("Jeannette"); buf = Util.objectToByteBuffer(addr); addr2 = (Address) Util.objectFromByteBuffer(buf); System.out.println("addr=" + addr + ", addr2=" + addr2); Assert.assertEquals(addr, addr2); buf = Util.objectToByteBuffer(list); list2 = (List<String>) Util.objectFromByteBuffer(buf); System.out.println("list=" + list + ", list2=" + list2); Assert.assertEquals(list, list2); byte[] buffer = {'B', 'e', 'l', 'a', ' ', 'B', 'a', 'n'}; buf = Util.objectToByteBuffer(buffer); byte[] buffer2 = (byte[]) Util.objectFromByteBuffer(buf); assert buffer2 != null && buffer.length == buffer2.length; assert Arrays.equals(buffer, buffer2); Object obj = null; buf = Util.objectToByteBuffer(obj); assert buf != null; assert buf.length > 0; obj = Util.objectFromByteBuffer(buf); assert obj == null; Object[] values = { Boolean.TRUE, true, false, Boolean.FALSE, (byte) 22, new Byte("2"), '5', 3.14, 352.3f, 0, 100, 322649, Integer.MAX_VALUE, Integer.MIN_VALUE, 0L, 322649L, Long.MAX_VALUE - 50, Long.MAX_VALUE, Long.MIN_VALUE, (short) 22, Short.MAX_VALUE, Short.MIN_VALUE, "Bela Ban", new byte[] {'H', 'e', 'l', 'l', 'o'}, Util.generateArray(1024) }; for (int i = 0; i < values.length; i++) { Object value = values[i]; marshal(value); } }