diff --git a/arbiter/arbiter-ui/src/main/java/org/deeplearning4j/arbiter/ui/module/ArbiterModule.java b/arbiter/arbiter-ui/src/main/java/org/deeplearning4j/arbiter/ui/module/ArbiterModule.java index 6bcf3acbd..dab0174df 100644 --- a/arbiter/arbiter-ui/src/main/java/org/deeplearning4j/arbiter/ui/module/ArbiterModule.java +++ b/arbiter/arbiter-ui/src/main/java/org/deeplearning4j/arbiter/ui/module/ArbiterModule.java @@ -51,6 +51,7 @@ import org.deeplearning4j.ui.components.text.style.StyleText; import org.deeplearning4j.ui.i18n.I18NResource; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; +import org.nd4j.common.function.Function; import org.nd4j.common.primitives.Pair; import org.nd4j.shade.jackson.core.JsonProcessingException; @@ -140,29 +141,89 @@ public class ArbiterModule implements UIModule { (path, rc) -> rc.response().end(multiSession ? "true" : "false"))); if (multiSession) { r.add(new Route("/arbiter", HttpMethod.GET, (path, rc) -> this.listSessions(rc))); + r.add(new Route("/arbiter/:sessionId", HttpMethod.GET, (path, rc) -> rc.response() + .putHeader("content-type", "text/html; charset=utf-8") + .sendFile("templates/ArbiterUI.html"))); + + r.add(new Route("/arbiter/:sessionId/lastUpdate", HttpMethod.GET, (path, rc) -> { + if (knownSessionIDs.containsKey(path.get(0))) { + this.getLastUpdateTime(path.get(0), rc); + } else { + sessionNotFound(path.get(0), rc.request().path(), rc); + } + })); + r.add(new Route("/arbiter/:sessionId/candidateInfo/:id", HttpMethod.GET, (path, rc) -> { + if (knownSessionIDs.containsKey(path.get(0))) { + this.getCandidateInfo(path.get(0), path.get(1), rc); + } else { + sessionNotFound(path.get(0), rc.request().path(), rc); + } + })); + r.add(new Route("/arbiter/:sessionId/config", HttpMethod.GET, (path, rc) -> { + if (knownSessionIDs.containsKey(path.get(0))) { + this.getOptimizationConfig(path.get(0), rc); + } else { + sessionNotFound(path.get(0), rc.request().path(), rc); + } + })); + r.add(new Route("/arbiter/:sessionId/results", HttpMethod.GET, (path, rc) -> { + if (knownSessionIDs.containsKey(path.get(0))) { + this.getSummaryResults(path.get(0), rc); + } else { + sessionNotFound(path.get(0), rc.request().path(), rc); + } + })); + r.add(new Route("/arbiter/:sessionId/summary", HttpMethod.GET, (path, rc) -> { + if (knownSessionIDs.containsKey(path.get(0))) { + this.getSummaryStatus(path.get(0), rc); + } else { + sessionNotFound(path.get(0), rc.request().path(), rc); + } + })); } else { r.add(new Route("/arbiter", HttpMethod.GET, (path, rc) -> rc.response() .putHeader("content-type", "text/html; charset=utf-8") .sendFile("templates/ArbiterUI.html"))); - r.add(new Route("/arbiter/lastUpdate", HttpMethod.GET, (path, rc) -> this.getLastUpdateTime(rc))); - r.add(new Route("/arbiter/lastUpdate/:ids", HttpMethod.GET, - (path, rc) -> this.getModelLastUpdateTimes(path.get(0), rc))); + r.add(new Route("/arbiter/lastUpdate", HttpMethod.GET, (path, rc) -> this.getLastUpdateTime(null, rc))); r.add(new Route("/arbiter/candidateInfo/:id", HttpMethod.GET, - (path, rc) -> this.getCandidateInfo(path.get(0), rc))); - r.add(new Route("/arbiter/config", HttpMethod.GET, (path, rc) -> this.getOptimizationConfig(rc))); - r.add(new Route("/arbiter/results", HttpMethod.GET, (path, rc) -> this.getSummaryResults(rc))); - r.add(new Route("/arbiter/summary", HttpMethod.GET, (path, rc) -> this.getSummaryStatus(rc))); + (path, rc) -> this.getCandidateInfo(null, path.get(0), rc))); + r.add(new Route("/arbiter/config", HttpMethod.GET, (path, rc) -> this.getOptimizationConfig(null, rc))); + r.add(new Route("/arbiter/results", HttpMethod.GET, (path, rc) -> this.getSummaryResults(null, rc))); + r.add(new Route("/arbiter/summary", HttpMethod.GET, (path, rc) -> this.getSummaryStatus(null, rc))); - r.add(new Route("/arbiter/sessions/all", HttpMethod.GET, (path, rc) -> this.sessionInfo(rc))); r.add(new Route("/arbiter/sessions/current", HttpMethod.GET, (path, rc) -> this.currentSession(rc))); r.add(new Route("/arbiter/sessions/set/:to", HttpMethod.GET, (path, rc) -> this.setSession(path.get(0), rc))); } + // common for single- and multi-session mode + r.add(new Route("/arbiter/sessions/all", HttpMethod.GET, (path, rc) -> this.sessionInfo(rc))); return r; } + /** + * Load StatsStorage via provider, or return "not found" + * + * @param sessionId session ID to look fo with provider + * @param targetPath one of overview / model / system, or null + * @param rc routing context + */ + private void sessionNotFound(String sessionId, String targetPath, RoutingContext rc) { + Function loader = VertxUIServer.getInstance().getStatsStorageLoader(); + if (loader != null && loader.apply(sessionId)) { + if (targetPath != null) { + rc.reroute(targetPath); + } else { + rc.response().end(); + } + } else { + rc.response().setStatusCode(HttpResponseStatus.NOT_FOUND.code()) + .end("Unknown session ID: " + sessionId); + } + } + + /** * List optimization sessions. Returns a HTML list of arbiter sessions */ @@ -182,7 +243,7 @@ public class ArbiterModule implements UIModule { if (!knownSessionIDs.isEmpty()) { sb.append("