From 7e7b6239ca8867d13e8d8b279a0541bfd71466f7 Mon Sep 17 00:00:00 2001 From: Fabian Lange Date: Wed, 12 Mar 2014 12:47:00 +0100 Subject: reduce frequency of session locking and StreamingProgressEvents (#13155) This change introduces throttling of streaming progress events. Before a event was fired once a buffer was filled. However as the buffer is only 4kb in size, fast uploads would trigger massive amounts of events. This change is backwards incompatible on a logical level. Before this change, a listener would get contentLength/4kb events, while after this change the amount is limited to one progress event per 500ms. Change-Id: I5da092ec4488971b8554b68b44c346057bfcc0e0 --- .../server/communication/FileUploadHandler.java | 49 ++++++++++++++++------ 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'server/src/com') diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java index 3f6bfd9267..88f2e4b120 100644 --- a/server/src/com/vaadin/server/communication/FileUploadHandler.java +++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java @@ -227,6 +227,9 @@ public class FileUploadHandler implements RequestHandler { /* Same as in apache commons file upload library that was previously used. */ private static final int MAX_UPLOAD_BUFFER_SIZE = 4 * 1024; + /* Minimum interval which will be used for streaming progress events. */ + public static final int DEFAULT_STREAMING_PROGRESS_EVENT_INTERVAL_MS = 500; + @Override public boolean handleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) throws IOException { @@ -537,26 +540,35 @@ public class FileUploadHandler implements RequestHandler { } final byte buffer[] = new byte[MAX_UPLOAD_BUFFER_SIZE]; + long lastStreamingEvent = 0; int bytesReadToBuffer = 0; - while ((bytesReadToBuffer = in.read(buffer)) > 0) { - out.write(buffer, 0, bytesReadToBuffer); - totalBytes += bytesReadToBuffer; + do { + bytesReadToBuffer = in.read(buffer); + if (bytesReadToBuffer > 0) { + out.write(buffer, 0, bytesReadToBuffer); + totalBytes += bytesReadToBuffer; + } if (listenProgress) { - // update progress if listener set and contentLength - // received - session.lock(); - try { - StreamingProgressEventImpl progressEvent = new StreamingProgressEventImpl( - filename, type, contentLength, totalBytes); - streamVariable.onProgress(progressEvent); - } finally { - session.unlock(); + long now = System.currentTimeMillis(); + // to avoid excessive session locking and event storms, + // events are sent in intervals, or at the end of the file. + if (lastStreamingEvent + getProgressEventInterval() <= now + || bytesReadToBuffer <= 0) { + lastStreamingEvent = now; + session.lock(); + try { + StreamingProgressEventImpl progressEvent = new StreamingProgressEventImpl( + filename, type, contentLength, totalBytes); + streamVariable.onProgress(progressEvent); + } finally { + session.unlock(); + } } } if (streamVariable.isInterrupted()) { throw new UploadInterruptedException(); } - } + } while (bytesReadToBuffer > 0); // upload successful out.close(); @@ -599,6 +611,17 @@ public class FileUploadHandler implements RequestHandler { return startedEvent.isDisposed(); } + /** + * To prevent event storming, streaming progress events are sent in this + * interval rather than every time the buffer is filled. This fixes #13155. + * To adjust this value override the method, and register your own handler + * in VaadinService.createRequestHandlers(). The default is 500ms, and + * setting it to 0 effectively restores the old behavior. + */ + protected int getProgressEventInterval() { + return DEFAULT_STREAMING_PROGRESS_EVENT_INTERVAL_MS; + } + static void tryToCloseStream(OutputStream out) { try { // try to close output stream (e.g. file handle) -- cgit v1.2.3 From 7cab7fd80f85b9a7846b1d771aa3dce592ae5d42 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 13 Mar 2014 13:23:21 +0200 Subject: Improve error message when reusing UI instance (#13457) Change-Id: I49ec1e837a1a2a04dfadef5fd5fb5b6fd10ffcbc --- server/src/com/vaadin/ui/UI.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'server/src/com') diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 746fa194ac..0412cb1882 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -601,7 +601,18 @@ public abstract class UI extends AbstractSingleComponentContainer implements */ public void doInit(VaadinRequest request, int uiId) { if (this.uiId != -1) { - throw new IllegalStateException("UI id has already been defined"); + String message = "This UI instance is already initialized (as UI id " + + this.uiId + + ") and can therefore not be initialized again (as UI id " + + uiId + "). "; + + if (getSession() != null + && !getSession().equals(VaadinSession.getCurrent())) { + message += "Furthermore, it is already attached to another VaadinSession. "; + } + message += "Please make sure you are not accidentally reusing an old UI instance."; + + throw new IllegalStateException(message); } this.uiId = uiId; -- cgit v1.2.3