/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library 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
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.impl.support;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import org.ccnx.ccn.impl.CCNNetworkManager;
/**
* Main ccnd command line daemon.
* Allows start & stop of ccnd, as well as interactive runs.
*
* TODO This is not actually yet used in any tests and therefore is itself not well tested
*/
public class CCNDaemon extends Daemon {
public static final String PROP_CCND_COMMAND = "ccnd.command";
public static final String PROP_CCND_DEBUG = "ccnd.debug";
private static final String DEFAULT_CCND_COMMAND_STRING = "../ccnd/agent/ccnd";
protected String _command = DEFAULT_CCND_COMMAND_STRING;
protected Process _ccndProcess = null;
protected CCNDaemon _daemon = null;
/**
* Stop ccnd on exit from daemon
*/
protected class CCNDShutdownHook extends Thread {
public void run() {
if (_ccndProcess != null)
_ccndProcess.destroy();
}
}
protected class CCNDWorkerThread extends Daemon.WorkerThread {
private static final long serialVersionUID = -6093561895394961537L;
protected boolean _shutdown = false;
protected CCNDWorkerThread(String daemonName) {
super(daemonName);
}
public void work() {
synchronized(this) {
boolean interrupted = false;
do {
try {
interrupted = false;
wait();
} catch (InterruptedException e) {
interrupted = true;
}
} while (interrupted && !_shutdown);
}
}
/**
* Start ccnd but set up a shutdown hook to allow it to stop
*/
public void initialize() {
String commandVal = System.getProperty(PROP_CCND_COMMAND);
if (commandVal != null) {
_command = commandVal;
}
Runtime.getRuntime().addShutdownHook(new CCNDShutdownHook());
ProcessBuilder pb = new ProcessBuilder(_command);
Map<String, String> env = pb.environment();
pb.redirectErrorStream(true);
String portval = System.getProperty(CCNNetworkManager.PROP_AGENT_PORT);
if (portval != null) {
env.put("CCN_LOCAL_PORT", portval);
}
String debugVal = System.getProperty(PROP_CCND_DEBUG);
if (debugVal != null) {
env.put("CCND_DEBUG", debugVal);
}
try {
_ccndProcess = pb.start();
} catch (IOException e) {
Log.logStackTrace(Level.WARNING, e);
e.printStackTrace();
}
String outputFile = System.getProperty(PROP_DAEMON_OUTPUT);
if (outputFile != null) {
try {
new DaemonOutput(_ccndProcess.getInputStream(), new FileOutputStream(outputFile, true));
} catch (FileNotFoundException e) {
Log.logStackTrace(Level.WARNING, e);
e.printStackTrace();
}
}
}
public void finish() {
synchronized (this) {
_shutdown = true;
notify();
}
}
public boolean signal(String name) {
return false;
}
public Object status(String type) {
return "running";
}
}
public CCNDaemon() {
super();
// This is a daemon: it should not do anything in the
// constructor but everything in the initialize() method
// which will be run in the process that will finally
// execute as the daemon, rather than in the launching
// and stopping processes also.
_daemonName = "ccnd";
_daemon = this;
}
protected void initialize(String[] args, Daemon daemon) {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-command")) {
_command = args[i + 1];
}
}
}
protected WorkerThread createWorkerThread() {
return new CCNDWorkerThread(daemonName());
}
protected void usage() {
try {
String msg = "usage: " + this.getClass().getName() + "[-start | -stop | -interactive | -signal <signal>] [-command <command>]";
System.out.println(msg);
Log.severe(msg);
} catch (Exception e) {
e.printStackTrace();
Log.logStackTrace(Level.SEVERE, e);
}
System.exit(1);
}
public static void main(String[] args) {
CCNDaemon daemon = null;
try {
daemon = new CCNDaemon();
runDaemon(daemon, args);
} catch (Exception e) {
System.err.println("Error attempting to start daemon.");
Log.warning("Error attempting to start daemon.");
Log.warningStackTrace(e);
}
}
}