/** * Message contains MethodCall. Execute it against *this* object and return result. Use * MethodCall.invoke() to do this. Return result. */ public Object handle(Message req) throws Exception { if (server_obj == null) { log.error(Util.getMessage("NoMethodHandlerIsRegisteredDiscardingRequest")); return null; } if (req == null || req.getLength() == 0) { log.error(Util.getMessage("MessageOrMessageBufferIsNull")); return null; } Object body = req_marshaller != null ? req_marshaller.objectFromBuffer(req.getRawBuffer(), req.getOffset(), req.getLength()) : req.getObject(); if (!(body instanceof MethodCall)) throw new IllegalArgumentException("message does not contain a MethodCall object"); MethodCall method_call = (MethodCall) body; if (log.isTraceEnabled()) log.trace("[sender=%s], method_call: %s", req.getSrc(), method_call); if (method_call.getMode() == MethodCall.ID) { if (method_lookup == null) throw new Exception( String.format( "MethodCall uses ID=%d, but method_lookup has not been set", method_call.getId())); Method m = method_lookup.findMethod(method_call.getId()); if (m == null) throw new Exception("no method found for " + method_call.getId()); method_call.setMethod(m); } return method_call.invoke(server_obj); }
/** * @param views Guaranteed to be non-null and to have >= 2 members, or else this thread would * not be started */ public synchronized void start(Map<Address, View> views) { if (thread == null || thread.isAlive()) { this.coords.clear(); // now remove all members which don't have us in their view, so RPCs won't block (e.g. // FLUSH) // https://jira.jboss.org/browse/JGRP-1061 sanitizeViews(views); // Add all different coordinators of the views into the hashmap and sets their members: Collection<Address> coordinators = Util.determineMergeCoords(views); for (Address coord : coordinators) { View view = views.get(coord); if (view != null) this.coords.put(coord, new ArrayList<Address>(view.getMembers())); } // For the merge participants which are not coordinator, we simply add them, and the // associated // membership list consists only of themselves Collection<Address> merge_participants = Util.determineMergeParticipants(views); merge_participants.removeAll(coordinators); for (Address merge_participant : merge_participants) { Collection<Address> tmp = new ArrayList<Address>(); tmp.add(merge_participant); coords.putIfAbsent(merge_participant, tmp); } thread = gms.getThreadFactory().newThread(this, "MergeTask"); thread.setDaemon(true); thread.start(); } }
/** Kicks off the benchmark on all cluster nodes */ void startBenchmark() throws Throwable { RequestOptions options = new RequestOptions(ResponseMode.GET_ALL, 0); options.setFlags(Message.OOB, Message.DONT_BUNDLE, Message.NO_FC); RspList<Object> responses = disp.callRemoteMethods(null, new MethodCall(START), options); long total_reqs = 0; long total_time = 0; System.out.println("\n======================= Results: ==========================="); for (Map.Entry<Address, Rsp<Object>> entry : responses.entrySet()) { Address mbr = entry.getKey(); Rsp rsp = entry.getValue(); Results result = (Results) rsp.getValue(); total_reqs += result.num_gets + result.num_puts; total_time += result.time; System.out.println(mbr + ": " + result); } double total_reqs_sec = total_reqs / (total_time / 1000.0); double throughput = total_reqs_sec * msg_size; double ms_per_req = total_time / (double) total_reqs; Protocol prot = channel.getProtocolStack().findProtocol(unicast_protocols); System.out.println("\n"); System.out.println( Util.bold( "Average of " + f.format(total_reqs_sec) + " requests / sec (" + Util.printBytes(throughput) + " / sec), " + f.format(ms_per_req) + " ms /request (prot=" + prot.getName() + ")")); System.out.println("\n\n"); }
/** * 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"); } }
static void marshal(Object obj) throws Exception { byte[] buf = Util.objectToByteBuffer(obj); assert buf != null; assert buf.length > 0; Object obj2 = Util.objectFromByteBuffer(buf); System.out.println( "obj=" + obj + ", obj2=" + obj2 + " (type=" + obj.getClass().getName() + ", length=" + buf.length + " bytes)"); Assert.assertEquals(obj, obj2); if (obj instanceof Integer) { // test compressed ints and longs buf = new byte[10]; Bits.writeIntCompressed((int) obj, buf, 0); obj2 = Bits.readIntCompressed(buf, 0); assert obj.equals(obj2); } if (obj instanceof Long) { // test compressed ints and longs buf = new byte[10]; Bits.writeLongCompressed((long) obj, buf, 0); obj2 = Bits.readLongCompressed(buf, 0); assert obj.equals(obj2); } }
public static void testAllEqual() { Address[] mbrs = Util.createRandomAddresses(5); View[] views = { View.create(mbrs[0], 1, mbrs), View.create(mbrs[0], 1, mbrs), View.create(mbrs[0], 1, mbrs) }; boolean same = Util.allEqual(Arrays.asList(views)); System.out.println("views=" + Arrays.toString(views) + ", same = " + same); assert same; views = new View[] { View.create(mbrs[0], 1, mbrs), View.create(mbrs[0], 2, mbrs), View.create(mbrs[0], 1, mbrs) }; same = Util.allEqual(Arrays.asList(views)); System.out.println("views=" + Arrays.toString(views) + ", same = " + same); assert !same; views = new View[] { View.create(mbrs[1], 1, mbrs), View.create(mbrs[0], 1, mbrs), View.create(mbrs[0], 1, mbrs) }; same = Util.allEqual(Arrays.asList(views)); System.out.println("views=" + Arrays.toString(views) + ", same = " + same); assert !same; }
public static void testDetermineMergeParticipantsAndMergeCoords() { Address a = Util.createRandomAddress(), b = Util.createRandomAddress(), c = Util.createRandomAddress(); org.jgroups.util.UUID.add(a, "A"); org.jgroups.util.UUID.add(b, "B"); org.jgroups.util.UUID.add(c, "C"); View v1 = View.create(b, 1, b, a, c); View v2 = View.create(b, 2, b, c); View v3 = View.create(b, 2, b, c); Map<Address, View> map = new HashMap<>(); map.put(a, v1); map.put(b, v2); map.put(c, v3); StringBuilder sb = new StringBuilder("map:\n"); for (Map.Entry<Address, View> entry : map.entrySet()) sb.append(entry.getKey() + ": " + entry.getValue() + "\n"); System.out.println(sb); Collection<Address> merge_participants = Util.determineMergeParticipants(map); System.out.println("merge_participants = " + merge_participants); assert merge_participants.size() == 2; assert merge_participants.contains(a) && merge_participants.contains(b); Collection<Address> merge_coords = Util.determineMergeCoords(map); System.out.println("merge_coords = " + merge_coords); assert merge_coords.size() == 1; assert merge_coords.contains(b); }
public static void testMessageToByteBuffer() throws Exception { _testMessage(new Message()); _testMessage(new Message(null, null, "hello world")); _testMessage(new Message(null, Util.createRandomAddress(), null)); _testMessage(new Message(null, Util.createRandomAddress(), null)); _testMessage(new Message(null, Util.createRandomAddress(), "bela")); }
private static void _testMessage(Message msg) throws Exception { Buffer buf = Util.messageToByteBuffer(msg); Message msg2 = Util.byteBufferToMessage(buf.getBuf(), buf.getOffset(), buf.getLength()); Assert.assertEquals(msg.getSrc(), msg2.getSrc()); Assert.assertEquals(msg.getDest(), msg2.getDest()); Assert.assertEquals(msg.getLength(), msg2.getLength()); }
private static void marshalString(int size) throws Exception { byte[] tmp = new byte[size]; String str = new String(tmp, 0, tmp.length); byte[] retval = Util.objectToByteBuffer(str); System.out.println("length=" + retval.length + " bytes"); String obj = (String) Util.objectFromByteBuffer(retval); System.out.println("read " + obj.length() + " string"); }
public static void testStringMarshalling() throws Exception { byte[] tmp = {'B', 'e', 'l', 'a'}; String str = new String(tmp); byte[] buf = Util.objectToByteBuffer(str); String str2 = (String) Util.objectFromByteBuffer(buf); assert str.equals(str2); tmp[1] = 'a'; str2 = (String) Util.objectFromByteBuffer(buf); assert str.equals(str2); }
public static void testWriteNullAddress() throws Exception { Address a1 = null; ByteArrayOutputStream outstream = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(outstream); Util.writeAddress(a1, dos); dos.close(); byte[] buf = outstream.toByteArray(); ByteArrayInputStream instream = new ByteArrayInputStream(buf); DataInputStream dis = new DataInputStream(instream); assert Util.readAddress(dis) == null; }
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"); }
/** * 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; } }
/** * Unmarshal the original message (in the payload) and then pass it up (unless already delivered) * * @param msg */ protected void unwrapAndDeliver(final Message msg, boolean flush_ack) { try { Message msg_to_deliver = Util.streamableFromBuffer( Message.class, msg.getRawBuffer(), msg.getOffset(), msg.getLength()); SequencerHeader hdr = (SequencerHeader) msg_to_deliver.getHeader(this.id); if (flush_ack) hdr.flush_ack = true; deliver(msg_to_deliver, new Event(Event.MSG, msg_to_deliver), hdr); } catch (Exception ex) { log.error(Util.getMessage("FailureUnmarshallingBuffer"), ex); } }
protected void forward(final Message msg, long seqno, boolean flush) { Address target = coord; if (target == null) return; byte type = flush ? SequencerHeader.FLUSH : SequencerHeader.FORWARD; try { SequencerHeader hdr = new SequencerHeader(type, seqno); Message forward_msg = new Message(target, Util.streamableToBuffer(msg)).putHeader(this.id, hdr); down_prot.down(new Event(Event.MSG, forward_msg)); forwarded_msgs++; } catch (Exception ex) { log.error(Util.getMessage("FailedForwardingMessageTo") + msg.getDest(), ex); } }
public static void testWriteByteBuffer() throws Exception { byte[] buf = new byte[1024], tmp; for (int i = 0; i < buf.length; i++) buf[i] = 0; ByteArrayOutputStream outstream = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(outstream); Util.writeByteBuffer(buf, dos); dos.close(); tmp = outstream.toByteArray(); ByteArrayInputStream instream = new ByteArrayInputStream(tmp); DataInputStream dis = new DataInputStream(instream); byte[] buf2 = Util.readByteBuffer(dis); assert buf2 != null; Assert.assertEquals(buf.length, buf2.length); }
protected void sendDiscoveryResponse( Address logical_addr, List<PhysicalAddress> physical_addrs, boolean is_server, boolean return_view_only, String logical_name, final Address sender) { PingData data; if (return_view_only) { data = new PingData(logical_addr, view, is_server, null, null); } else { ViewId view_id = view != null ? view.getViewId() : null; data = new PingData(logical_addr, null, view_id, is_server, logical_name, physical_addrs); } final Message rsp_msg = new Message(sender, null, null); rsp_msg.setFlag(Message.OOB); final PingHeader rsp_hdr = new PingHeader(PingHeader.GET_MBRS_RSP, data); rsp_msg.putHeader(this.id, rsp_hdr); if (stagger_timeout > 0) { int view_size = view != null ? view.size() : 10; int rank = Util.getRank(view, local_addr); // returns 0 if view or local_addr are null long sleep_time = rank == 0 ? Util.random(stagger_timeout) : stagger_timeout * rank / view_size - (stagger_timeout / view_size); timer.schedule( new Runnable() { public void run() { if (log.isTraceEnabled()) log.trace( local_addr + ": received GET_MBRS_REQ from " + sender + ", sending staggered response " + rsp_hdr); down_prot.down(new Event(Event.MSG, rsp_msg)); } }, sleep_time, TimeUnit.MILLISECONDS); return; } if (log.isTraceEnabled()) log.trace("received GET_MBRS_REQ from " + sender + ", sending response " + rsp_hdr); down_prot.down(new Event(Event.MSG, rsp_msg)); }
/** * Invokes a method in all members and expects responses from members contained in dests (or all * members if dests is null). * * @param dests A list of addresses. If null, we'll wait for responses from all cluster members * @param method_call The method (plus args) to be invoked * @param options A collection of call options, e.g. sync versus async, timeout etc * @param listener A FutureListener which will be registered (if non null) with the future * <em>before</em> the call is invoked * @return NotifyingFuture A future from which the results can be fetched * @throws Exception If the sending of the message threw an exception. Note that <em>no</em> * exception will be thrown if any of the target members threw an exception; such an exception * will be in the Rsp element for the particular member in the RspList */ public <T> NotifyingFuture<RspList<T>> callRemoteMethodsWithFuture( Collection<Address> dests, MethodCall method_call, RequestOptions options, FutureListener<RspList<T>> listener) throws Exception { if (dests != null && dests.isEmpty()) { // don't send if dest list is empty if (log.isTraceEnabled()) log.trace( "destination list of %s() is empty: no need to send message", method_call.getName()); return new NullFuture<>(new RspList()); } if (log.isTraceEnabled()) log.trace("dests=%s, method_call=%s, options=%s", dests, method_call, options); Buffer buf = req_marshaller != null ? req_marshaller.objectToBuffer(method_call) : Util.objectToBuffer(method_call); Message msg = new Message().setBuffer(buf); NotifyingFuture<RspList<T>> retval = super.castMessageWithFuture(dests, msg, options, listener); if (log.isTraceEnabled()) log.trace("responses: %s", retval); return retval; }
public void up(MessageBatch batch) { // Sort fork messages by fork-stack-id Map<String, List<Message>> map = new HashMap<>(); for (Message msg : batch) { ForkHeader hdr = (ForkHeader) msg.getHeader(id); if (hdr != null) { batch.remove(msg); List<Message> list = map.get(hdr.fork_stack_id); if (list == null) { list = new ArrayList<>(); map.put(hdr.fork_stack_id, list); } list.add(msg); } } // Now pass fork messages up, batched by fork-stack-id for (Map.Entry<String, List<Message>> entry : map.entrySet()) { String fork_stack_id = entry.getKey(); List<Message> list = entry.getValue(); Protocol bottom_prot = get(fork_stack_id); if (bottom_prot == null) continue; MessageBatch mb = new MessageBatch( batch.dest(), batch.sender(), batch.clusterName(), batch.multicast(), list); try { bottom_prot.up(mb); } catch (Throwable t) { log.error(Util.getMessage("FailedPassingUpBatch"), t); } } if (!batch.isEmpty()) up_prot.up(batch); }
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; }
/** * 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 } }
public Results startTest() throws Throwable { System.out.println( "invoking " + num_msgs + " RPCs of " + Util.printBytes(msg_size) + ", sync=" + sync + ", oob=" + oob); int total_gets = 0, total_puts = 0; final AtomicInteger num_msgs_sent = new AtomicInteger(0); Invoker[] invokers = new Invoker[num_threads]; for (int i = 0; i < invokers.length; i++) invokers[i] = new Invoker(members, num_msgs, num_msgs_sent); long start = System.currentTimeMillis(); for (Invoker invoker : invokers) invoker.start(); for (Invoker invoker : invokers) { invoker.join(); total_gets += invoker.numGets(); total_puts += invoker.numPuts(); } long total_time = System.currentTimeMillis() - start; System.out.println("done (in " + total_time + " ms)"); return new Results(total_gets, total_puts, total_time); }
public void readFrom(DataInput in) throws Exception { type = in.readByte(); switch (type) { case DATA: seqno = Util.readLong(in); conn_id = in.readShort(); first = in.readBoolean(); break; case ACK: seqno = Util.readLong(in); conn_id = in.readShort(); break; case SEND_FIRST_SEQNO: seqno = Util.readLong(in); break; } }
public static void testParseSemicolonDelimitedString2() { String input = " myID1::subID1 ; myID2::mySubID2; myID3 ;myID4::blaSubID4"; List list = Util.parseStringList(input, ";"); System.out.println("list: " + list); Assert.assertEquals(4, list.size()); Assert.assertEquals("myID1::subID1", list.get(0)); Assert.assertEquals("myID4::blaSubID4", list.get(list.size() - 1)); }
public static void testParseSemicolonDelimitedString() { String input = "one;two ; three; four ; five;six"; List list = Util.parseStringList(input, ";"); System.out.println("list: " + list); Assert.assertEquals(6, list.size()); Assert.assertEquals("one", list.get(0)); Assert.assertEquals("six", list.get(list.size() - 1)); }
protected PingData deserialize(final byte[] data) { try { return (PingData) Util.streamableFromByteBuffer(PingData.class, data); } catch (Exception e) { log.error("Error", e); return null; } }
public static void testWriteStreamable() throws Exception { Message m = new Message(null, null, "Hello"); ViewId vid2 = new ViewId(Util.createRandomAddress(), 35623); ByteArrayOutputStream outstream = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(outstream); Util.writeGenericStreamable(m, dos); Util.writeGenericStreamable(vid2, dos); dos.close(); byte[] buf = outstream.toByteArray(); ByteArrayInputStream instream = new ByteArrayInputStream(buf); DataInputStream dis = new DataInputStream(instream); Message m2 = (Message) Util.readGenericStreamable(dis); ViewId v3 = (ViewId) Util.readGenericStreamable(dis); assert m2.getBuffer() != null; Assert.assertEquals(m.getLength(), m2.getLength()); assert v3 != null; }
private boolean matchMergeId(MergeId id) { merge_lock.lock(); try { return Util.match(this.merge_id, id); } finally { merge_lock.unlock(); } }
void setReadPercentage() throws Exception { double tmp = Util.readDoubleFromStdin("Read percentage: "); if (tmp < 0 || tmp > 1.0) { System.err.println("read percentage must be >= 0 or <= 1.0"); return; } disp.callRemoteMethods(null, new MethodCall(SET_READ_PERCENTAGE, tmp), RequestOptions.SYNC()); }