package cz.cuni.mff.d3s.been.hostruntime.task;
import static cz.cuni.mff.d3s.been.socketworks.NamedSockets.TASK_LOG_0MQ;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.exec.LogOutputStream;
import cz.cuni.mff.d3s.been.core.TaskMessageType;
import cz.cuni.mff.d3s.been.logging.LogMessage;
import cz.cuni.mff.d3s.been.logging.TaskLogMessage;
import cz.cuni.mff.d3s.been.mq.MessageQueues;
import cz.cuni.mff.d3s.been.util.JSONUtils;
import cz.cuni.mff.d3s.been.util.JsonException;
/**
*
* Processes output from a task line by line.
*
* A line is converted to a {@link LogMessage} and request to a queue for
* processing.
*
* // TODO This implementation is suboptimal since it uses
* {@link MessageQueues#send(String, java.io.Serializable)}.
*
*
* @author Martin Sixta
*/
public class TaskStdInOutHandler extends LogOutputStream {
/**
* UNIX line separator
*/
public static final char UNIX_LINE_SEPARATOR = '\n';
private final String taskId;
private final String contextId;
private final String benchmarkId;
private final String name;
private final MessageQueues messageQueues;
private final JSONUtils jsonUtils;
private final OutputStream secondRedirectOutputStream;
/**
* Creates new TaskStdInOutHandler
*
* @param taskId
* ID of tha task
* @param contextId
* context ID of the task
* @param benchmarkId
* benchmark ID of the task
* @param name
* task's name
* @param secondRedirectOutputStream
* where to redirect output
*/
public TaskStdInOutHandler(
String taskId,
String contextId,
String benchmarkId,
String name,
OutputStream secondRedirectOutputStream) {
this.taskId = taskId;
this.contextId = contextId;
this.benchmarkId = benchmarkId;
this.name = name;
this.messageQueues = MessageQueues.getInstance();
this.jsonUtils = JSONUtils.newInstance();
this.secondRedirectOutputStream = secondRedirectOutputStream;
}
@Override
protected void processLine(String line, int level) {
try {
secondRedirectOutputStream.write((line + UNIX_LINE_SEPARATOR).getBytes());
} catch (Throwable t) {
t.printStackTrace();
}
// Fabricate a log message
// Send it
try {
String json = createJsonLogMessage(line, level);
messageQueues.send(TASK_LOG_0MQ.getName(), createTypedMessage(json));
} catch (Throwable t) {
t.printStackTrace();
}
}
private String createJsonLogMessage(String line, int level) throws JsonException {
TaskLogMessage logMsg = new TaskLogMessage().withMessage(new LogMessage(name, level, line));
logMsg.withTaskId(taskId).withContextId(contextId).withBenchmarkId(benchmarkId);
return jsonUtils.serialize(logMsg);
}
private String createTypedMessage(String json) {
return String.format("%s#%s", TaskMessageType.LOG_MESSAGE.toString(), json);
}
@Override
public void close() throws IOException {
super.close();
secondRedirectOutputStream.close();
}
}