@Deprecated public <T> NotifyingFuture<T> callRemoteMethodWithFuture( Address dest, MethodCall method_call, int mode, long timeout, boolean oob) throws Throwable { RequestOptions options = new RequestOptions(mode, timeout, false, null); if (oob) options.setFlags(Message.OOB); return callRemoteMethodWithFuture(dest, method_call, options); }
/** 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"); }
public void testSendMessage() throws Exception { final Address address = channels[1].getAddress(); Message message = new Message(address); // Validate normal dispatchers Object response = dispatchers[0].sendMessage(message, RequestOptions.SYNC()); Assert.assertEquals(response, "dispatcher[1]"); // Validate muxed dispatchers for (int j = 0; j < muxDispatchers[0].length; ++j) { response = muxDispatchers[0][j].sendMessage(message, RequestOptions.SYNC()); Assert.assertEquals(response, "muxDispatcher[1][" + j + "]"); } // Filter testing is disabled for now pending filter improvements in JGroups 3 // // Validate muxed rpc dispatchers w/filter // // RspFilter filter = new RspFilter() { // // @Override // public boolean isAcceptable(Object response, Address sender) { // return !sender.equals(address); // } // // @Override // public boolean needMoreResponses() { // return true; // } // }; // // response = muxDispatchers[0][0].callRemoteMethod(address, method, // RequestOptions.SYNC.setRspFilter(filter)); // // Assert.assertNull(address); // // // Validate stopped mux dispatcher response is auto-filtered // muxDispatchers[1][0].stop(); // // response = muxDispatchers[0][0].callRemoteMethod(address, method, // RequestOptions.SYNC.setRspFilter(null)); // // Assert.assertNull(address); // // // Validate restarted mux dispatcher functions normally // muxDispatchers[1][0].start(); // // response = muxDispatchers[0][0].callRemoteMethod(address, method, // RequestOptions.SYNC.setRspFilter(null)); // // Assert.assertEquals(response, "muxDispatcher[1][0]"); }
@Deprecated public NotifyingFuture<RspList> callRemoteMethodsWithFuture( Vector<Address> dests, MethodCall method_call, int mode, long timeout, boolean use_anycasting, boolean oob, RspFilter filter) { RequestOptions options = new RequestOptions(mode, timeout, use_anycasting, filter); if (oob) options.setFlags(Message.OOB); return callRemoteMethodsWithFuture(dests, method_call, options); }
/** * If the coordinator of the lock locks the lock and then send a message, the receiver will wait * for ever in tryLock. However, castMessage will return after a while because of the default * settings of RequestOptions.SYNC(). */ public void testCoordSendFirst() throws Exception { System.out.println("Running testCoordSendFirst"); // =========================================================================== if (lock_a.tryLock()) { try { System.out.println("A aquired the lock, about to send message to B"); String rsp = disp_a.sendMessage( new Message(b.getAddress(), "bla"), RequestOptions.SYNC().setTimeout(60000)); if (rsp == null) { System.err.println("ERROR: didn't return correctly"); Assert.fail("Didn't return correctly"); } else System.out.println("Returned: " + rsp); } finally { lock_a.unlock(); } } else { Assert.fail("The lock was already locked"); System.out.println("A failed to aquire the lock"); } // =========================================================================== System.out.println(); }
public <T> NotifyingFuture<T> callRemoteMethodWithFuture( Address dest, MethodCall call, RequestOptions options) throws Throwable { if (log.isTraceEnabled()) log.trace("dest=" + dest + ", method_call=" + call + ", options=" + options); Object buf = req_marshaller != null ? req_marshaller.objectToBuffer(call) : Util.objectToByteBuffer(call); Message msg = new Message(dest, null, null); if (buf instanceof Buffer) msg.setBuffer((Buffer) buf); else msg.setBuffer((byte[]) buf); msg.setFlag(options.getFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); return super.sendMessageWithFuture(msg, options); }
public void testMethodReturningException() throws Exception { Object retval = disp.callRemoteMethod( channel.getAddress(), "returnException", null, null, RequestOptions.SYNC()); System.out.println("retval: " + retval); assertNotNull(retval); assert retval instanceof IllegalArgumentException; }
/** * Invokes a method in all members contained in dests (or all members if dests is null). * * @param dests A list of addresses. If null, the method will be invoked on 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 * @return RspList A list of return values and flags (suspected, not received) per member * @since 2.9 */ public RspList callRemoteMethods( Collection<Address> dests, MethodCall method_call, RequestOptions options) { if (dests != null && dests.isEmpty()) { // don't send if dest list is empty if (log.isTraceEnabled()) log.trace( new StringBuilder("destination list of ") .append(method_call.getName()) .append("() is empty: no need to send message")); return RspList.EMPTY_RSP_LIST; } if (log.isTraceEnabled()) log.trace( new StringBuilder("dests=") .append(dests) .append(", method_call=") .append(method_call) .append(", options=") .append(options)); Object buf; try { buf = req_marshaller != null ? req_marshaller.objectToBuffer(method_call) : Util.objectToByteBuffer(method_call); } catch (Exception e) { // if(log.isErrorEnabled()) log.error("exception", e); // we will change this in 3.0 to add the exception to the signature // (see http://jira.jboss.com/jira/browse/JGRP-193). The reason for a RTE is that we cannot // change the // signature in 2.3, otherwise 2.3 would be *not* API compatible to prev releases throw new RuntimeException("failure to marshal argument(s)", e); } Message msg = new Message(); if (buf instanceof Buffer) msg.setBuffer((Buffer) buf); else msg.setBuffer((byte[]) buf); msg.setFlag(options.getFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); RspList retval = super.castMessage(dests, msg, options); if (log.isTraceEnabled()) log.trace("responses: " + retval); return retval; }
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()); }
@Test(expectedExceptions = TimeoutException.class) public void testMethodWithExceptionWithoutWrapping() throws Exception { disp.wrapExceptions(false); try { disp.callRemoteMethod(channel.getAddress(), "bar", null, null, RequestOptions.SYNC()); } finally { disp.wrapExceptions(true); } }
// @Test(expectedExceptions=IllegalArgumentException.class) public void testMethodWithException2() throws Exception { try { disp.callRemoteMethod(channel.getAddress(), "foobar", null, null, RequestOptions.SYNC()); } catch (Throwable t) { System.out.println("t = " + t); assert t instanceof InvocationTargetException; assert t.getCause() instanceof IllegalArgumentException; } }
// @Test(expectedExceptions=InvocationTargetException.class) public void testMethodWithException() throws Exception { try { disp.callRemoteMethod(channel.getAddress(), "bar", null, null, RequestOptions.SYNC()); assert false : "method should have thrown an exception"; } catch (Exception ex) { assert ex instanceof InvocationTargetException; Throwable cause = ex.getCause(); assert cause instanceof TimeoutException; } }
void setAnycastCount() throws Exception { int tmp = Util.readIntFromStdin("Anycast count: "); View view = channel.getView(); if (tmp > view.size()) { System.err.println( "anycast count must be smaller or equal to the view size (" + view + ")\n"); return; } disp.callRemoteMethods(null, new MethodCall(SET_ANYCAST_COUNT, tmp), RequestOptions.SYNC()); }
public Object callRemoteMethod(Address dest, MethodCall call, RequestOptions options) throws Throwable { if (log.isTraceEnabled()) log.trace("dest=" + dest + ", method_call=" + call + ", options=" + options); Object buf = req_marshaller != null ? req_marshaller.objectToBuffer(call) : Util.objectToByteBuffer(call); Message msg = new Message(dest, null, null); if (buf instanceof Buffer) msg.setBuffer((Buffer) buf); else msg.setBuffer((byte[]) buf); msg.setFlag(options.getFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); Object retval = super.sendMessage(msg, options); if (log.isTraceEnabled()) log.trace("retval: " + retval); if (retval instanceof Throwable) throw (Throwable) retval; return retval; }
/** Tests https://issues.jboss.org/browse/JGRP-1369 */ public void testRequestOptionsChaining() throws Exception { MuxRpcDispatcher muxRpc = new MuxRpcDispatcher((short) 1, channel, null, null, new Server()); channel.connect("group"); for (int i = 0; i < 20; i++) muxRpc.callRemoteMethods(null, new MethodCall(Server.class.getMethod("foo")), reqOpt); RspFilter filter = reqOpt.getRspFilter(); int count = count(filter); System.out.println("count=" + count); assert count == 1; }
/** * Sends a unicast message and - depending on the options - returns a result * * @param msg the message to be sent. The destination needs to be non-null * @param opts the options to be used * @return T the result * @throws Exception If there was problem sending the request, processing it at the receiver, or * processing it at the sender. * @throws TimeoutException If the call didn't succeed within the timeout defined in options (if * set) */ public <T> T sendMessage(Message msg, RequestOptions opts) throws Exception { Address dest = msg.getDest(); if (dest == null) throw new IllegalArgumentException("message destination is null, cannot send message"); if (opts != null) { msg.setFlag(opts.getFlags()).setTransientFlag(opts.getTransientFlags()); if (opts.getScope() > 0) msg.setScope(opts.getScope()); if (opts.getMode() == ResponseMode.GET_NONE) async_unicasts.incrementAndGet(); else sync_unicasts.incrementAndGet(); } UnicastRequest<T> req = new UnicastRequest<T>(msg, corr, dest, opts); req.execute(); if (opts != null && opts.getMode() == ResponseMode.GET_NONE) return null; Rsp<T> rsp = req.getResult(); if (rsp.wasSuspected()) throw new SuspectedException(dest); Throwable exception = rsp.getException(); if (exception != null) { if (exception instanceof Error) throw (Error) exception; else if (exception instanceof RuntimeException) throw (RuntimeException) exception; else if (exception instanceof Exception) throw (Exception) exception; else throw new RuntimeException(exception); } if (rsp.wasUnreachable()) throw new UnreachableException(dest); if (!rsp.wasReceived() && !req.responseReceived()) throw new TimeoutException("timeout sending message to " + dest); return rsp.getValue(); }
public void run() { final byte[] buf = new byte[msg_size]; Object[] put_args = {0, buf}; Object[] get_args = {0}; MethodCall get_call = new MethodCall(GET, get_args); MethodCall put_call = new MethodCall(PUT, put_args); RequestOptions get_options = new RequestOptions(ResponseMode.GET_ALL, 40000, false, null); RequestOptions put_options = new RequestOptions( sync ? ResponseMode.GET_ALL : ResponseMode.GET_NONE, 40000, true, null); if (oob) { get_options.setFlags(Message.OOB); put_options.setFlags(Message.OOB); } if (sync) { get_options.setFlags(Message.DONT_BUNDLE, Message.NO_FC); put_options.setFlags(Message.DONT_BUNDLE, Message.NO_FC); } while (true) { long i = num_msgs_sent.getAndIncrement(); if (i >= num_msgs_to_send) break; boolean get = Util.tossWeightedCoin(read_percentage); try { if (get) { // sync GET Address target = pickTarget(); get_args[0] = i; disp.callRemoteMethod(target, get_call, get_options); num_gets++; } else { // sync or async (based on value of 'sync') PUT Collection<Address> targets = pickAnycastTargets(); put_args[0] = i; disp.callRemoteMethods(targets, put_call, put_options); num_puts++; } } catch (Throwable throwable) { throwable.printStackTrace(); } } }
/** * Sends a unicast message to the target defined by msg.getDest() and returns a future * * @param msg The unicast message to be sent. msg.getDest() must not be null * @param options * @param listener A FutureListener which will be registered (if non null) with the future * <em>before</em> the call is invoked * @return NotifyingFuture<T> A future from which the result can be fetched * @throws Exception If there was problem sending the request, processing it at the receiver, or * processing it at the sender. {@link java.util.concurrent.Future#get()} will throw this * exception * @throws TimeoutException If the call didn't succeed within the timeout defined in options (if * set) */ public <T> NotifyingFuture<T> sendMessageWithFuture( Message msg, RequestOptions options, FutureListener<T> listener) throws Exception { Address dest = msg.getDest(); if (dest == null) throw new IllegalArgumentException("message destination is null, cannot send message"); if (options != null) { msg.setFlag(options.getFlags()).setTransientFlag(options.getTransientFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); if (options.getMode() == ResponseMode.GET_NONE) async_unicasts.incrementAndGet(); else sync_unicasts.incrementAndGet(); } UnicastRequest<T> req = new UnicastRequest<T>(msg, corr, dest, options); if (listener != null) req.setListener(listener); req.setBlockForResults(false); req.execute(); if (options != null && options.getMode() == ResponseMode.GET_NONE) return new NullFuture<T>(null); return req; }
public void testCastMessage() throws Exception { Message message = new Message(); // Validate normal dispatchers Map<Address, Rsp<Object>> responses = dispatchers[0].castMessage(null, message, RequestOptions.SYNC()); Assert.assertEquals(responses.size(), 2); for (int i = 0; i < dispatchers.length; ++i) { verifyResponse(responses, channels[i], "dispatcher[" + i + "]"); } // Validate muxed dispatchers for (int j = 0; j < muxDispatchers[0].length; ++j) { responses = muxDispatchers[0][j].castMessage(null, message, RequestOptions.SYNC()); Assert.assertEquals(responses.size(), 2); for (int i = 0; i < dispatchers.length; ++i) { verifyResponse(responses, channels[i], "muxDispatcher[" + i + "][" + j + "]"); } } final Address address = channels[0].getAddress(); RspFilter filter = new RspFilter() { public boolean isAcceptable(Object response, Address sender) { return !sender.equals(address); } public boolean needMoreResponses() { return true; } }; // Validate muxed rpc dispatchers w/filter responses = muxDispatchers[0][0].castMessage(null, message, RequestOptions.SYNC().setRspFilter(filter)); Assert.assertEquals(responses.size(), 2); verifyResponse(responses, channels[0], null); verifyResponse(responses, channels[1], "muxDispatcher[1][0]"); muxDispatchers[1][0].stop(); // Validate stopped mux dispatcher response is auto-filtered responses = muxDispatchers[0][0].castMessage(null, message, RequestOptions.SYNC().setRspFilter(null)); Assert.assertEquals(responses.size(), 2); verifyResponse(responses, channels[0], "muxDispatcher[0][0]"); verifyResponse(responses, channels[1], null); // Validate stopped mux dispatcher response is auto-filtered and custom filter is applied responses = muxDispatchers[0][0].castMessage(null, message, RequestOptions.SYNC().setRspFilter(filter)); Assert.assertEquals(responses.size(), 2); verifyResponse(responses, channels[0], null); verifyResponse(responses, channels[1], null); muxDispatchers[1][0].start(); // Validate restarted mux dispatcher functions normally responses = muxDispatchers[0][0].castMessage(null, message, RequestOptions.SYNC().setRspFilter(null)); Assert.assertEquals(responses.size(), 2); verifyResponse(responses, channels[0], "muxDispatcher[0][0]"); verifyResponse(responses, channels[1], "muxDispatcher[1][0]"); }
private static RspList<Object> processCalls( ReplicableCommand command, boolean broadcast, long timeout, RspFilter filter, List<Address> dests, ResponseMode mode, DeliverOrder deliverOrder, Marshaller marshaller, CommandAwareRpcDispatcher card, boolean ignoreLeavers) throws Exception { if (trace) log.tracef( "Replication task sending %s to addresses %s with response mode %s", command, dests, mode); boolean rsvp = isRsvpCommand(command); RspList<Object> retval = null; Buffer buf; if (deliverOrder == DeliverOrder.TOTAL) { buf = marshallCall(marshaller, command); Message message = constructMessage(buf, new AnycastAddress(dests), mode, rsvp, deliverOrder); retval = card.castMessage(dests, message, new RequestOptions(mode, timeout, false, filter)); } else if (broadcast || FORCE_MCAST) { buf = marshallCall(marshaller, command); RequestOptions opts = new RequestOptions(mode, timeout, false, filter); // Only the commands in total order must be received... // For correctness, ispn doesn't need their own message, so add own address to exclusion list opts.setExclusionList(card.getChannel().getAddress()); retval = card.castMessage(dests, constructMessage(buf, null, mode, rsvp, deliverOrder), opts); } else { RequestOptions opts = new RequestOptions(mode, timeout); // Only the commands in total order must be received... opts.setExclusionList(card.getChannel().getAddress()); if (dests.isEmpty()) return new RspList<>(); buf = marshallCall(marshaller, command); // if at all possible, try not to use JGroups' ANYCAST for now. Multiple (parallel) UNICASTs // are much faster. if (filter != null) { // This is possibly a remote GET. // These UNICASTs happen in parallel using sendMessageWithFuture. Each future has a // listener attached // (see FutureCollator) and the first successful response is used. FutureCollator futureCollator = new FutureCollator(filter, dests.size(), timeout, card.timeService); for (Address a : dests) { NotifyingFuture<Object> f = card.sendMessageWithFuture(constructMessage(buf, a, mode, rsvp, deliverOrder), opts); futureCollator.watchFuture(f, a); } retval = futureCollator.getResponseList(); } else if (mode == ResponseMode.GET_ALL) { // A SYNC call that needs to go everywhere Map<Address, Future<Object>> futures = new HashMap<>(dests.size()); for (Address dest : dests) futures.put( dest, card.sendMessageWithFuture( constructMessage(buf, dest, mode, rsvp, deliverOrder), opts)); retval = new RspList<>(); // a get() on each future will block till that call completes. for (Map.Entry<Address, Future<Object>> entry : futures.entrySet()) { Address target = entry.getKey(); try { retval.addRsp(target, entry.getValue().get(timeout, MILLISECONDS)); } catch (java.util.concurrent.TimeoutException te) { throw new TimeoutException( formatString( "Timed out after %s waiting for a response from %s", prettyPrintTime(timeout), target)); } catch (ExecutionException e) { if (ignoreLeavers && e.getCause() instanceof SuspectedException) { log.tracef(formatString("Ignoring node %s that left during the remote call", target)); } else { throw wrapThrowableInException(e.getCause()); } } } } else if (mode == ResponseMode.GET_NONE) { // An ASYNC call. We don't care about responses. for (Address dest : dests) card.sendMessage(constructMessage(buf, dest, mode, rsvp, deliverOrder), opts); } } // we only bother parsing responses if we are not in ASYNC mode. if (mode != ResponseMode.GET_NONE) { if (trace) log.tracef("Responses: %s", retval); // a null response is 99% likely to be due to a marshalling problem - we throw a NSE, this // needs to be changed when // JGroups supports http://jira.jboss.com/jira/browse/JGRP-193 // the serialization problem could be on the remote end and this is why we cannot catch this // above, when marshalling. if (retval == null) throw new NotSerializableException( "RpcDispatcher returned a null. This is most often caused by args for " + command.getClass().getSimpleName() + " not being serializable."); } return retval; }
void setMessageSize() throws Exception { int tmp = Util.readIntFromStdin("Message size: "); disp.callRemoteMethods(null, new MethodCall(SET_MSG_SIZE, tmp), RequestOptions.SYNC()); }
void setNumMessages() throws Exception { int tmp = Util.readIntFromStdin("Number of RPCs: "); disp.callRemoteMethods(null, new MethodCall(SET_NUM_MSGS, tmp), RequestOptions.SYNC()); }
void setSenderThreads() throws Exception { int threads = Util.readIntFromStdin("Number of sender threads: "); disp.callRemoteMethods(null, new MethodCall(SET_NUM_THREADS, threads), RequestOptions.SYNC()); }
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; }
public void eventLoop() throws Throwable { int c; while (true) { c = Util.keyPress( "[1] Send msgs [2] Print view [3] Print conns " + "[4] Trash conn [5] Trash all conns" + "\n[6] Set sender threads (" + num_threads + ") [7] Set num msgs (" + num_msgs + ") " + "[8] Set msg size (" + Util.printBytes(msg_size) + ")" + " [9] Set anycast count (" + anycast_count + ")" + "\n[o] Toggle OOB (" + oob + ") [s] Toggle sync (" + sync + ") [r] Set read percentage (" + f.format(read_percentage) + ")" + "\n[q] Quit\n"); switch (c) { case -1: break; case '1': try { startBenchmark(); } catch (Throwable t) { System.err.println(t); } break; case '2': printView(); break; case '3': printConnections(); break; case '4': removeConnection(); break; case '5': removeAllConnections(); break; case '6': setSenderThreads(); break; case '7': setNumMessages(); break; case '8': setMessageSize(); break; case '9': setAnycastCount(); break; case 'o': boolean new_value = !oob; disp.callRemoteMethods(null, new MethodCall(SET_OOB, new_value), RequestOptions.SYNC()); break; case 's': boolean new_val = !sync; disp.callRemoteMethods(null, new MethodCall(SET_SYNC, new_val), RequestOptions.SYNC()); break; case 'r': setReadPercentage(); break; case 'q': channel.close(); return; case '\n': case '\r': break; default: break; } } }