source: trunk/autoquest-generic-event-monitor/src/main/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorLogManager.java @ 2155

Last change on this file since 2155 was 2155, checked in by pharms, 7 years ago
  • Property svn:mime-type set to text/plain
File size: 6.7 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.genericeventmonitor;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21import java.util.Timer;
22import java.util.TimerTask;
23
24import de.ugoe.cs.util.console.Console;
25
26/**
27 * <p>
28 * The log manager handles different {@link OutputWriter}s to perform the logging
29 * of recorded events. It initializes a new writer if the first event set for a specific
30 * client is received and it closes a writer if for a specific period of time no further message
31 * of the same client was received. The writers themselves consider log rotation. For handling
32 * messages, the {@link GenericEventMonitorMessageListener} mechanism provided by the
33 * {@link GenericEventMonitorServer} is used.
34 * </p>
35 *
36 * @author Patrick Harms
37 */
38class GenericEventMonitorLogManager
39    implements GenericEventMonitorComponent, GenericEventMonitorMessageListener
40{
41   
42    /**
43     * the timeout after which a writer of an inactive client is closed
44     */
45    private static final int SESSION_TIMEOUT = 10 * 60 * 1000;
46   
47    /**
48     * the directory into which the log files shall be written
49     */
50    private String logFileBaseDir;
51
52    /**
53     * the mapping of client ids to the respective writers.
54     */
55    private Map<String, OutputWriter> writers;
56
57    /**
58     * a timer used to detect client timeouts
59     */
60    private Timer logFileMonitorTimer;
61
62    /**
63     * <p>
64     * initializes the log manager with the directory into which the log files shall be stored
65     * </p>
66     *
67     * @param logFileBaseDir the directory into which the log files shall be stored
68     */
69    GenericEventMonitorLogManager(String logFileBaseDir) {
70        this.logFileBaseDir = logFileBaseDir;
71    }
72
73    /* (non-Javadoc)
74     * @see de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitorComponent#init()
75     */
76    @Override
77    public synchronized void init() throws IllegalStateException, GenericEventMonitorException {
78        if (writers != null) {
79            throw new IllegalStateException("already initialized");
80        }
81       
82        writers = new HashMap<String, OutputWriter>();
83        logFileMonitorTimer = new Timer();
84    }
85
86    /* (non-Javadoc)
87     * @see de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitorComponent#start()
88     */
89    @Override
90    public synchronized void start() throws IllegalStateException, GenericEventMonitorException {
91        if (writers == null) {
92            throw new IllegalStateException("not initialized");
93        }
94       
95        logFileMonitorTimer.schedule
96            (new LogFileMonitorTimerTask(), SESSION_TIMEOUT / 2, SESSION_TIMEOUT / 2);
97    }
98
99    /* (non-Javadoc)
100     * @see de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitorComponent#stop()
101     */
102    @Override
103    public synchronized void stop() {
104        if (writers != null) {
105            logFileMonitorTimer.cancel();
106           
107            for (OutputWriter writer : writers.values()) {
108                writer.stop();
109            }
110        }
111       
112        writers = null;
113    }
114
115    /* (non-Javadoc)
116     * @see GenericEventMonitorMessageListener#handleEvents(ClientInfos, GenericEvent[])
117     */
118    @Override
119    public void handleEvents(ClientInfos          clientInfos,
120                             GenericEvent[]       events)
121    {
122        OutputWriter writer = writers.get(clientInfos.getAppId() + clientInfos.getClientId());
123       
124        try {
125            if (writer == null) {
126                synchronized (this) {
127                    writer = writers.get(clientInfos.getAppId() + clientInfos.getClientId());
128                    if (writer == null) {
129                        writer = new OutputWriter(logFileBaseDir,
130                                                  clientInfos.getAppId(),
131                                                  clientInfos.getClientId());
132
133                        writer.init();
134                        writer.start();
135                        writers.put(clientInfos.getAppId() + clientInfos.getClientId(), writer);
136                    }
137                }
138            }
139
140            writer.handleEvents(clientInfos, events);
141        }
142        catch (Exception e) {
143            Console.printerrln("could not handle message of client " + clientInfos.getClientId() +
144                               " for app " + clientInfos.getAppId() + ": " + e);
145            e.printStackTrace();
146            Console.logException(e);
147           
148            // determine, if the writer exists but is not able to log something. In this case,
149            // destroy the writer (part of the message may be logged twice through this).
150            writer = writers.get(clientInfos.getClientId());
151            if (writer != null) {
152                try {
153                    writer.handleEvents(clientInfos, events);
154                }
155                catch (Exception e1) {
156                    synchronized (this) {
157                        writers.remove(clientInfos.getClientId());
158                        writer.stop();
159                    }
160                }
161            }
162        }
163    }
164
165    /**
166     * <p>
167     * internal timer task used for detecting session timeouts of clients
168     * </p>
169     *
170     * @author Patrick Harms
171     */
172    public class LogFileMonitorTimerTask extends TimerTask {
173
174        /* (non-Javadoc)
175         * @see java.lang.Runnable#run()
176         */
177        @Override
178        public void run() {
179            synchronized (GenericEventMonitorLogManager.this) {
180                List<String> timeoutSessions = new ArrayList<String>();
181                for (Map.Entry<String, OutputWriter> entry : writers.entrySet()) {
182                    OutputWriter writer = entry.getValue();
183                   
184                    if (System.currentTimeMillis() - writer.getLastUpdate() > SESSION_TIMEOUT) {
185                        timeoutSessions.add(entry.getKey());
186                    }
187                }
188               
189                for (String sessionId : timeoutSessions) {
190                    OutputWriter writer = writers.remove(sessionId);
191                    writer.stop();
192                }
193            }
194        }
195
196    }
197
198}
Note: See TracBrowser for help on using the repository browser.