com.bigdata.counters.ActiveProcess Maven / Gradle / Ivy
/*
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Mar 26, 2008
*/
package com.bigdata.counters;
import com.bigdata.util.DaemonThreadFactory;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Command manages the execution and termination of a native process and an
* object reading the output of that process.
*
* @author Bryan Thompson
* @version $Id$
*/
public class ActiveProcess {
static protected final Logger log = Logger.getLogger(ActiveProcess.class);
/**
* Used to read {@link #is} and aggregate the performance data reported
* by the {@link #process}.
*/
protected final ExecutorService readService = Executors
.newSingleThreadExecutor(new DaemonThreadFactory(getClass()
.getName()
+ ".readService"));
protected Process process = null;
protected InputStream is = null;
protected volatile Future readerFuture;
// This is used in tests
protected ActiveProcess() {
}
/**
*
* @param command
* The command to be executed. See
* {@link ProcessBuilder#command(List)}.
* @param collector
*/
public ActiveProcess(List command,
AbstractProcessCollector collector) {
if (command == null)
throw new IllegalArgumentException();
if (command.isEmpty())
throw new IllegalArgumentException();
if (collector == null)
throw new IllegalArgumentException();
// log the command that will be run.
{
StringBuilder sb = new StringBuilder();
for (String s : command) {
sb.append( s +" ");
}
if (log.isInfoEnabled())
log.info("command:\n" + sb);
}
try {
ProcessBuilder tmp = new ProcessBuilder(command);
collector.setEnvironment(tmp.environment());
process = tmp.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
/*
* Note: Process is running but the reader on the process output has
* not been started yet!
*/
}
/**
* Attaches the reader to the process, which was started by the ctor and
* is already running.
*
* @param processReader
* The reader.
*/
public void start(AbstractProcessReader processReader) {
log.info("");
if (processReader == null)
throw new IllegalArgumentException();
if (readerFuture != null)
throw new IllegalStateException();
is = process.getInputStream();
assert is != null;
/*
* @todo restart processes if it dies before we shut it down, but no
* more than some #of tries. if the process dies then we will not have
* any data for this host.
*
* @todo this code for monitoring processes is a mess and should
* probably be re-written from scratch. the processReader task
* references the readerFuture via isAlive() but the readerFuture is not
* even assigned until after we submit the processReader task, which
* means that it can be running before the readerFuture is set! The
* concrete implementations of ProcessReaderHelper all poll isAlive()
* until the readerFuture becomes available.
*/
if (log.isInfoEnabled())
log.info("starting process reader: " + processReader);
processReader.start(is);
if (log.isInfoEnabled())
log.info("submitting process reader task: "+processReader);
readerFuture = readService.submit(processReader);
if (log.isInfoEnabled())
log.info("readerFuture: done="+readerFuture.isDone());
}
/**
* Stops the process
*/
public void stop() {
if (readerFuture == null) {
// not running.
return;
}
// attempt to cancel the reader.
readerFuture.cancel(true/* mayInterruptIfRunning */);
// shutdown the thread running the reader.
readService.shutdownNow();
if (process != null) {
// destroy the running process.
process.destroy();
process = null;
is = null;
}
readerFuture = null;
}
/**
* Return true
unless the process is known to be dead.
*/
public boolean isAlive() {
if(readerFuture==null || readerFuture.isDone() || process == null || is == null) {
if (log.isInfoEnabled())
log.info("Not alive: readerFuture="
+ readerFuture
+ (readerFuture != null ? "done="
+ readerFuture.isDone() : "") + ", process="
+ process + ", is=" + is);
return false;
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy