blob: a98e29994504aaff363d3a734c8fa63af0d32f30 [file] [log] [blame]
package com.gemstone.gemfire.internal.process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.logging.log4j.Logger;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.util.StopWatch;
/**
* Reads the InputStream per-byte instead of per-line. Uses BufferedReader.ready()
* to ensure that calls to read() will not block. Uses continueReadingMillis to
* continue reading after the Process terminates in order to fully read the last
* of that Process' output (such as a stack trace).
*
* @author Kirk Lund
* @since 8.2
*/
public final class NonBlockingProcessStreamReader extends ProcessStreamReader {
private static final Logger logger = LogService.getLogger();
/** millis to continue reading after Process terminates in order to fully read the last of its output */
private final long continueReadingMillis;
protected NonBlockingProcessStreamReader(final Builder builder) {
super(builder);
continueReadingMillis = builder.continueReadingMillis;
}
@Override
public void run() {
final boolean isDebugEnabled = logger.isDebugEnabled();
if (isDebugEnabled) {
logger.debug("Running {}", this);
}
StopWatch continueReading = new StopWatch();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
boolean ready = false;
int ch = 0;
while (ch != -1) {
while ((ready = reader.ready()) && (ch = reader.read()) != -1) {
sb.append((char)ch);
if ((char)ch == '\n') {
this.inputListener.notifyInputLine(sb.toString());
sb = new StringBuilder();
}
}
if (!ready) {
if (!ProcessUtils.isProcessAlive(process)) {
if (!continueReading.isRunning()) {
continueReading.start();
} else if (continueReading.elapsedTimeMillis() > continueReadingMillis) {
return;
}
}
Thread.sleep(10);
}
}
} catch (IOException e) {
if (isDebugEnabled) {
logger.debug("Failure reading from buffered input stream: {}", e.getMessage(), e);
}
} catch (InterruptedException e) {
if (isDebugEnabled) {
logger.debug("Interrupted reading from buffered input stream: {}", e.getMessage(), e);
}
} finally {
try {
reader.close();
} catch (IOException e) {
if (isDebugEnabled) {
logger.debug("Failure closing buffered input stream reader: {}", e.getMessage(), e);
}
}
if (isDebugEnabled) {
logger.debug("Terminating {}", this);
}
}
}
}