diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
index 28dc131..1fb16fa 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
@@ -5,17 +5,7 @@
*/
package br.ufrgs.inf.prosoft.requestssimulator;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.function.Consumer;
-import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.stream.Stream;
/**
*
@@ -29,60 +19,21 @@ public class Main {
System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [RequestsSimulator] %5$s %n");
String path = null;
+ int users = 1;
if (args.length < 1) {
- System.err.println("<RequestsPath>");
+ System.err.println("<RequestsPath> [<users>]");
System.exit(1);
} else {
path = args[0];
- }
-
- try (Stream<String> lines = Files.lines(Paths.get(path))) {
- long count = Files.lines(Paths.get(path)).count();
- logger.log(Level.INFO, "requesting {0} URLS", count);
- lines.forEach(new Consumer<String>() {
- private int i = 1;
-
- @Override
- public void accept(String line) {
- try {
- if (line.startsWith("POST")) {
- String[] split = line.split(" ");
- URL url = new URL(split[1]);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("POST");
- connection.setDoOutput(true);
- try (OutputStream outputStream = connection.getOutputStream()) {
- outputStream.write(split[2].getBytes());
- }
- int responseCode = connection.getResponseCode();
- if (responseCode == 200) {
- logger.log(Level.INFO, "{0} {1}", new Object[]{i, line});
- } else {
- logger.log(Level.SEVERE, "{0} error {1} on {2}", new Object[]{i, responseCode, line});
- }
- connection.disconnect();
- } else {
- URL url = new URL(line);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("GET");
- int responseCode = connection.getResponseCode();
- if (responseCode == 200) {
- logger.log(Level.INFO, "{0} GET {1}", new Object[]{i, line});
- } else {
- logger.log(Level.SEVERE, "{0} error {1} on {2}", new Object[]{i, responseCode, line});
- }
- connection.disconnect();
- }
- } catch (MalformedURLException ex) {
- logger.log(Level.SEVERE, "Malormed URL");
- } catch (IOException ex) {
- logger.log(Level.SEVERE, "IOException");
- }
- i++;
+ if (args.length == 2) {
+ try {
+ users = Integer.valueOf(args[1]);
+ } catch (NumberFormatException ex) {
+ System.err.println("<users> must be a number");
+ System.exit(1);
}
- });
- } catch (IOException ex) {
- logger.log(Level.SEVERE, "cannot open file {0}", path);
+ }
}
+ Simulator.simulate(path, users);
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java
new file mode 100644
index 0000000..fb67c0a
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java
@@ -0,0 +1,148 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.requestssimulator;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Stream;
+
+/**
+ *
+ * @author romulo
+ */
+public class Simulator {
+
+ private static final Logger logger = Logger.getLogger(Simulator.class.getName());
+
+ public static final void simulate(String path) {
+ simulate(path, 1);
+ }
+
+ public static final void simulate(String path, int users) {
+ if (users < 1) {
+ logger.log(Level.SEVERE, "informed {0} users. Using 1", users);
+ users = 1;
+ }
+ try {
+ long count = Files.lines(Paths.get(path)).count();
+ logger.log(Level.INFO, "requesting {0} URLS", count);
+ if (users == 1) {
+ Stream<String> lines = Files.lines(Paths.get(path));
+ lines.forEach(new RequestProcesser());
+ } else {
+ List<String> requests = Files.readAllLines(Paths.get(path));
+ int requestsSize = requests.size();
+ int inclusiveStart = 0;
+ int partitionSize = requestsSize / users;
+ if (partitionSize < 1) {
+ partitionSize = 1;
+ logger.log(Level.SEVERE, "more users {0} than requests {1}. Using {1} users", new Object[]{users, requests.size()});
+ }
+ Collection<Thread> threads = new ArrayList<>();
+ while (inclusiveStart < requestsSize) {
+ int exclusiveEnd = inclusiveStart + partitionSize;
+ Thread thread = new Thread(new PartitionProcesser(requests, inclusiveStart, exclusiveEnd));
+ thread.start();
+ threads.add(thread);
+ inclusiveStart = exclusiveEnd;
+ }
+ threads.forEach(thread -> {
+ try {
+ thread.join();
+ } catch (InterruptedException ex) {
+ logger.log(Level.SEVERE, "thread stopped");
+ }
+ });
+ }
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, "cannot open file {0}", path);
+ }
+ }
+
+ private static class RequestProcesser implements Consumer<String> {
+
+ private int i;
+
+ public RequestProcesser() {
+ this.i = 1;
+ }
+
+ public RequestProcesser(int i) {
+ this.i = i;
+ }
+
+ @Override
+ public void accept(String line) {
+ try {
+ if (line.startsWith("POST")) {
+ String[] split = line.split(" ");
+ URL url = new URL(split[1]);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(true);
+ try (OutputStream outputStream = connection.getOutputStream()) {
+ outputStream.write(split[2].getBytes());
+ }
+ int responseCode = connection.getResponseCode();
+ if (responseCode == 200) {
+ logger.log(Level.INFO, "{0} {1}", new Object[]{i, line});
+ } else {
+ logger.log(Level.SEVERE, "{0} error {1} on {2}", new Object[]{i, responseCode, line});
+ }
+ connection.disconnect();
+ } else {
+ URL url = new URL(line);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ int responseCode = connection.getResponseCode();
+ if (responseCode == 200) {
+ logger.log(Level.INFO, "{0} GET {1}", new Object[]{i, line});
+ } else {
+ logger.log(Level.SEVERE, "{0} error {1} on {2}", new Object[]{i, responseCode, line});
+ }
+ connection.disconnect();
+ }
+ } catch (MalformedURLException ex) {
+ logger.log(Level.SEVERE, "Malormed URL");
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, "IOException");
+ }
+ i++;
+ }
+ }
+
+ private static class PartitionProcesser implements Runnable {
+
+ private final Stream<String> requests;
+ private final int inclusiveStart;
+
+ public PartitionProcesser(List<String> requests, int incusiveStart, int exclusiveEnd) {
+ this.inclusiveStart = incusiveStart;
+ this.requests = requests.subList(incusiveStart, exclusiveEnd).stream();
+ }
+
+ public PartitionProcesser(Stream<String> requests) {
+ this.requests = requests;
+ this.inclusiveStart = 1;
+ }
+
+ @Override
+ public void run() {
+ this.requests.forEach(new RequestProcesser(this.inclusiveStart + 1));
+ }
+ }
+}