net.fenyo.gnetwatch.activities.MergeQueue.java Source code

Java tutorial

Introduction

Here is the source code for net.fenyo.gnetwatch.activities.MergeQueue.java

Source

/*
 * GNetWatch
 * Copyright 2006, 2007, 2008 Alexandre Fenyo
 * gnetwatch@fenyo.net
 *
 * This file is part of GNetWatch.
 *
 * GNetWatch 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 2 of the License, or
 * (at your option) any later version.
 *
 * GNetWatch 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 GNetWatch; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package net.fenyo.gnetwatch.activities;

import java.util.*;

import net.fenyo.gnetwatch.*;
import net.fenyo.gnetwatch.GUI.*;
import net.fenyo.gnetwatch.actions.*;
import net.fenyo.gnetwatch.data.*;
import net.fenyo.gnetwatch.targets.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;

// memory usage: see jconsole, jps and '-Dcom.sun.management.jmxremote -XX:+AggressiveHeap'

public class MergeQueue extends Queue implements Runnable {
    private static Log log = LogFactory.getLog(MergeQueue.class);

    /**
     * Constructor.
     * @param name queue name.
     * @param config configuration.
     */
    // main thread
    public MergeQueue(final String name, final Config config) {
        super(name, config);
        setDescription(config.getString("dedicated_for_merging"));
    }

    /**
     * Returns the time to wait after each cycle.
     * @param none.
     * @return int time to wait.
     */
    // Queue thread
    protected int getCycleDelay() {
        return 0;
    }

    /**
     * Returns the time to wait between empty cycles.
     * @param none.
     * @return time to wait.
     */
    // Queue thread
    protected int getEmptyCycleDelay() {
        return 60 * 60 * 1000; // every one hour
        //    return 5000;
    }

    /**
     * Returns the time to wait between two actions.
     * @param none.
     * @return time to wait.
     */
    // Queue thread
    protected int getActionDelay() {
        return 0;
    }

    private void mergeEventsChunk(final List<EventGeneric> events, final java.util.Date date) {
        final Session session = getGUI().getSynchro().getSessionFactory().getCurrentSession();
        if (events.size() < 2)
            return;
        double sum = 0D;
        int cnt = 0;
        boolean neg = true;
        boolean first = true;
        for (final EventGeneric event : events) {
            if (event.getIntValue() >= 0) {
                neg = false;
                cnt++;
                sum += event.getIntValue();
            }
            if (first == false)
                session.delete(event);
            first = false;
        }

        events.get(0).setDate(new java.sql.Date(date.getTime()));

        if (neg == true)
            events.get(0).setIntValue(-1);
        else
            events.get(0).setIntValue((int) (sum / cnt));
    }

    final void mergeEventsOfTarget(final Target target, final String event_type, final Long s,
            final EventGeneric ev_first) {
        if (ev_first == null)
            return;

        final org.hibernate.Query query = getGUI().getSynchro().getSessionFactory().getCurrentSession()
                .createQuery("from EventGeneric as ev " + "where ev.eventList = :event_list "
                        + "and ev.date < :stop_date " + "and ev.merged != :s order by ev.date asc")
                .setString("event_list", target.getEventLists().get(event_type).getId().toString()).setLong("s", s)
                .setString("stop_date", ev_first.getDate().toString());
        //    log.debug("stop date : " + ev_first.getDate().toString());
        final List<EventGeneric> results = query.list();
        if (results.size() > 0) {
            EventGeneric prev_event = null;
            final ArrayList<EventGeneric> events = new ArrayList<EventGeneric>();
            for (final EventGeneric event : results) {
                event.setMerged(s);
                if (prev_event != null) {
                    if (event.getDate().getTime()
                            - event.getDate().getTime() % (s * 1000) == prev_event.getDate().getTime()
                                    - prev_event.getDate().getTime() % (s * 1000)) {
                        if (!events.contains(prev_event))
                            events.add(prev_event);
                        if (!events.contains(event))
                            events.add(event);
                    } else {
                        if (events.size() > 0)
                            mergeEventsChunk(events, new java.util.Date(events.get(0).getDate().getTime()
                                    - events.get(0).getDate().getTime() % (s * 1000) + s * 500));
                        events.clear();
                        events.add(event);
                    }
                }
                prev_event = event;
            }
            if (events.size() > 0)
                mergeEventsChunk(events, new java.util.Date(events.get(0).getDate().getTime()
                        - events.get(0).getDate().getTime() % (s * 1000) + s * 500));
            events.clear();
        }
    }

    final EventGeneric getEventByIndex(final int index, final Long targetId) {
        final org.hibernate.Query query = getGUI().getSynchro().getSessionFactory().getCurrentSession()
                .createQuery("from EventGeneric as ev " + "where ev.eventList = :event_list order by ev.date desc")
                .setString("event_list", targetId.toString()).setFirstResult(index - 1).setMaxResults(1);
        return (query.list().size() > 0) ? (EventGeneric) query.uniqueResult() : null;
    }

    private void mergeEvents() {
        // should be localized
        final long start_time = System.currentTimeMillis();
        getGUI().appendConsole("<HR><B>Merging old events</B><BR/>start time: " + new Date(start_time) + "<BR/>");

        org.hibernate.Query query;
        synchronized (getGUI().getSynchro()) {
            final Session session = getGUI().getSynchro().getSessionFactory().getCurrentSession();
            session.beginTransaction();

            try {
                for (final VisualElement elt : getGUI().getVisualTransient().getSubElements(Target.class)) {
                    final Target target = (Target) elt;
                    session.update(target);
                    for (final String event_type : target.getEventLists().keySet()) {
                        final Integer count = (Integer) session
                                .createQuery("select count(*) from EventGeneric ev "
                                        + "where ev.eventList = :event_list")
                                .setString("event_list", target.getEventLists().get(event_type).getId().toString())
                                .uniqueResult();

                        // merge old events
                        if (count > new Integer(getConfig().getProperty("events.merge.threshold.0"))) {
                            int idx = 1;
                            while (getConfig().getProperty("events.merge.delay." + idx) != null) {
                                mergeEventsOfTarget(target, event_type,
                                        new Long(getConfig().getProperty("events.merge.delay." + idx)),
                                        getEventByIndex(
                                                new Integer(getConfig()
                                                        .getProperty("events.merge.threshold." + (idx - 1))),
                                                target.getEventLists().get(event_type).getId()));
                                idx++;
                            }

                            // remove very old events
                            final EventGeneric ev = getEventByIndex(
                                    new Integer(getConfig().getProperty("events.merge.threshold." + (idx - 1))),
                                    target.getEventLists().get(event_type).getId());
                            if (ev != null) {
                                query = session
                                        .createQuery("delete EventGeneric as ev "
                                                + "where ev.eventList = :event_list and ev.date < :stop_date")
                                        .setString("event_list",
                                                target.getEventLists().get(event_type).getId().toString())
                                        .setString("stop_date", ev.getDate().toString());
                                query.executeUpdate();
                            }
                        }
                    }
                }

                session.getTransaction().commit();
            } catch (final Exception ex) {
                log.error("Exception", ex);
                session.getTransaction().rollback();
            }
        }

        // should be localized
        getGUI().appendConsole("finished in " + (System.currentTimeMillis() - start_time) / 1000 + " seconds");
    }

    // synchronized : protger l'accs  setGUI()
    public synchronized void inform(final Object obj) {
        setGUI((GUI) obj);
    }

    // synchronized : protger l'accs  getGUI()
    public synchronized void informCycle() {
        while (getGUI() == null) {
            try {
                Thread.sleep(1000);
            } catch (final InterruptedException ex) {
                log.warn("Exception", ex);
            }
        }

        if (getGUI() != null && getGUI().getSynchro() != null)
            mergeEvents();
    }
}