// EventTracker.java // (C) 2007 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany // first published 17.11.2007 on http://yacy.net // // This is a part of YaCy, a peer-to-peer based web search engine // // $LastChangedDate$ // $LastChangedRevision$ // $LastChangedBy$ // // LICENSE // // 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 2 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, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package net.yacy.kelondro.util; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import de.anomic.yacy.graphics.ProfilingGraph; public class EventTracker { private final static int maxQueueSize = 30000; private final static long maxQueueAge = ProfilingGraph.maxTime; public enum EClass { WORDCACHE, MEMORY, PPM, PEERPING, DHT, INDEX, SEARCH; } private final static Map> historyMaps = new ConcurrentHashMap>(); private final static Map eventAccess = new ConcurrentHashMap(); // value: last time when this was accessed public final static void delete(final EClass eventName) { historyMaps.remove(eventName); eventAccess.remove(eventName); } public final static void update(final EClass eventName, final Object eventPayload, final boolean useProtection) { // check protection against too heavy access if (useProtection) { final Long lastAcc = eventAccess.get(eventName); if (lastAcc == null) { eventAccess.put(eventName, Long.valueOf(System.currentTimeMillis())); } else { final long time = System.currentTimeMillis(); if (time - lastAcc.longValue() < 1000) { return; // protect against too heavy load } eventAccess.put(eventName, Long.valueOf(time)); } } // get event history container ConcurrentLinkedQueue history = historyMaps.get(eventName); // create history if (history == null) { history = new ConcurrentLinkedQueue(); // update entry history.offer(new Event(eventPayload)); // store map historyMaps.put(eventName, history); return; } // update history history.offer(new Event(eventPayload)); // clean up too old entries int tp = history.size() - maxQueueSize; while (tp-- > 0) history.poll(); if (history.size() % 10 == 0) { // reduce number of System.currentTimeMillis() calls synchronized (history) { if (history.size() % 10 == 0) { // check again Event e; final long now = System.currentTimeMillis(); while (history.size() > 0) { e = history.peek(); if (now - e.time < maxQueueAge) break; history.poll(); } } } } } public final static Iterator getHistory(final EClass eventName) { final ConcurrentLinkedQueue list = historyMaps.get(eventName); if (list == null) return null; return list.iterator(); } public final static int countEvents(final EClass eventName, final long time) { final Iterator event = getHistory(eventName); if (event == null) return 0; final long now = System.currentTimeMillis(); int count = 0; while (event.hasNext()) { if (now - event.next().time < time) count++; } return count; } public final static class Event { public Object payload; public long time; public Event(final Object payload) { this.payload = payload; this.time = System.currentTimeMillis(); } } }