org.unitime.timetable.onlinesectioning.OnlineSectioningLogger.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.onlinesectioning.OnlineSectioningLogger.java

Source

/*
 * UniTime 3.2 - 3.5 (University Timetabling Application)
 * Copyright (C) 2011 - 2013, UniTime LLC, and individual contributors
 * as indicated by the @authors tag.
 * 
 * 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; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * 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, see <http://www.gnu.org/licenses/>.
 * 
*/
package org.unitime.timetable.onlinesectioning;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.CacheMode;
import org.unitime.timetable.defaults.ApplicationProperty;
import org.unitime.timetable.model.Session;
import org.unitime.timetable.model.Student;
import org.unitime.timetable.model.dao.OnlineSectioningLogDAO;
import org.unitime.timetable.model.dao.SessionDAO;
import org.unitime.timetable.model.dao.StudentDAO;

/**
 * @author Tomas Muller
 */
public class OnlineSectioningLogger extends Thread {
    private static Log sLog = LogFactory.getLog(OnlineSectioningLogger.class);
    private List<OnlineSectioningLog.Action> iActions = new Vector<OnlineSectioningLog.Action>();
    private boolean iActive = false;
    private boolean iEnabled = false;
    private int iLogLimit = -1;
    private PrintWriter iOut = null;

    private static OnlineSectioningLogger sInstance = null;

    public static OnlineSectioningLogger getInstance() {
        if (sInstance == null)
            startLogger();
        return sInstance;
    }

    public static void startLogger() {
        if (sInstance == null) {
            sInstance = new OnlineSectioningLogger();
            sInstance.start();
        }
    }

    public static void stopLogger() {
        if (sInstance != null) {
            sInstance.iActive = false;
            sInstance.interrupt();
            try {
                sInstance.join();
            } catch (InterruptedException e) {
            }
            sInstance = null;
        }
    }

    private OnlineSectioningLogger() {
        super("OnlineSectioningLogger");
        setDaemon(true);
        iEnabled = ApplicationProperty.OnlineSchedulingLoggingEnabled.isTrue();
        iLogLimit = ApplicationProperty.OnlineSchedulingLogLimit.intValue();
        try {
            if (ApplicationProperty.OnlineSchedulingLogFile.value() != null)
                iOut = new PrintWriter(
                        new FileWriter(new File(ApplicationProperty.OnlineSchedulingLogFile.value()), true));
        } catch (IOException e) {
            sLog.warn("Unable to create sectioning log: " + e.getMessage(), e);
        }
    }

    public boolean isEnabled() {
        return iEnabled;
    }

    public void setEnabled(boolean enabled) {
        iEnabled = enabled;
    }

    public boolean isActive() {
        return iActive;
    }

    public void record(OnlineSectioningLog.Log log) {
        if (log == null || !isEnabled() || !isActive())
            return;
        for (OnlineSectioningLog.Action action : log.getActionList()) {
            if (action.hasStartTime() && action.hasStudent() && action.hasOperation() && action.hasSession()) {
                synchronized (iActions) {
                    if (iLogLimit <= 0 || iActions.size() < iLogLimit)
                        iActions.add(action);
                }
                if (iOut != null) {
                    synchronized (iOut) {
                        iOut.print(OnlineSectioningLog.Log.newBuilder().addAction(action).build().toString());
                        iOut.flush();
                    }
                }
            }
        }
    }

    public void run() {
        sLog.info("Online Sectioning Logger is up.");
        try {
            iActive = true;
            while (true) {
                try {
                    sleep(60000);
                } catch (InterruptedException e) {
                }
                List<OnlineSectioningLog.Action> actionsToSave = null;
                synchronized (iActions) {
                    if (!iActions.isEmpty()) {
                        actionsToSave = new ArrayList<OnlineSectioningLog.Action>(iActions);
                        iActions.clear();
                    }
                }
                try {
                    if (actionsToSave != null) {
                        sLog.debug("Persisting " + actionsToSave.size() + " actions...");
                        if (iLogLimit > 0 && actionsToSave.size() >= iLogLimit)
                            sLog.warn("The limit of " + iLogLimit
                                    + " unpersisted log messages was reached, some messages have been dropped.");
                        org.hibernate.Session hibSession = OnlineSectioningLogDAO.getInstance().createNewSession();
                        hibSession.setCacheMode(CacheMode.IGNORE);
                        try {
                            Hashtable<Long, Session> sessions = new Hashtable<Long, Session>();
                            for (OnlineSectioningLog.Action q : actionsToSave) {
                                org.unitime.timetable.model.OnlineSectioningLog log = new org.unitime.timetable.model.OnlineSectioningLog();
                                log.setAction(q.toByteArray());
                                log.setOperation(q.getOperation());
                                String studentExternalId = (q.getStudent().hasExternalId()
                                        ? q.getStudent().getExternalId()
                                        : null);
                                if (studentExternalId == null || studentExternalId.isEmpty()) {
                                    Student student = StudentDAO.getInstance().get(q.getStudent().getUniqueId(),
                                            hibSession);
                                    if (student == null)
                                        continue;
                                    studentExternalId = student.getExternalUniqueId();
                                }
                                log.setStudent(studentExternalId);
                                log.setTimeStamp(new Date(q.getStartTime()));
                                if (q.hasResult())
                                    log.setResult(q.getResult().getNumber());
                                if (q.hasUser() && q.getUser().hasExternalId())
                                    log.setUser(q.getUser().getExternalId());
                                Long sessionId = q.getSession().getUniqueId();
                                Session session = sessions.get(sessionId);
                                if (session == null) {
                                    session = SessionDAO.getInstance().get(sessionId, hibSession);
                                    sessions.put(sessionId, session);
                                }
                                log.setSession(session);
                                hibSession.save(log);
                            }
                            hibSession.flush();
                        } finally {
                            hibSession.close();
                        }
                    }
                } catch (Throwable t) {
                    sLog.warn("Failed to save " + actionsToSave.size() + " log actions: " + t.getMessage(), t);
                }
                if (!iActive)
                    break;
            }
        } catch (Throwable t) {
            sLog.error("Online Sectioning Logger failed: " + t.getMessage(), t);
        } finally {
            iActive = false;
            if (iOut != null) {
                iOut.flush();
                iOut.close();
            }
        }
        sLog.info("Online Sectioning Logger is down.");
    }

}