From 008912fd5ea5d6d0c5342be978546618ed689085 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 7 Jul 2016 14:04:17 +1000 Subject: [PATCH 1/3] Issue #658 Add setter to control using memcached heartbeats. --- .../config/etc/gcloud-memcached-session-context.xml | 6 ++++++ .../session/GCloudMemcachedSessionManager.java | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/config/etc/gcloud-memcached-session-context.xml b/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/config/etc/gcloud-memcached-session-context.xml index 04a9cfcf4e1..b35daa8bd23 100644 --- a/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/config/etc/gcloud-memcached-session-context.xml +++ b/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/config/etc/gcloud-memcached-session-context.xml @@ -17,6 +17,12 @@ 600 + + diff --git a/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/java/org/eclipse/jetty/gcloud/memcached/session/GCloudMemcachedSessionManager.java b/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/java/org/eclipse/jetty/gcloud/memcached/session/GCloudMemcachedSessionManager.java index 5d97e599466..094c33c4533 100644 --- a/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/java/org/eclipse/jetty/gcloud/memcached/session/GCloudMemcachedSessionManager.java +++ b/jetty-gcloud/jetty-gcloud-memcached-session-manager/src/main/java/org/eclipse/jetty/gcloud/memcached/session/GCloudMemcachedSessionManager.java @@ -52,6 +52,7 @@ public class GCloudMemcachedSessionManager extends GCloudSessionManager protected String _port; protected MemcachedClient _client; protected int _expirySec = 0; + private boolean _heartbeats = true; @@ -210,6 +211,15 @@ public class GCloudMemcachedSessionManager extends GCloudSessionManager { _expirySec = expirySec; } + + + /** + * @param heartbeats if true memcached heartbeats are enabled. Default is true. + */ + public void setHeartbeats (boolean heartbeats) + { + _heartbeats = heartbeats; + } @Override @@ -222,6 +232,8 @@ public class GCloudMemcachedSessionManager extends GCloudSessionManager XMemcachedClientBuilder builder = new XMemcachedClientBuilder(_host+":"+_port); _client = builder.build(); + _client.setEnableHeartBeat(_heartbeats); + _client.setTranscoder(new ContextClassloaderSerializingTranscoder()); super.doStart(); From 7afc36064bdb74dceb2f98682e1970f8543cdef5 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 7 Jul 2016 15:12:32 +1000 Subject: [PATCH 2/3] Issue #678 --- .../eclipse/jetty/annotations/AnnotationConfiguration.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java index 0ef01a78c2f..fcab2ac596a 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java @@ -559,6 +559,9 @@ public class AnnotationConfiguration extends AbstractConfiguration } boolean timeout = !latch.await(getMaxScanWait(context), TimeUnit.SECONDS); + long elapsedMs = TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS); + + LOG.info("Scanning elapsed time={}ms",elapsedMs); if (LOG.isDebugEnabled()) { @@ -567,7 +570,7 @@ public class AnnotationConfiguration extends AbstractConfiguration LOG.debug("Scanned {} container path jars, {} WEB-INF/lib jars, {} WEB-INF/classes dirs in {}ms for context {}", _containerPathStats.getTotal(), _webInfLibStats.getTotal(), _webInfClassesStats.getTotal(), - (TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)), + elapsedMs, context); } From 183e3acabb828af8ed370b8a5eeaacbd6a5bf91b Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 7 Jul 2016 16:36:22 +1000 Subject: [PATCH 3/3] Issue #695 improve getResponse methods --- .../eclipse/jetty/io/ByteArrayEndPoint.java | 2 +- .../eclipse/jetty/server/LocalConnector.java | 100 +++++++++++++++--- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayEndPoint.java index 6e9684bf050..fd2a6b9c806 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayEndPoint.java @@ -282,7 +282,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint try(Locker.Lock lock = _locker.lock()) { - if (BufferUtil.isEmpty(_out)) + if (BufferUtil.isEmpty(_out) && !_closed && !_oshut) _hasOutput.await(time,unit); b=_out; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java index c00b0673338..348cf148de5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java @@ -38,11 +38,20 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; +/** + * A local connector, mostly for testing purposes. + *
+ *  HttpTester.Request request = HttpTester.newRequest();
+ *  request.setURI("/some/resource");
+ *  HttpTester.Response response = 
+ *      HttpTester.parseResponse(HttpTester.from(localConnector.getResponse(request.generate())));
+ * 
+ * + */ public class LocalConnector extends AbstractConnector { private final BlockingQueue _connects = new LinkedBlockingQueue<>(); - public LocalConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, int acceptors, ConnectionFactory... factories) { super(server,executor,scheduler,pool,acceptors,factories); @@ -198,20 +207,36 @@ public class LocalConnector extends AbstractConnector { return getResponse(requestsBuffer,false,10,TimeUnit.SECONDS); } + + /** Get a single response using a parser to search for the end of the message. + * @param requestBuffer The request to send + * @param time The time to wait + * @param unit The units of the wait + * @return ByteBuffer containing response or null. + * @throws Exception If there is a problem + */ + public ByteBuffer getResponse(ByteBuffer requestBuffer, long time,TimeUnit unit) throws Exception + { + boolean head = BufferUtil.toString(requestBuffer).toLowerCase().startsWith("head "); + if (LOG.isDebugEnabled()) + LOG.debug("requests {}", BufferUtil.toUTF8String(requestBuffer)); + LocalEndPoint endp = executeRequest(requestBuffer); + return endp.waitForResponse(head,time,unit); + } /** Get a single response using a parser to search for the end of the message. - * @param requestsBuffer The request to send + * @param requestBuffer The request to send * @param head True if the response is for a head request * @param time The time to wait * @param unit The units of the wait * @return ByteBuffer containing response or null. * @throws Exception If there is a problem */ - public ByteBuffer getResponse(ByteBuffer requestsBuffer,boolean head, long time,TimeUnit unit) throws Exception + public ByteBuffer getResponse(ByteBuffer requestBuffer,boolean head, long time,TimeUnit unit) throws Exception { if (LOG.isDebugEnabled()) - LOG.debug("requests {}", BufferUtil.toUTF8String(requestsBuffer)); - LocalEndPoint endp = executeRequest(requestsBuffer); + LOG.debug("requests {}", BufferUtil.toUTF8String(requestBuffer)); + LocalEndPoint endp = executeRequest(requestBuffer); return endp.waitForResponse(head,time,unit); } @@ -225,6 +250,25 @@ public class LocalConnector extends AbstractConnector { return getResponse(rawRequest,false,30,TimeUnit.SECONDS); } + + /** Get a single response using a parser to search for the end of the message. + * @param rawRequest The request to send + * @param time The time to wait + * @param unit The units of the wait + * @return ByteBuffer containing response or null. + * @throws Exception If there is a problem + */ + public String getResponse(String rawRequest,long time,TimeUnit unit) throws Exception + { + boolean head = rawRequest.toLowerCase().startsWith("head "); + ByteBuffer requestsBuffer = BufferUtil.toBuffer(rawRequest, StandardCharsets.ISO_8859_1); + if (LOG.isDebugEnabled()) + LOG.debug("request {}", BufferUtil.toUTF8String(requestsBuffer)); + LocalEndPoint endp = executeRequest(requestsBuffer); + + return BufferUtil.toString(endp.waitForResponse(head,time,unit), StandardCharsets.ISO_8859_1); + } + /** Get a single response using a parser to search for the end of the message. * @param rawRequest The request to send @@ -244,8 +288,6 @@ public class LocalConnector extends AbstractConnector return BufferUtil.toString(endp.waitForResponse(head,time,unit), StandardCharsets.ISO_8859_1); } - - /** Local EndPoint */ public class LocalEndPoint extends ByteArrayEndPoint @@ -332,7 +374,30 @@ public class LocalConnector extends AbstractConnector } } } - + + /** Wait for a response using a parser to detect the end of message + * @return Buffer containing full response or null for EOF; + * @throws Exception + */ + public String getResponse() throws Exception + { + return getResponse(false,30,TimeUnit.SECONDS); + } + + /** Wait for a response using a parser to detect the end of message + * @param head + * @param time + * @param unit + * @return Buffer containing full response or null for EOF; + * @throws Exception + */ + public String getResponse(boolean head, long time,TimeUnit unit) throws Exception + { + ByteBuffer response = waitForResponse(head,time,unit); + if (response!=null) + return BufferUtil.toString(response); + return null; + } /** Wait for a response using a parser to detect the end of message * @param head @@ -391,7 +456,6 @@ public class LocalConnector extends AbstractConnector } }; - HttpParser parser = new HttpParser(handler); parser.setHeadResponse(head); try(ByteArrayOutputStream2 bout = new ByteArrayOutputStream2();) @@ -399,10 +463,20 @@ public class LocalConnector extends AbstractConnector loop: while(true) { // read a chunk of response - ByteBuffer chunk = BufferUtil.hasContent(_responseData) - ? _responseData : waitForOutput(time,unit); - _responseData=null; - + ByteBuffer chunk; + if (BufferUtil.hasContent(_responseData)) + chunk = _responseData; + else + { + chunk = waitForOutput(time,unit); + if (BufferUtil.isEmpty(chunk) && (!isOpen() || isOutputShutdown())) + { + parser.atEOF(); + parser.parseNext(BufferUtil.EMPTY_BUFFER); + break loop; + } + } + // Parse the content of this chunk while (BufferUtil.hasContent(chunk)) {