package de.ugoe.cs.autoquest.htmlmonitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import de.ugoe.cs.util.console.Console;
/**
*
* The log manager handles different {@link HtmlMonitorOutputWriter}s to perform the logging
* of recorded messages. It initializes a new writer if the first message for a specific
* client is received and it closes a writer if for a specific period of time no further message
* of the same client was received. The writers themselves consider log rotation. For handling
* messages, the {@link HtmlMonitorMessageListener} mechanism provided by the
* {@link HtmlMonitorServer} is used.
*
*
* @author Patrick Harms
*/
class HtmlMonitorLogManager implements HtmlMonitorComponent, HtmlMonitorMessageListener {
/**
* the timeout after which a writer of an inactive client is closed
*/
private static final int SESSION_TIMEOUT = 100000;
/**
* the directory into which the log files shall be written
*/
private String logFileBaseDir;
/**
* the mapping of client ids to the respective writers.
*/
private Map writers;
/**
* a timer used to detect client timouts
*/
private Timer logFileMonitorTimer;
/**
*
* initializes the log manager with the directory into which the log files shall be stored
*
*
* @param logFileBaseDir the directory into which the log files shall be stored
*/
HtmlMonitorLogManager(String logFileBaseDir) {
this.logFileBaseDir = logFileBaseDir;
}
/* (non-Javadoc)
* @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#init()
*/
@Override
public synchronized void init() throws IllegalStateException, HtmlMonitorException {
if (writers != null) {
throw new IllegalStateException("already initialized");
}
writers = new HashMap();
logFileMonitorTimer = new Timer();
}
/* (non-Javadoc)
* @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#start()
*/
@Override
public synchronized void start() throws IllegalStateException, HtmlMonitorException {
if (writers == null) {
throw new IllegalStateException("not initialized");
}
logFileMonitorTimer.schedule
(new LogFileMonitorTimerTask(), SESSION_TIMEOUT / 2, SESSION_TIMEOUT / 2);
}
/* (non-Javadoc)
* @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#stop()
*/
@Override
public synchronized void stop() {
if (writers != null) {
logFileMonitorTimer.cancel();
for (HtmlMonitorOutputWriter writer : writers.values()) {
writer.stop();
}
}
writers = null;
}
/* (non-Javadoc)
* @see HtmlMonitoringListener#handleEvents(HtmlClientInfos, HtmlEvent[])
*/
@Override
public void handleMessage(HtmlClientInfos clientInfos, HtmlEvent[] events) {
HtmlMonitorOutputWriter writer = writers.get(clientInfos.getClientId());
try {
if (writer == null) {
synchronized (this) {
writer = writers.get(clientInfos.getClientId());
if (writer == null) {
writer =
new HtmlMonitorOutputWriter(logFileBaseDir, clientInfos.getClientId());
writer.init();
writer.start();
writers.put(clientInfos.getClientId(), writer);
}
}
}
writer.handleMessage(clientInfos, events);
}
catch (Exception e) {
Console.printerrln("could not handle message of client " + clientInfos.getClientId() +
": " + e);
Console.logException(e);
// determine, if the writer exists but is not able to log something. In this case,
// destroy the writer (part of the message may be logged twice through this).
writer = writers.get(clientInfos.getClientId());
if (writer != null) {
try {
writer.handleMessage(clientInfos, events);
}
catch (Exception e1) {
synchronized (this) {
writers.remove(clientInfos.getClientId());
writer.stop();
}
}
}
}
}
/**
*
* internal timer task used for detecting session timeouts of clients
*
*
* @author Patrick Harms
*/
public class LogFileMonitorTimerTask extends TimerTask {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
synchronized (HtmlMonitorLogManager.this) {
List timeoutSessions = new ArrayList();
for (Map.Entry entry : writers.entrySet()) {
HtmlMonitorOutputWriter writer = entry.getValue();
if (System.currentTimeMillis() - writer.getLastUpdate() > SESSION_TIMEOUT) {
timeoutSessions.add(entry.getKey());
}
}
for (String clientId : timeoutSessions) {
HtmlMonitorOutputWriter writer = writers.remove(clientId);
writer.stop();
}
}
}
}
}