/* * ALMA - Atacama Large Millimiter Array (c) European Southern Observatory, 2010 * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package alma.acs.alarmsystemprofiler.document; import java.sql.Timestamp; import java.util.Date; import java.util.Vector; import cern.laser.source.alarmsysteminterface.FaultState; import alma.acs.alarmsystemprofiler.parts.ChartViewBase; import alma.alarmsystem.clients.source.SourceListener; /** * The container with the number of alarms received every 10 minutes for a maximum * of one week. * <P> * If the tool listens for alarms for more then one week, the oldest number are * removed. * * @author acaproni * */ public class TenMinutesContainer implements Runnable, SourceListener { /** * One entry storing the number of alarms received in 10 minutes after the timestamp. * * @author acaproni * */ class TenMinutesNumber { // The timestamp when the count started public final Timestamp time; /** * The number of alarms received in 10 minutes */ private int value=0; public TenMinutesNumber() { time=new Timestamp(System.currentTimeMillis()); value=0; } /** * Increment the counter when a new alarm has been received */ public void inc() { value++; } /** * Getter */ public int getValue() { return value; } } /** * The time interval (in minutes) for recording alarms */ public static final int MINUTESTIMEINTERVAL=10; /** * <code>true</code> if the container has been shut down */ protected boolean shutdown=false; /** * The number we are currently updating */ private TenMinutesNumber actualNumber=null; /** * The view showing numbers from this container */ private ChartViewBase chartView=null; /** * The vector of numbers. * <P> * The increment and initial capacity is enough for 1 hr. * <P> * The size of the vector is limited by <code>numbersMaxSize</code>. * If the tool sample for more then one week, the oldest numbers are discarded. * <P> * The oldest sample are in the beginning of the vector while the newest are at the end. */ private Vector<TenMinutesNumber> numbers = new Vector<TenMinutesContainer.TenMinutesNumber>(6,6); /** * The max number of items in the vector <code>numbers</code>: it is enough for one week */ private final int numbersMaxSize=6*24*7; /** * The singleton */ private static TenMinutesContainer singleton=null; public static TenMinutesContainer getInstance() { if (singleton==null) { singleton = new TenMinutesContainer(); } return singleton; } /** * Constructor */ private TenMinutesContainer() { Thread t = new Thread(this,getClass().getName()); t.setDaemon(true); t.start(); } @Override public void faultStateReceived(FaultState faultState) { if (actualNumber==null) { // This can happen if a fault state is received before // starting the thread // // We can safely ignore it. return; } actualNumber.inc(); } @Override public void sourceXMLMsgReceived(String asiMessage) {} /** * The thread does nothing but waiting that the time elapses then * start a new sample. */ @Override public void run() { while (!shutdown) { synchronized (this) { actualNumber=startNewSample(); } for (int min=0; min<MINUTESTIMEINTERVAL && !shutdown; min++) { for (int sec=0; sec<60 && !shutdown; sec++) { try { Thread.sleep(1000); } catch (InterruptedException ie) { continue; } } } refresh(); } } /** * A new sample period just started: we instantiated a new {@link TenMinutesNumber} to store the * number. * <P> * The {@link TenMinutesNumber} object newly created is added to the vector, <code>numbers</code> taking care * that its size remains less the <code>MINUTESTIMEINTERVAL</code>. * * @return The newly created <code>TenMinutesNumber</code> for storing the sample */ private TenMinutesNumber startNewSample() { TenMinutesNumber ret = new TenMinutesNumber(); while (numbers.size()>numbersMaxSize) { numbers.remove(0); } numbers.add(ret); return ret; } /** * Shut down the container and free the resources */ public synchronized void shutdownContainer() { shutdown=true; chartView=null; } /** * Set the view showing numbers from this container * @param view */ public void setChartViewer(ChartViewBase view) { chartView=view; } /** * Ask the view to refresh the chart */ public synchronized void refresh() { if (chartView==null) { return; } Date[] dates=new Date[numbers.size()]; double[] values=new double[numbers.size()]; for (int t=0; t<numbers.size(); t++) { dates[t]=numbers.get(t).time; values[t]=numbers.get(t).getValue(); } chartView.refreshChart(values,dates); } }