From dc343b05a2f26a1730715628272e1b60111dd61f Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 15 Nov 2018 14:24:46 +0000 Subject: [PATCH] MLab/NDT: Hook test to wizard Make helper the session scope, not handler Reduce whitespace in formhandler.jsi Notes on why FormHandler can't be session scope Ajax still TODO --- .../src/net/i2p/router/web/FormHandler.java | 2 + .../i2p/router/web/helpers/WizardHandler.java | 155 ++++------------- .../i2p/router/web/helpers/WizardHelper.java | 157 ++++++++++++++++++ apps/routerconsole/jsp/formhandler.jsi | 8 +- apps/routerconsole/jsp/welcome.jsp | 32 ++-- 5 files changed, 213 insertions(+), 141 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index eec72e2f62..7681196748 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -18,6 +18,8 @@ import net.i2p.util.Log; * The form is "processed" after the properties are set and the first output * property is retrieved - either getAll(), getNotices() or getErrors(). * + * This Handler will only process a single POST. The jsp bean must be declared scope=request. + * */ public abstract class FormHandler { protected RouterContext _context; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHandler.java index 7bf50fbddc..646f84e5b3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHandler.java @@ -2,9 +2,6 @@ package net.i2p.router.web.helpers; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.vuze.plugins.mlab.MLabRunner; import net.i2p.router.Router; import net.i2p.router.transport.FIFOBandwidthRefiller; @@ -12,28 +9,35 @@ import net.i2p.router.web.FormHandler; /** * The new user wizard. - * This bean has SESSION scope so the results may be retrieved. - * All necessary methods are synchronized. + * + * This handler has request scope (as all FormHandlers must), so it controls + * the test via the helper, which has session scope. * * @since 0.9.38 */ public class WizardHandler extends FormHandler { - // session scope, but it's an underlying singleton - private MLabRunner _mlab; - // session scope - private TestListener _listener; - - @Override - public void setContextId(String contextId) { - super.setContextId(contextId); - _mlab = MLabRunner.getInstance(_context); - } + private WizardHelper _helper; + /** + * Bind the helper (scope session) to this handler (scope request) + */ + public void setWizardHelper(WizardHelper helper) { + _helper = helper; + } + @Override protected void processForm() { +{ +String page = getJettyString("page"); +System.out.println("Action: " + _action + " page: " + page); +} if (_action == null) return; + if (getJettyString("cancelbw") != null) { + cancelNDT(); + return; + } if (getJettyString("next") == null) return; if (_action.equals("blah")) { @@ -44,7 +48,9 @@ public class WizardHandler extends FormHandler { // Saved in CSSHelper, assume success addFormNoticeNoEscape(_t("Console language saved.")); } - if ("6".equals(page)) { + if ("4".equals(page)) { + startNDT(); + } else if ("6".equals(page)) { Map<String, String> changes = new HashMap<String, String>(); boolean updated = updateRates(changes); if (updated) { @@ -116,120 +122,25 @@ public class WizardHandler extends FormHandler { return updated; } - public synchronized boolean isNDTComplete() { - return _listener != null && _listener.isComplete(); - } - - public synchronized boolean isNDTRunning() { - return _listener != null && !_listener.isComplete(); - } - - /** - * @return status string or null - */ - public synchronized String getCompletionStatus() { - return _listener != null ? _listener.getSummary() : null; - } - - /** - * @return status string or null - */ - public synchronized String getDetailStatus() { - return _listener != null ? _listener.getDetail() : null; - } - - /** - * @return bytes per second or 0 - */ - public long getUpBandwidth() { - return getLongResult("up"); - } - - /** - * @return bytes per second or 0 - */ - public long getDownBandwidth() { - return getLongResult("down"); - } - - public synchronized long getLongResult(String key) { - if (_listener != null) { - Map<String, Object> results = _listener.getResults(); - if (results != null) { - Long v = (Long) results.get(key); - if (v != null) - return v.longValue(); - } - } - return 0; - } - /** start the test */ - public synchronized void startNDT() { - if (_mlab.isRunning() || _listener != null && !_listener.isComplete()) { - addFormError(_t("Bandwidth test is already running")); - return; - } - _listener = new TestListener(); - MLabRunner.ToolRun runner = _mlab.runNDT(_listener); - if (runner != null) { + private void startNDT() { + if (_helper == null) { + addFormError("Bad state for test"); + } else if (_helper.startNDT()) { addFormNotice(_t("Started bandwidth test")); } else { - Map<String, Object> map = new HashMap<String, Object>(2); - _listener.complete(map); addFormError(_t("Bandwidth test is already running")); } } /** cancel the test */ - public synchronized void cancelNDT() { - synchronized(WizardHandler.class) { - if (!_mlab.isRunning()) { - addFormError(_t("Bandwidth test was not running")); - return; - } -/**** -TODO - if (runner != null) - addFormNotice(_t("Started bandwidth test")); - else - addFormError(_t("Bandwidth test is already running")); -****/ - } - } - - /** test results */ - private static class TestListener implements MLabRunner.ToolListener { - private String _summary, _detail; - private Map<String, Object> _results; - - public synchronized void reportSummary(String str) { - _summary = str; - } - - public synchronized void reportDetail(String str) { - _detail = str; - } - - public synchronized void complete(Map<String, Object> results) { - _results = results; - } - - public synchronized boolean isComplete() { - return _results != null; - } - - public synchronized String getSummary() { - return _summary; - } - - public synchronized String getDetail() { - return _detail; - } - - public synchronized Map<String, Object> getResults() { - return _results; + private void cancelNDT() { + if (_helper == null) { + addFormError("Bad state for test"); + } else if (_helper.cancelNDT()) { + addFormNotice(_t("Candelled bandwidth test")); + } else { + addFormError(_t("Bandwidth test was not running")); } } - } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHelper.java index c3a326d006..f9ea1c346a 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/WizardHelper.java @@ -1,17 +1,174 @@ package net.i2p.router.web.helpers; +import java.util.HashMap; +import java.util.Map; + +import com.vuze.plugins.mlab.MLabRunner; + +import net.i2p.data.DataHelper; import net.i2p.router.web.HelperBase; /** * The new user wizard. * + * This bean has SESSION scope so the results may be retrieved. + * All necessary methods are synchronized. + * * @since 0.9.38 */ public class WizardHelper extends HelperBase { public static final String PROP_COMPLETE = "routerconsole.welcomeWizardComplete"; + // session scope, but it's an underlying singleton + private MLabRunner _mlab; + + // session scope + private TestListener _listener; + private MLabRunner.ToolRun _runner; + + /** + * Overriden to only do this once. + */ + @Override + public void setContextId(String contextId) { + if (_context == null) { + super.setContextId(contextId); + _mlab = MLabRunner.getInstance(_context); + } + } + public void complete() { _context.router().saveConfig(PROP_COMPLETE, "true"); } + + public synchronized boolean isNDTComplete() { + return _listener != null && _listener.isComplete(); + } + + public synchronized boolean isNDTRunning() { + return _listener != null && !_listener.isComplete(); + } + + /** + * @return HTML-escaped status string or "" + */ + public synchronized String getCompletionStatus() { + String rv = ""; + if (_listener != null) { + String s = _listener.getSummary(); + if (s != null) + s = DataHelper.escapeHTML(s); + } + return rv; + } + + /** + * @return HTML-escaped status string or "" + */ + public synchronized String getDetailStatus() { + String rv = ""; + if (_listener != null) { + String s = _listener.getDetail(); + if (s != null) + s = DataHelper.escapeHTML(s); + } + return rv; + } + + /** + * @return bytes per second or 0 + */ + public long getUpBandwidth() { + return getLongResult("up"); + } + + /** + * @return bytes per second or 0 + */ + public long getDownBandwidth() { + return getLongResult("down"); + } + + public synchronized long getLongResult(String key) { + if (_listener != null) { + Map<String, Object> results = _listener.getResults(); + if (results != null) { + Long v = (Long) results.get(key); + if (v != null) + return v.longValue(); + } + } + return 0; + } + + /** + * Start the test. Called from the Handler. + * @return success + */ + synchronized boolean startNDT() { + if (_mlab.isRunning() || _listener != null && !_listener.isComplete()) { + return false; + } + _listener = new TestListener(); + _runner = _mlab.runNDT(_listener); + if (_runner != null) { + return true; + } else { + Map<String, Object> map = new HashMap<String, Object>(2); + _listener.complete(map); + return false; + } + } + + /** + * Cancel the test. Called from the Handler. + * @return success + */ + synchronized boolean cancelNDT() { + if (!_mlab.isRunning()) { + return false; + } + if (_runner != null) { + _runner.cancel(); + _runner = null; + return true; + } else { + return false; + } + } + + /** test results */ + private static class TestListener implements MLabRunner.ToolListener { + private String _summary, _detail; + private Map<String, Object> _results; + + public synchronized void reportSummary(String str) { + _summary = str; + } + + public synchronized void reportDetail(String str) { + _detail = str; + } + + public synchronized void complete(Map<String, Object> results) { + _results = results; + } + + public synchronized boolean isComplete() { + return _results != null; + } + + public synchronized String getSummary() { + return _summary; + } + + public synchronized String getDetail() { + return _detail; + } + + public synchronized Map<String, Object> getResults() { + return _results; + } + } } diff --git a/apps/routerconsole/jsp/formhandler.jsi b/apps/routerconsole/jsp/formhandler.jsi index e168cc7373..21ced430b0 100644 --- a/apps/routerconsole/jsp/formhandler.jsi +++ b/apps/routerconsole/jsp/formhandler.jsi @@ -50,13 +50,9 @@ // Put all the params in the map, some handlers use this instead of individual setters // We also call all of the setters below. formhandler.setSettings(request.getParameterMap()); -%> -<jsp:setProperty name="formhandler" property="*" /> -<% +%><jsp:setProperty name="formhandler" property="*" /><% } -%> -<jsp:getProperty name="formhandler" property="allMessages" /> -<% +%><jsp:getProperty name="formhandler" property="allMessages" /><% // Only call this once per page, do not getProperty("newNonce") elsewhere, // use the variable instead. diff --git a/apps/routerconsole/jsp/welcome.jsp b/apps/routerconsole/jsp/welcome.jsp index 906040c6b8..a7c9edf950 100644 --- a/apps/routerconsole/jsp/welcome.jsp +++ b/apps/routerconsole/jsp/welcome.jsp @@ -1,4 +1,8 @@ -<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><jsp:useBean class="net.i2p.router.web.helpers.WizardHelper" id="wizhelper" scope="request" /><% +<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><jsp:useBean class="net.i2p.router.web.helpers.WizardHelper" id="wizhelper" scope="session" /><% + // note that for the helper we use a session scope, not a request scope, + // so that we can access the NDT test results. + // The MLabHelper singleton will prevent multiple simultaneous tests, even across sessions. + // page ID final int LAST_PAGE = 7; String pg = request.getParameter("page"); @@ -59,6 +63,7 @@ <%@include file="css.jsi" %> <%=intl.title("New Install Wizard")%> <% + wizhelper.setContextId(i2pcontextId); if (ipg == 4) { %> <script src="/js/ajax.js" type="text/javascript"></script> @@ -84,19 +89,17 @@ %> <h2><%=intl._t("New Install Wizard")%> <%=ipg%>/<%=LAST_PAGE%></h2> <div id="wizard"> -<%-- - // note that for the handler we use a session scope, not a page scope, - // so that we can access the NDT test results. - // The MLabHelper singleton will prevent multiple simultaneous tests, even across sessions. ---%> -<jsp:useBean class="net.i2p.router.web.helpers.WizardHandler" id="formhandler" scope="session" /> +<jsp:useBean class="net.i2p.router.web.helpers.WizardHandler" id="formhandler" scope="request" /> +<% + // Bind the session-scope Helper to the request-scope Handler + formhandler.setWizardHelper(wizhelper); +%> <%@include file="formhandler.jsi" %> <form action="" method="POST"> <input type="hidden" name="nonce" value="<%=pageNonce%>"> <input type="hidden" name="action" value="blah" > <input type="hidden" name="page" value="<%=(ipg + 1)%>" > <% - if (ipg == 1) { // language selection %> @@ -141,7 +144,7 @@ // Bandwidth test in progress (w/ AJAX) %> <h3><%=intl._t("Bandwidth Test in Progress")%></h3> -<p>TODO</p> +<p>Ajax TODO - wait 60 seconds then click next</p> <% } else if (ipg == 5) { @@ -152,9 +155,12 @@ <jsp:setProperty name="nethelper" property="contextId" value="<%=i2pcontextId%>" /> <h3><%=intl._t("Bandwidth Test Results")%></h3> <table class="configtable"> -<tr><td> -Test results go here -</td></tr> +<tr><td><%=intl._t("Test running?")%></td><td><%=wizhelper.isNDTRunning()%></td></tr> +<tr><td><%=intl._t("Test complete?")%></td><td><%=wizhelper.isNDTComplete()%></td></tr> +<tr><td><%=intl._t("Completion status")%></td><td><%=wizhelper.getCompletionStatus()%></td></tr> +<tr><td><%=intl._t("Details")%></td><td><%=wizhelper.getDetailStatus()%></td></tr> +<tr><td><%=intl._t("Upstream Bandwidth")%></td><td><%=net.i2p.data.DataHelper.formatSize2Decimal(wizhelper.getUpBandwidth())%>Bps</td></tr> +<tr><td><%=intl._t("Downstream Bandwidth")%></td><td><%=net.i2p.data.DataHelper.formatSize2Decimal(wizhelper.getDownBandwidth())%>Bps</td></tr> </table> <h3><%=intl._t("Bandwidth Configuration")%></h3> <table id="bandwidthconfig" class="configtable"> @@ -245,6 +251,6 @@ Test results go here <% } %> -</td></tr></table> +</td></tr></table></div> </form> </div></body></html> -- GitLab