package edu.stanford.nlp.sempre.interactive;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
import org.testng.collections.Lists;
import edu.stanford.nlp.sempre.Json;
import fig.basic.LogInfo;
import fig.basic.Option;
import fig.basic.OptionsParser;
import fig.exec.Execution;
/**
* utilites for simulating a session through the server
*
* @author sidaw
*/
class GZIPFiles {
/**
* Get a lazily loaded stream of lines from a gzipped file, similar to
* {@link Files#lines(java.nio.file.Path)}.
*
* @param path
* The path to the gzipped file.
* @return stream with lines.
*/
public static Stream<String> lines(Path path) {
InputStream fileIs = null;
BufferedInputStream bufferedIs = null;
GZIPInputStream gzipIs = null;
try {
fileIs = Files.newInputStream(path);
// Even though GZIPInputStream has a buffer it reads individual bytes
// when processing the header, better add a buffer in-between
bufferedIs = new BufferedInputStream(fileIs, 65535);
gzipIs = new GZIPInputStream(bufferedIs);
} catch (IOException e) {
closeSafely(gzipIs);
closeSafely(bufferedIs);
closeSafely(fileIs);
throw new UncheckedIOException(e);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipIs));
return reader.lines().onClose(() -> closeSafely(reader));
}
private static void closeSafely(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// Ignore
}
}
}
}
public class Simulator implements Runnable {
@Option
public static String serverURL = "http://localhost:8410";
@Option
public static int numThreads = 1;
@Option
public static int verbose = 1;
@Option
public static boolean useThreads = false;
@Option
public static long maxQueries = Long.MAX_VALUE;
@Option
public static String reqParams = "grammar=0&cite=0&learn=0";
@Option
public static List<String> logFiles = null;
public void readQueries() {
// T.printAllRules();
// A.assertAll();
for (String fileName : logFiles) {
long startTime = System.nanoTime();
Stream<String> stream;
try {
if (fileName.endsWith(".gz"))
stream = GZIPFiles.lines(Paths.get(fileName));
else
stream = Files.lines(Paths.get(fileName));
List<String> lines = stream.collect(Collectors.toList());
LogInfo.logs("Reading %s (%d lines)", fileName, lines.size());
int numLinesRead = 0;
// ExecutorService executor = new ThreadPoolExecutor(numThreads,
// numThreads,
// 15000, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>());
ExecutorService executor = Executors.newSingleThreadExecutor();
for (String l : lines) {
numLinesRead++;
if (numLinesRead > maxQueries)
break;
LogInfo.logs("Line %d", numLinesRead);
if (!useThreads) {
executeLine(l);
} else {
Future<?> future = executor.submit(() -> executeLine(l));
try {
future.get(10, TimeUnit.MINUTES);
} catch (Throwable t) {
t.printStackTrace();
} finally {
future.cancel(true); // may or may not desire this
long endTime = System.nanoTime();
LogInfo.logs("Took %d ns or %.4f s", (endTime - startTime), (endTime - startTime) / 1.0e9);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
SimulationAnalyzer.flush();
}
static void executeLine(String l) {
Map<String, Object> json = null;
try {
json = Json.readMapHard(l);
} catch (RuntimeException e) {
LogInfo.logs("Json cannot be read from %s: %s", l, e.toString());
return;
}
Object command = json.get("q");
if (command == null) // to be backwards compatible
command = json.get("log");
Object sessionId = json.get("sessionId");
if (sessionId == null) // to be backwards compatible
sessionId = json.get("id");
try {
String response = sempreQuery(command.toString(), sessionId.toString());
SimulationAnalyzer.addStats(json, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
public static String sempreQuery(String query, String sessionId) throws UnsupportedEncodingException {
String params = "q=" + URLEncoder.encode(query, "UTF-8");
params += String.format("&sessionId=%s&%s", sessionId, reqParams);
// params = URLEncoder.encode(params);
String url = String.format("%s/sempre?", serverURL);
// LogInfo.log(params);
// LogInfo.log(query);
String response = executePost(url + params, "");
// LogInfo.log(response);
return response;
}
public static String executePost(String targetURL, String urlParameters) {
HttpURLConnection connection = null;
try {
// Create connection
URL url = new URL(targetURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoOutput(true);
// Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.close();
// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
StringBuilder response = new StringBuilder(); // or StringBuffer if Java
// version 5+
String line;
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
public static void main(String[] args) {
OptionsParser parser = new OptionsParser();
Simulator simulator = new Simulator();
// parser.register("", opts);
Execution.run(args, "Simulator", simulator, parser);
}
@Override
public void run() {
LogInfo.logs("setting numThreads %d", numThreads);
readQueries();
}
}