summaryrefslogtreecommitdiffstats
path: root/clustercontroller-utils/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'clustercontroller-utils/src/main/java')
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClient.java16
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClientWithBase.java39
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/JsonAsyncHttpClient.java59
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/LoggingAsyncHttpClient.java43
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/ProxyAsyncHttpClient.java30
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/RequestQueue.java87
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/SyncHttpClient.java11
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/TimeoutHandler.java151
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/FakeClock.java38
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/SettableClock.java11
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/TestTransport.java187
11 files changed, 0 insertions, 672 deletions
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClient.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClient.java
deleted file mode 100644
index 6af3e4de759..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClient.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-
-/**
- * Abstraction of an asynchronous HTTP client, such that applications don't need to depend directly on an HTTP client.
- */
-public interface AsyncHttpClient<V extends HttpResult> {
-
- AsyncOperation<V> execute(HttpRequest r);
-
- /** Attempt to cancel all pending operations and shut down the client. */
- void close();
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClientWithBase.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClientWithBase.java
deleted file mode 100644
index d824303df57..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/AsyncHttpClientWithBase.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-
-public class AsyncHttpClientWithBase<V extends HttpResult> implements AsyncHttpClient<V> {
-
- protected final AsyncHttpClient<V> client;
- private HttpRequest baseRequest = new HttpRequest();
-
- public AsyncHttpClientWithBase(AsyncHttpClient<V> client) {
- if (client == null) throw new IllegalArgumentException("HTTP client must be set.");
- this.client = client;
- }
-
- /**
- * If all your http requests have common features you want to set once, you can provide those values in a base
- * request. For instance, if you specify a host and a port using this function, all your requests will use that
- * host and port unless specified in the request you execute.
- */
- public void setHttpRequestBase(HttpRequest r) {
- this.baseRequest = (r == null ? new HttpRequest() : r.clone());
- }
-
- public HttpRequest getHttpRequestBase() {
- return baseRequest;
- }
-
- @Override
- public AsyncOperation<V> execute(HttpRequest r) {
- return client.execute(baseRequest.merge(r));
- }
-
- @Override
- public void close() {
- client.close();
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/JsonAsyncHttpClient.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/JsonAsyncHttpClient.java
deleted file mode 100644
index dac4decc1ee..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/JsonAsyncHttpClient.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.RedirectedAsyncOperation;
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
-
-/**
- * Wrapped for the HTTP client, converting requests to/from JSON.
- */
-public class JsonAsyncHttpClient implements AsyncHttpClient<JsonHttpResult> {
-
- private AsyncHttpClient<HttpResult> client;
- private boolean verifyRequestContentAsJson = true;
- private boolean addJsonContentType = true;
-
- public JsonAsyncHttpClient(AsyncHttpClient<HttpResult> client) {
- this.client = client;
- }
-
- public JsonAsyncHttpClient verifyRequestContentAsJson(boolean doIt) {
- verifyRequestContentAsJson = doIt;
- return this;
- }
-
- public JsonAsyncHttpClient addJsonContentType(boolean doIt) {
- addJsonContentType = doIt;
- return this;
- }
-
- public AsyncOperation<JsonHttpResult> execute(HttpRequest r) {
- if (verifyRequestContentAsJson) {
- if (r.getPostContent() != null && !(r.getPostContent() instanceof JSONObject)) {
- try{
- r = r.clone().setPostContent(new JSONObject(r.getPostContent().toString()));
- } catch (JSONException e) {
- throw new IllegalArgumentException(e);
- }
- }
- }
- if (addJsonContentType && r.getPostContent() != null) {
- r = r.clone().addHttpHeader("Content-Type", "application/json");
- }
- final AsyncOperation<HttpResult> op = client.execute(r);
- return new RedirectedAsyncOperation<HttpResult, JsonHttpResult>(op) {
- @Override
- public JsonHttpResult getResult() {
- return (op.getResult() == null ? null : new JsonHttpResult(op.getResult()));
- }
- };
- }
-
- @Override
- public void close() {
- client.close();
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/LoggingAsyncHttpClient.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/LoggingAsyncHttpClient.java
deleted file mode 100644
index 2d967223f9e..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/LoggingAsyncHttpClient.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.PipedAsyncOperation;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class LoggingAsyncHttpClient<T extends HttpResult> extends AsyncHttpClientWithBase<T> {
-
- private static final Logger log = Logger.getLogger(LoggingAsyncHttpClient.class.getName());
- private int requestCounter = 0;
-
- public LoggingAsyncHttpClient(AsyncHttpClient<T> client) {
- super(client);
- log.info("Logging HTTP requests if fine logging level is added");
- }
-
- public AsyncOperation<T> execute(HttpRequest r) {
- final int requestCount = ++requestCounter;
- log.fine("Issuing HTTP request " + requestCount + ": " + r.toString(true));
- final AsyncOperation<T> op = client.execute(r);
- return new PipedAsyncOperation<T, T>(op) {
- @Override
- public T convertResult(T result) {
- if (log.isLoggable(Level.FINE)) {
- if (op.isSuccess()) {
- log.fine("HTTP request " + requestCount + " completed: " + result.toString(true));
- } else {
- StringWriter sw = new StringWriter();
- op.getCause().printStackTrace(new PrintWriter(sw));
- log.fine("HTTP request " + requestCount + " failed: " + sw);
- }
- }
- return result;
- }
- };
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/ProxyAsyncHttpClient.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/ProxyAsyncHttpClient.java
deleted file mode 100644
index 3d6658ae366..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/ProxyAsyncHttpClient.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-
-public class ProxyAsyncHttpClient<V extends HttpResult> extends AsyncHttpClientWithBase<V> {
-
- private final String proxyHost;
- private final int proxyPort;
-
- public ProxyAsyncHttpClient(AsyncHttpClient<V> client, String proxyHost, int proxyPort) {
- super(client);
- this.proxyHost = proxyHost;
- this.proxyPort = proxyPort;
- }
-
- @Override
- public AsyncOperation<V> execute(HttpRequest r) {
- r = getHttpRequestBase().merge(r);
- if (r.getHost() == null || r.getPath() == null) {
- throw new IllegalStateException("Host and path must be set prior to being able to proxy an HTTP request");
- }
- StringBuilder path = new StringBuilder().append(r.getHost());
- if (r.getPort() != 0) path.append(':').append(r.getPort());
- if (r.getPath().isEmpty() || r.getPath().charAt(0) != '/') path.append('/');
- path.append(r.getPath());
- return client.execute(r.setHost(proxyHost).setPort(proxyPort).setPath(path.toString()));
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/RequestQueue.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/RequestQueue.java
deleted file mode 100644
index 2a3af5724ab..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/RequestQueue.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncCallback;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-
-import java.util.LinkedList;
-import java.util.logging.Logger;
-
-/**
- * Utility class to schedule HTTP requests and keeping a maximum amount of them pending at a time.
- */
-public class RequestQueue<V extends HttpResult> {
-
- private static final Logger log = Logger.getLogger(RequestQueue.class.getName());
- private final AsyncHttpClient<V> httpClient;
- private final LinkedList<Request<V>> requestQueue = new LinkedList<>();
- private final int maxPendingRequests;
- private int pendingRequests = 0;
-
- public RequestQueue(AsyncHttpClient<V> httpClient, int maxPendingRequests) {
- this.httpClient = httpClient;
- this.maxPendingRequests = maxPendingRequests;
- }
-
- public boolean empty() {
- synchronized (requestQueue) {
- return (requestQueue.isEmpty() && pendingRequests == 0);
- }
- }
-
- public void waitUntilEmpty() throws InterruptedException {
- synchronized (requestQueue) {
- while (!empty()) {
- requestQueue.wait();
- }
- }
- }
-
- public void schedule(HttpRequest request, AsyncCallback<V> callback) {
- log.fine("Scheduling " + request + " call");
- synchronized (requestQueue) {
- requestQueue.addLast(new Request<>(request, callback));
- sendMore();
- }
- }
-
- private void sendMore() {
- while (pendingRequests < maxPendingRequests && !requestQueue.isEmpty()) {
- Request<V> call = requestQueue.removeFirst();
- log.fine("Sending " + call.getRequest() + ".");
- ++pendingRequests;
- AsyncOperation<V> op = httpClient.execute(call.getRequest());
- op.register(call);
- }
- }
-
- private class Request<V extends HttpResult> implements AsyncCallback<V> {
- private final HttpRequest request;
- private final AsyncCallback<V> callback;
-
- Request(HttpRequest request, AsyncCallback<V> callback) {
- this.request = request;
- this.callback = callback;
- }
-
- public HttpRequest getRequest() { return request; }
-
- @Override
- public void done(AsyncOperation<V> op) {
- if (op.isSuccess()) {
- log.fine("Operation " + op.getName() + " completed successfully");
- } else {
- log.fine("Operation " + op.getName() + " failed: " + op.getCause());
- }
- synchronized (requestQueue) {
- --pendingRequests;
- }
- callback.done(op);
- synchronized (requestQueue) {
- requestQueue.notifyAll();
- sendMore();
- }
- }
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/SyncHttpClient.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/SyncHttpClient.java
deleted file mode 100644
index b8890550dc6..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/SyncHttpClient.java
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-public interface SyncHttpClient {
-
- HttpResult execute(HttpRequest r);
-
- /** Attempt to cancel all pending operations and shut down the client. */
- void close();
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/TimeoutHandler.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/TimeoutHandler.java
deleted file mode 100644
index eae7e15541b..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/communication/http/TimeoutHandler.java
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.communication.http;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncCallback;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperationImpl;
-import com.yahoo.vespa.clustercontroller.utils.util.Clock;
-
-import java.util.*;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
-import java.util.logging.Logger;
-
-public class TimeoutHandler<V extends HttpResult> extends AsyncHttpClientWithBase<V> {
-
- public static class InternalRequest<V extends HttpResult> extends AsyncOperationImpl<V> {
- final AsyncOperation<V> operation;
- long startTime;
- long timeout;
-
- public InternalRequest(AsyncOperation<V> op, long startTime, long timeout) {
- super(op.getName(), op.getDescription());
- this.operation = op;
- this.startTime = startTime;
- this.timeout = timeout;
- op.register(new AsyncCallback<V>() {
- @Override
- public void done(AsyncOperation<V> op) {
- if (!isDone()) {
- if (op.isSuccess()) {
- setResult(op.getResult());
- } else {
- setFailure(op.getCause(), op.getResult());
- }
- }
- }
- });
- }
-
- public long getTimeoutTime() { return startTime + timeout; }
-
- public void handleTimeout(long currentTime) {
- long timePassed = currentTime - startTime;
- this.setFailure(new TimeoutException("Operation timeout. " + timePassed + " ms since operation was issued. Timeout was " + timeout + " ms."));
- operation.cancel();
- }
-
- @Override
- public boolean cancel() { return operation.cancel(); }
- @Override
- public boolean isCanceled() { return operation.isCanceled(); }
- @Override
- public Double getProgress() { return (isDone() ? Double.valueOf(1.0) : operation.getProgress()); }
- }
-
- public static class ChangeLogger {
- private InternalRequest lastTimeoutLogged = null;
- private boolean emptyLogged = true;
-
- public void logChanges(TreeMap<Long, InternalRequest> requests) {
- if (requests.isEmpty()) {
- if (!emptyLogged) {
- log.finest("No more pending requests currently.");
- emptyLogged = true;
- }
- } else {
- emptyLogged = false;
- InternalRequest r = requests.firstEntry().getValue();
- if (lastTimeoutLogged == null || !lastTimeoutLogged.equals(r)) {
- lastTimeoutLogged = r;
- log.finest("Next operation to possibly timeout will do so at " + r.getTimeoutTime());
- }
- }
- }
- }
-
- private final static Logger log = Logger.getLogger(TimeoutHandler.class.getName());
- private final TreeMap<Long, InternalRequest> requests = new TreeMap<>();
- private final ChangeLogger changeLogger = new ChangeLogger();
- private final Clock clock;
- private boolean run = true;
- private Runnable timeoutHandler = new Runnable() {
- @Override
- public void run() {
- log.fine("Starting timeout monitor thread");
- while (true) {
- performTimeoutHandlerTick();
- synchronized (clock) {
- try{ clock.wait(100); } catch (InterruptedException e) {}
- if (!run) break;
- }
- }
- log.fine("Stopped timeout monitor thread");
- }
- };
-
- public TimeoutHandler(Executor executor, Clock clock, AsyncHttpClient<V> client) {
- super(client);
- this.clock = clock;
- executor.execute(timeoutHandler);
- }
-
- @Override
- public void close() {
- synchronized (clock) {
- run = false;
- clock.notifyAll();
- }
- synchronized (requests) {
- for (InternalRequest r : requests.values()) {
- r.operation.cancel();
- r.setFailure(new TimeoutException("Timeout handler shutting down. Shutting down all requests monitored."));
- }
- requests.clear();
- }
- }
-
- @Override
- public AsyncOperation<V> execute(HttpRequest r) {
- AsyncOperation<V> op = super.execute(r);
- InternalRequest<V> request = new InternalRequest<>(op, clock.getTimeInMillis(), r.getTimeoutMillis());
- synchronized (requests) {
- requests.put(request.getTimeoutTime(), request);
- }
- return request;
- }
-
- void performTimeoutHandlerTick() {
- synchronized (requests) {
- removeCompletedRequestsFromTimeoutList();
- handleTimeoutsAtTime(clock.getTimeInMillis());
- changeLogger.logChanges(requests);
- }
- }
-
- private void removeCompletedRequestsFromTimeoutList() {
- while (!requests.isEmpty() && requests.firstEntry().getValue().operation.isDone()) {
- requests.remove(requests.firstEntry().getKey());
- log.finest("Removed completed request from operation timeout list.");
- }
- }
-
- private void handleTimeoutsAtTime(long currentTime) {
- Map<Long, InternalRequest> timeouts = requests.subMap(0l, currentTime + 1);
- for (InternalRequest r : timeouts.values()) {
- r.handleTimeout(currentTime);
- requests.values().remove(r);
- }
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/FakeClock.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/FakeClock.java
deleted file mode 100644
index 80f06b62675..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/FakeClock.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.test;
-
-import java.util.logging.Logger;
-
-/**
- * Unit tests want to fast forward time to avoid waiting for time to pass
- */
-public class FakeClock extends SettableClock {
-
- private static final Logger logger = Logger.getLogger(FakeClock.class.getName());
- protected long currentTime = 1;
-
- @Override
- public long getTimeInMillis() {
- return currentTime;
- }
-
- @Override
- public void adjust(long adjustment) {
- synchronized (this) {
- logger.fine("Adjusting clock, adding " + adjustment + " ms to it.");
- currentTime += adjustment;
- notifyAll();
- }
- }
-
- @Override
- public void set(long newTime) {
- synchronized (this) {
- if (newTime < currentTime) {
- // throw new IllegalArgumentException("Clock attempted to be set to go backwards");
- }
- currentTime = newTime;
- }
- }
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/SettableClock.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/SettableClock.java
deleted file mode 100644
index 12b398709f0..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/SettableClock.java
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.test;
-
-import com.yahoo.vespa.clustercontroller.utils.util.Clock;
-
-public abstract class SettableClock extends Clock {
-
- public abstract void set(long newTime);
- public abstract void adjust(long adjustment);
-
-}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/TestTransport.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/TestTransport.java
deleted file mode 100644
index 87ecd127e44..00000000000
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/test/TestTransport.java
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.clustercontroller.utils.test;
-
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperation;
-import com.yahoo.vespa.clustercontroller.utils.communication.async.AsyncOperationImpl;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.AsyncHttpClient;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequest;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequestHandler;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpResult;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-/**
- * This class is a utility for unit tests.. You can register HttpRequestHandler instances in it, and then
- * you can extract an AsyncHttpClient&lt;HttpResult&gt; instance from it, which you can use to talk to the
- * registered servers. Thus you can do end to end testing of components talking over HTTP without actually
- * going through HTTP if you are using the HTTP abstraction layer in communication.http package.
- */
-public class TestTransport {
-
- private static final Logger log = Logger.getLogger(TestTransport.class.getName());
- private static class Handler {
- HttpRequestHandler handler;
- String pathPrefix;
- Handler(HttpRequestHandler h, String prefix) { this.handler = h; this.pathPrefix = prefix; }
- }
- private static class Socket {
- public final String hostname;
- public final int port;
-
- Socket(String hostname, int port) {
- this.hostname = hostname;
- this.port = port;
- }
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Socket)) return false;
- Socket other = (Socket) o;
- return (hostname.equals(other.hostname) && port == other.port);
- }
- @Override
- public int hashCode() {
- return hostname.hashCode() * port;
- }
- }
- private static class Request {
- public final HttpRequest request;
- public final AsyncOperationImpl<HttpResult> result;
-
- Request(HttpRequest r, AsyncOperationImpl<HttpResult> rr) {
- this.request = r;
- this.result = rr;
- }
- }
- private final Map<Socket, List<Handler>> handlers = new HashMap<>();
- private final LinkedList<Request> requests = new LinkedList<>();
- private final AsyncHttpClient<HttpResult> client = new AsyncHttpClient<HttpResult>() {
- @Override
- public AsyncOperation<HttpResult> execute(HttpRequest r) {
- log.fine("Queueing request " + r);
- if (r.getHttpOperation() == null) {
- r = r.clone();
- r.setHttpOperation(r.getPostContent() == null ? HttpRequest.HttpOp.GET : HttpRequest.HttpOp.POST);
- }
- r.verifyComplete();
- AsyncOperationImpl<HttpResult> op = new AsyncOperationImpl<>(r.toString());
- synchronized (requests) {
- requests.addLast(new Request(r, op));
- }
- return op;
- }
- @Override
- public void close() { TestTransport.this.close(); }
- };
- private boolean running = true;
- private final Thread workerThread = new Thread() {
- @Override
- public void run() {
- while (running) {
- synchronized (requests) {
- if (requests.isEmpty()) {
- try {
- requests.wait(100);
- } catch (InterruptedException e) { return; }
- } else {
- Request request = requests.removeFirst();
- HttpRequest r = request.request;
- log.fine("Processing request " + r);
- HttpRequestHandler handler = getHandler(r);
- if (handler == null) {
- if (log.isLoggable(Level.FINE)) {
- log.fine("Failed to find target for request " + r.toString(true));
- log.fine("Existing handlers:");
- for (Socket socket : handlers.keySet()) {
- log.fine(" Socket " + socket.hostname + ":" + socket.port);
- for (Handler h : handlers.get(socket)) {
- log.fine(" " + h.pathPrefix);
- }
- }
- }
- request.result.setResult(new HttpResult().setHttpCode(
- 404, "No such server socket with suitable path prefix found open"));
- } else {
- try{
- request.result.setResult(handler.handleRequest(r));
- } catch (Exception e) {
- HttpResult result = new HttpResult().setHttpCode(500, e.getMessage());
- StringWriter sw = new StringWriter();
- e.printStackTrace(new PrintWriter(sw));
- result.setContent(sw.toString());
- request.result.setResult(result);
- }
- }
- //log.fine("Request " + r.toString(true) + " created result " + request.getSecond().getResult().toString(true));
- }
- }
- }
- }
- };
-
- public TestTransport() {
- workerThread.start();
- }
-
- public void close() {
- if (!running) return;
- running = false;
- synchronized (requests) { requests.notifyAll(); }
- try {
- workerThread.join();
- } catch (InterruptedException e) {}
- }
-
- /** Get an HTTP client that talks to this test transport layer. */
- public AsyncHttpClient<HttpResult> getClient() { return client; }
-
- private HttpRequestHandler getHandler(HttpRequest r) {
- Socket socket = new Socket(r.getHost(), r.getPort());
- synchronized (this) {
- List<Handler> handlerList = handlers.get(socket);
- if (handlerList == null) {
- log.fine("No socket match");
- return null;
- }
- log.fine("Socket found");
- for (Handler h : handlers.get(socket)) {
- if (r.getPath().length() >= h.pathPrefix.length() && r.getPath().substring(0, h.pathPrefix.length()).equals(h.pathPrefix)) {
- return h.handler;
- }
- }
- log.fine("No path prefix match");
- }
- return null;
- }
-
- public void addServer(HttpRequestHandler server, String hostname, int port, String pathPrefix) {
- Socket socket = new Socket(hostname, port);
- synchronized (this) {
- List<Handler> shandlers = handlers.get(socket);
- if (shandlers == null) {
- shandlers = new LinkedList<>();
- handlers.put(socket, shandlers);
- }
- shandlers.add(new Handler(server, pathPrefix));
- }
- }
-
- public void removeServer(HttpRequestHandler server, String hostname, int port, String pathPrefix) {
- Socket socket = new Socket(hostname, port);
- synchronized (this) {
- List<Handler> shandlers = handlers.get(socket);
- if (shandlers == null) return;
- for (Handler h : shandlers) {
- if (h.handler == server && h.pathPrefix.equals(pathPrefix)) {
- shandlers.remove(h);
- }
- }
- }
- }
-
-}