Skip to content

Commit 5b3f53b

Browse files
author
Ajay Kannan
committed
---
yaml --- r: 6315 b: refs/heads/tswast-patch-1 c: 235da5a h: refs/heads/master i: 6313: 326479a 6311: 0008d41
1 parent 8077282 commit 5b3f53b

2 files changed

Lines changed: 67 additions & 114 deletions

File tree

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ refs/tags/v0.18.0: 9d193c4c4b9d1c6f21515dd8e50836b9194ec9bb
5757
refs/tags/v0.19.0: e67b56e4d8dad5f9a7b38c9b2107c23c828f2ed5
5858
refs/tags/v0.20.0: 839f7fb7156535146aa1cb2c5aadd8d375d854e8
5959
refs/tags/v0.20.1: 370471f437f1f4f68a11e068df5cd6bf39edb1fa
60-
refs/heads/tswast-patch-1: 39e3d3a18429c814cbd5911bd13caa92510dafdf
60+
refs/heads/tswast-patch-1: 235da5aade459cd24f0b572a8cace8924f455352
6161
refs/heads/pubsub-streaming-pull: 19262b752ee874eb2ca3b950eb2aef44d5a5267b

branches/tswast-patch-1/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/testing/LocalGcdHelper.java

Lines changed: 66 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,23 @@
5454
import java.util.List;
5555
import java.util.Locale;
5656
import java.util.Map;
57-
import java.util.logging.Level;
58-
import java.util.logging.Logger;
5957
import java.util.regex.Pattern;
6058
import java.util.zip.ZipEntry;
6159
import java.util.zip.ZipInputStream;
6260

61+
import java.util.logging.Level;
62+
import java.util.logging.Logger;
63+
6364
/**
6465
* Utility to start and stop local Google Cloud Datastore process.
6566
*/
6667
public class LocalGcdHelper {
68+
6769
private static final Logger log = Logger.getLogger(LocalGcdHelper.class.getName());
6870

6971
private final String projectId;
7072
private Path gcdPath;
71-
private Process startProcess;
7273
private ProcessStreamReader processReader;
73-
private ProcessErrorStreamReader processErrorReader;
7474
private final int port;
7575

7676
public static final String DEFAULT_PROJECT_ID = "projectid1";
@@ -179,134 +179,91 @@ private static Path executablePath(String cmd) {
179179
}
180180

181181
private static class ProcessStreamReader extends Thread {
182-
private final BufferedReader reader;
183-
184-
ProcessStreamReader(InputStream inputStream) {
185-
super("Local GCD InputStream reader");
186-
setDaemon(true);
187-
reader = new BufferedReader(new InputStreamReader(inputStream));
188-
}
189-
190-
void terminate() throws IOException {
191-
reader.close();
192-
}
193-
194-
@Override
195-
public void run() {
196-
try {
197-
while (!(reader.readLine() != null)) {
198-
// consume line
199-
}
200-
} catch (IOException e) {
201-
// ignore
202-
}
203-
}
204-
205-
public static ProcessStreamReader start(InputStream inputStream) {
206-
ProcessStreamReader thread = new ProcessStreamReader(inputStream);
207-
thread.start();
208-
return thread;
209-
}
210-
}
211-
212-
private static class ProcessErrorStreamReader extends Thread {
213-
private static final int LOG_LENGTH_LIMIT = 50000;
214-
private static final String GCD_LOGGING_CLASS =
215-
"com.google.apphosting.client.serviceapp.BaseApiServlet";
216182

183+
private final Process process;
184+
private final BufferedReader reader;
217185
private final BufferedReader errorReader;
218-
private String currentLog = null;
219-
private Level currentLogLevel = null;
220186

221-
ProcessErrorStreamReader(InputStream errorStream, String blockUntil) throws IOException {
222-
super("Local GCD ErrorStream reader");
187+
ProcessStreamReader(
188+
Process process, String blockUntil, boolean blockOnErrorStream) throws IOException {
189+
super("Local GCD InputStream reader");
223190
setDaemon(true);
224-
errorReader = new BufferedReader(new InputStreamReader(errorStream));
191+
this.process = process;
192+
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
193+
errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
225194
if (!Strings.isNullOrEmpty(blockUntil)) {
226195
String line;
227196
do {
228-
line = errorReader.readLine();
197+
if (blockOnErrorStream) {
198+
line = errorReader.readLine();
199+
} else {
200+
line = reader.readLine();
201+
}
229202
} while (line != null && !line.contains(blockUntil));
230203
}
231204
}
232205

233-
void terminate() throws IOException {
234-
writeLog(currentLogLevel, currentLog);
235-
errorReader.close();
206+
void terminate() throws InterruptedException, IOException {
207+
process.destroy();
208+
process.waitFor();
209+
reader.close();
236210
}
237211

238212
@Override
239213
public void run() {
240214
try {
215+
boolean readerDone = false;
241216
boolean errorReaderDone = false;
242-
String previousLine = "";
243-
String currentLine = "";
244-
while (!errorReaderDone) {
245-
previousLine = currentLine;
246-
currentLine = errorReader.readLine();
247-
if (currentLine == null) {
248-
errorReaderDone = true;
249-
} else {
250-
processLogLine(previousLine, currentLine);
217+
String currentLog = null;
218+
while (!readerDone || !errorReaderDone) {
219+
if (!readerDone && reader.ready()) {
220+
readerDone = reader.readLine() == null;
221+
}
222+
if (!errorReaderDone && errorReader.ready()) {
223+
String errorOutput = errorReader.readLine();
224+
if (errorOutput == null) {
225+
errorReaderDone = true;
226+
} else {
227+
currentLog = processLog(errorOutput, currentLog);
228+
}
251229
}
252230
}
253231
} catch (IOException e) {
254232
// ignore
255233
}
256234
}
257235

258-
private void processLogLine(String previousLine, String currentLine) {
259-
// Each gcd log is two lines with the following format:
260-
// [Date] [Time] [GCD_LOGGING_CLASS] [method]
261-
// [LEVEL]: error message
262-
// Exceptions and stack traces are included in gcd error stream, separated by a newline
263-
Level nextLogLevel = getLevel(currentLine);
264-
if (previousLine.contains(GCD_LOGGING_CLASS) && nextLogLevel != null) {
265-
writeLog(currentLogLevel, currentLog);
266-
if (currentLine.startsWith("SEVERE: ")) {
267-
// don't show duplicate error messages from gcd.sh (see issue #258)
268-
currentLog = null;
269-
currentLogLevel = null;
270-
} else {
271-
currentLog = "GCD" + currentLine.split(":", 2)[1] + System.getProperty("line.separator");
272-
currentLogLevel = nextLogLevel;
273-
}
274-
} else if (currentLog != null && currentLog.length() > LOG_LENGTH_LIMIT) {
275-
// log processing may be off, so drop some logs before the string becomes too big
276-
currentLog = null;
277-
currentLogLevel = null;
278-
} else if (currentLog != null && isUsefulLogInfo(currentLine)) {
279-
currentLog += currentLine + System.getProperty("line.separator");
280-
}
236+
private static boolean isNewGcdLog(String line) {
237+
return line.contains("com.google.apphosting.client.serviceapp.BaseApiServlet")
238+
&& !line.trim().startsWith("at ");
281239
}
282240

283-
private static void writeLog(Level level, String msg) {
284-
if (level != null && !Strings.isNullOrEmpty(msg)) {
285-
log.log(level, msg.trim());
286-
}
287-
}
288-
289-
private static boolean isUsefulLogInfo(String line) {
290-
return !line.trim().startsWith("at ") && !line.contains(GCD_LOGGING_CLASS);
291-
}
292-
293-
private static Level getLevel(String line) {
294-
try {
295-
return Level.parse(line.split(":")[0]);
296-
} catch (IllegalArgumentException e) {
297-
return null; // level wasn't supplied in this log line
241+
private static String processLog(String currentLine, String currentLog) {
242+
if (isNewGcdLog(currentLine)) {
243+
if (currentLog != null) {
244+
log.info(currentLog.trim());
245+
}
246+
return "GCD ";
247+
} else if (currentLine.startsWith("SEVERE: ")) {
248+
return null; // Don't show duplicate error messages from gcd.sh
249+
} else if (currentLog != null && currentLine.startsWith("INFO: ")) {
250+
return currentLog + currentLine.substring("INFO: ".length()) + "\n";
251+
} else if (currentLog != null && !currentLine.trim().startsWith("at ")) {
252+
return currentLog + currentLine + "\n";
298253
}
254+
return currentLog;
299255
}
300256

301-
public static ProcessErrorStreamReader start(InputStream errorStream, String blockUntil)
302-
throws IOException {
303-
ProcessErrorStreamReader thread = new ProcessErrorStreamReader(errorStream, blockUntil);
257+
public static ProcessStreamReader start(
258+
Process process, String blockUntil, boolean blockOnErrorStream) throws IOException {
259+
ProcessStreamReader thread = new ProcessStreamReader(process, blockUntil, blockOnErrorStream);
304260
thread.start();
305261
return thread;
306262
}
307263
}
308264

309265
private static class CommandWrapper {
266+
310267
private final List<String> prefix;
311268
private List<String> command;
312269
private String nullFilename;
@@ -477,15 +434,12 @@ private void startGcd(Path executablePath) throws IOException, InterruptedExcept
477434
if (log.isLoggable(Level.FINE)) {
478435
log.log(Level.FINE, "Starting datastore emulator for the project: {0}", projectId);
479436
}
480-
startProcess =
481-
CommandWrapper.create()
482-
.command(gcdAbsolutePath.toString(), "start", "--testing", "--allow_remote_shutdown",
483-
"--port=" + Integer.toString(port), projectId)
484-
.directory(gcdPath)
485-
.start();
486-
processReader = ProcessStreamReader.start(startProcess.getInputStream());
487-
processErrorReader = ProcessErrorStreamReader.start(
488-
startProcess.getErrorStream(), "Dev App Server is now running");
437+
Process startProcess = CommandWrapper.create()
438+
.command(gcdAbsolutePath.toString(), "start", "--testing", "--allow_remote_shutdown",
439+
"--port=" + Integer.toString(port), projectId)
440+
.directory(gcdPath)
441+
.start();
442+
processReader = ProcessStreamReader.start(startProcess, "Dev App Server is now running", true);
489443
}
490444

491445
private static String md5(File gcdZipFile) throws IOException {
@@ -541,9 +495,6 @@ public void stop() throws IOException, InterruptedException {
541495
sendQuitRequest(port);
542496
if (processReader != null) {
543497
processReader.terminate();
544-
processErrorReader.terminate();
545-
startProcess.destroy();
546-
startProcess.waitFor();
547498
}
548499
if (gcdPath != null) {
549500
deleteRecurse(gcdPath);
@@ -555,6 +506,7 @@ private static void deleteRecurse(Path path) throws IOException {
555506
return;
556507
}
557508
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
509+
558510
@Override
559511
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
560512
Files.delete(dir);
@@ -569,7 +521,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
569521
});
570522
}
571523

572-
public static LocalGcdHelper start(String projectId, int port)
524+
public static LocalGcdHelper start(String projectId, int port)
573525
throws IOException, InterruptedException {
574526
LocalGcdHelper helper = new LocalGcdHelper(projectId, port);
575527
helper.start();
@@ -579,14 +531,15 @@ public static LocalGcdHelper start(String projectId, int port)
579531
public static void main(String... args) throws IOException, InterruptedException {
580532
Map<String, String> parsedArgs = parseArgs(args);
581533
String action = parsedArgs.get("action");
582-
int port =
583-
(parsedArgs.get("port") == null) ? DEFAULT_PORT : Integer.parseInt(parsedArgs.get("port"));
534+
int port = (parsedArgs.get("port") == null) ? DEFAULT_PORT
535+
: Integer.parseInt(parsedArgs.get("port"));
584536
switch (action) {
585537
case "START":
586538
if (!isActive(DEFAULT_PROJECT_ID, port)) {
587539
LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, port);
588540
try (FileWriter writer = new FileWriter(".local_gcd_helper")) {
589-
writer.write(helper.gcdPath.toAbsolutePath().toString() + System.lineSeparator());
541+
writer.write(
542+
helper.gcdPath.toAbsolutePath().toString() + System.lineSeparator());
590543
writer.write(Integer.toString(port));
591544
}
592545
}

0 commit comments

Comments
 (0)