Introduce BlockingHttpEndpoint.
diff --git a/src/com/facebook/buck/cli/BUCK b/src/com/facebook/buck/cli/BUCK
index 34c27d8..6b8f806 100644
--- a/src/com/facebook/buck/cli/BUCK
+++ b/src/com/facebook/buck/cli/BUCK
@@ -54,6 +54,7 @@
'//src/com/facebook/buck/util:constants',
'//src/com/facebook/buck/util:exceptions',
'//src/com/facebook/buck/util:io',
+ '//src/com/facebook/buck/util:network',
'//src/com/facebook/buck/util:util',
'//src/com/facebook/buck/util/environment:environment',
'//src/com/facebook/buck/timing:timing',
diff --git a/src/com/facebook/buck/cli/Main.java b/src/com/facebook/buck/cli/Main.java
index fecf397..6c93040 100644
--- a/src/com/facebook/buck/cli/Main.java
+++ b/src/com/facebook/buck/cli/Main.java
@@ -465,6 +465,8 @@
loadListenersFromBuckConfig(eventListenersBuilder, projectFilesystem, config);
+
+
ImmutableList<BuckEventListener> eventListeners = eventListenersBuilder.build();
for (BuckEventListener eventListener : eventListeners) {
@@ -472,6 +474,7 @@
}
JavaUtilsLoggingBuildListener.ensureLogFileIsWritten();
+
return eventListeners;
}
diff --git a/src/com/facebook/buck/event/listener/BUCK b/src/com/facebook/buck/event/listener/BUCK
index 0ab6760..8f78998 100644
--- a/src/com/facebook/buck/event/listener/BUCK
+++ b/src/com/facebook/buck/event/listener/BUCK
@@ -20,8 +20,8 @@
'//src/com/facebook/buck/util:constants',
'//src/com/facebook/buck/util:exceptions',
'//src/com/facebook/buck/util/environment:environment',
- '//src/com/facebook/buck/util:network',
'//src/com/facebook/buck/util:io',
+ '//src/com/facebook/buck/util:network',
'//src/com/facebook/buck/util:util',
],
visibility = [
diff --git a/src/com/facebook/buck/util/BUCK b/src/com/facebook/buck/util/BUCK
index d3623bf..37b372c 100644
--- a/src/com/facebook/buck/util/BUCK
+++ b/src/com/facebook/buck/util/BUCK
@@ -51,6 +51,7 @@
)
NETWORK_SRCS = [
+ 'BlockingHttpEndpoint.java',
'HttpEndpoint.java',
]
java_library(
diff --git a/src/com/facebook/buck/util/BlockingHttpEndpoint.java b/src/com/facebook/buck/util/BlockingHttpEndpoint.java
new file mode 100644
index 0000000..6c3c3c7
--- /dev/null
+++ b/src/com/facebook/buck/util/BlockingHttpEndpoint.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.facebook.buck.util;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * HttpEndpoint implementation which only allows a certain number of concurrent requests to be in
+ * flight at any given point in time.
+ */
+public class BlockingHttpEndpoint implements HttpEndpoint {
+
+ public static final int DEFAULT_COMMON_TIMEOUT_MS = 5000;
+
+ private URL url;
+ private int timeout = DEFAULT_COMMON_TIMEOUT_MS;
+ private final ListeningExecutorService requestService;
+
+ public BlockingHttpEndpoint(String url, int maxParallelRequests) throws MalformedURLException {
+ this.url = new URL(url);
+
+ // Create an ExecutorService that blocks after N requests are in flight. Taken from
+ // http://www.springone2gx.com/blog/billy_newport/2011/05/there_s_more_to_configuring_threadpools_than_thread_pool_size
+ LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(maxParallelRequests);
+ ExecutorService executor = new ThreadPoolExecutor(maxParallelRequests,
+ maxParallelRequests,
+ 2L,
+ TimeUnit.MINUTES,
+ workQueue,
+ new ThreadPoolExecutor.CallerRunsPolicy());
+ requestService = MoreExecutors.listeningDecorator(executor);
+ }
+
+ @Override
+ public ListenableFuture<?> post(String content) throws IOException {
+ HttpURLConnection connection = buildConnection("POST");
+ connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+ return send(connection, content);
+ }
+
+ private ListenableFuture<?> send(final HttpURLConnection connection, final String content) {
+ return requestService.submit(new Runnable() {
+ @Override
+ public void run() {
+ try (DataOutputStream out = new DataOutputStream(connection.getOutputStream())) {
+ out.writeBytes(content);
+ out.flush();
+ out.close();
+ try (InputStream response = connection.getInputStream()) {
+ ByteStreams.copy(response, ByteStreams.nullOutputStream());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ private HttpURLConnection buildConnection(String httpMethod) throws IOException {
+ HttpURLConnection connection = (HttpURLConnection) this.url.openConnection();
+ connection.setUseCaches(false);
+ connection.setDoOutput(true);
+ connection.setConnectTimeout(timeout);
+ connection.setReadTimeout(timeout);
+ connection.setRequestMethod(httpMethod);
+ return connection;
+ }
+}
diff --git a/src/com/facebook/buck/util/HttpEndpoint.java b/src/com/facebook/buck/util/HttpEndpoint.java
index c8e144d..5053545 100644
--- a/src/com/facebook/buck/util/HttpEndpoint.java
+++ b/src/com/facebook/buck/util/HttpEndpoint.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-present Facebook, Inc.
+ * Copyright 2013-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
@@ -13,74 +13,13 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
+
package com.facebook.buck.util;
-import com.google.common.base.Charsets;
+import com.google.common.util.concurrent.ListenableFuture;
-import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.Map;
-/**
- * HTTP POST things to a commonly used endpoint.
- */
-public class HttpEndpoint {
-
- public static final int DEFAULT_COMMON_TIMEOUT_MS = 5000;
-
- private URL url;
- private int timeout = DEFAULT_COMMON_TIMEOUT_MS;
-
- public HttpEndpoint(String url) throws IOException {
- this.url = new URL(url);
- }
-
- public InputStream post(Map<String,Object> params) throws IOException {
- return post(encodeParameters(params));
- }
-
- public InputStream post(String content) throws IOException {
- HttpURLConnection connection = buildConnection("POST");
- connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
- return send(connection, content);
- }
-
- private InputStream send(HttpURLConnection connection, String content) throws IOException {
- DataOutputStream out = new DataOutputStream(connection.getOutputStream());
- out.writeBytes(content);
- out.flush();
- out.close();
- return connection.getInputStream();
- }
-
- private HttpURLConnection buildConnection(String httpMethod) throws IOException {
- HttpURLConnection connection = (HttpURLConnection) this.url.openConnection();
- connection.setUseCaches(false);
- connection.setDoOutput(true);
- connection.setConnectTimeout(timeout);
- connection.setReadTimeout(timeout);
- connection.setRequestMethod(httpMethod);
- return connection;
- }
-
- private static String encodeParameters(Map<String,Object> params)
- throws UnsupportedEncodingException {
- String content = "";
- for (Object key : params.keySet()) {
- Object value = params.get(key);
- String ukey = URLEncoder.encode((String) key, String.valueOf(Charsets.UTF_8));
- String uvalue = URLEncoder.encode(String.valueOf(value), String.valueOf(Charsets.UTF_8));
- content += ukey + "=" + uvalue + "&";
- }
- return content.substring(0, content.length()-1);
- }
-
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
+public interface HttpEndpoint {
+ ListenableFuture<?> post(String content) throws IOException;
}
diff --git a/test/com/facebook/buck/event/listener/BUCK b/test/com/facebook/buck/event/listener/BUCK
index 66cf52a..2212b4e 100644
--- a/test/com/facebook/buck/event/listener/BUCK
+++ b/test/com/facebook/buck/event/listener/BUCK
@@ -27,6 +27,7 @@
'//src/com/facebook/buck/util:constants',
'//src/com/facebook/buck/util:io',
'//src/com/facebook/buck/util/environment:environment',
+ '//src/com/facebook/buck/util:network',
'//test/com/facebook/buck/event:testutil',
'//test/com/facebook/buck/model:BuildTargetFactory',
'//test/com/facebook/buck/rules:testutil',