/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) COSYLAB - Control System Laboratory, 2011
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* 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 com.cosylab.logging.stats;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import com.cosylab.logging.LoggingClient;
/**
* Shows statistics from loaded logs
*
* @author acaproni
*
*/
public class StatsDlg extends JDialog implements ActionListener {
/**
* The string shown when it is not possible to get a value
* from the system
*/
private static final String NotAvailable= "N/A";
/**
* The interval (msec) between iterations while monitoring
*/
private static final int MONITORING_INTERVAL = 1000;
private JLabel totNumOfLogsLbl = new JLabel(NotAvailable);
private JLabel visibleLogsLbl = new JLabel(NotAvailable);
private JLabel hiddenLogsLbl = new JLabel(NotAvailable);
private JLabel availMemLbl = new JLabel(NotAvailable);
private JLabel usedMemLbl = new JLabel(NotAvailable);
private JLabel timeFrameLbl = new JLabel(NotAvailable);
private JLabel inRateLbl = new JLabel(NotAvailable);
private JLabel outRateLbl = new JLabel(NotAvailable);
/**
* The number of the cache files (it refers to the cache of jlog
* and not to the cache of the engine)
*/
private JLabel numOfCacheFiles = new JLabel(NotAvailable);
/**
* The disk space used by all the files of the cache
* (it refers to the cache of jlog and not to the cache of the engine)
*/
private JLabel diskSpace = new JLabel(NotAvailable);
private JButton closeBtn = new JButton("Close");
private JButton refreshBtn = new JButton("Refresh");
private JButton monitorBtn = new JButton("Start monitoring");
// A reference to the LoggingClient
private LoggingClient logging;
/**
* The timer for monitoring
*/
private Timer timer=null;
/**
* Builds and show the dialog
*
* @param logCache
*/
public StatsDlg(LoggingClient mainWin) {
super();
if (mainWin==null) {
throw new IllegalArgumentException("The LoggingClient can't be null");
}
logging =mainWin;
setDefaultCloseOperation(HIDE_ON_CLOSE);
initialize();
pack();
}
/**
* Setup the GUI
*/
private void initialize() {
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Statistics");
this.setBounds(50, 35, 100, 100);
JPanel mainPnl = new JPanel(new BorderLayout());
JPanel valuesPnl = new JPanel(new GridLayout(10,1));
// Add the num of logs
JPanel numOfLogsPnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
numOfLogsPnl.add(new JLabel("Total logs: "));
numOfLogsPnl.add(totNumOfLogsLbl);
valuesPnl.add(numOfLogsPnl);
// Visible logs
JPanel visibleLogsPnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
visibleLogsPnl.add(new JLabel("Visible logs: "));
visibleLogsPnl.add(visibleLogsLbl);
valuesPnl.add(visibleLogsPnl);
// Hidden logs
JPanel hiddenLogsPnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
hiddenLogsPnl.add(new JLabel("Hidden logs: "));
hiddenLogsPnl.add(hiddenLogsLbl);
valuesPnl.add(hiddenLogsPnl);
// Add the available memory
JPanel availMemPnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
availMemPnl.add(new JLabel("Memory available: "));
availMemPnl.add(availMemLbl);
valuesPnl.add(availMemPnl);
// Add the used memory
JPanel usedMemPnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
usedMemPnl.add(new JLabel("Used memory: "));
usedMemPnl.add(usedMemLbl);
valuesPnl.add(usedMemPnl);
// Add the number of the files of cache
JPanel usedCacheFiles = new JPanel(new FlowLayout(FlowLayout.LEFT));
usedCacheFiles.add(new JLabel("Number of files of cache: "));
usedCacheFiles.add(numOfCacheFiles);
valuesPnl.add(usedCacheFiles);
// Add the disk space used by the files of the cache
JPanel usedDiskSpace = new JPanel(new FlowLayout(FlowLayout.LEFT));
usedDiskSpace.add(new JLabel("Disk space used by the cache: "));
usedDiskSpace.add(diskSpace);
valuesPnl.add(usedDiskSpace);
// Add the time frame
JPanel timeFramePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
timeFramePnl.add(new JLabel("Time frame: "));
timeFramePnl.add(timeFrameLbl);
valuesPnl.add(timeFramePnl);
// Add the rate from the NC
JPanel inRatePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
inRatePnl.add(new JLabel("Rate of logs from NC: "));
inRatePnl.add(inRateLbl);
valuesPnl.add(inRatePnl);
// Add the rate to the listeners
JPanel outRatePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
outRatePnl.add(new JLabel("Rate of logs sent to table: "));
outRatePnl.add(outRateLbl);
valuesPnl.add(outRatePnl);
mainPnl.add(valuesPnl,BorderLayout.CENTER);
// Add the refresh and the close buttons
JPanel buttonPanel = new JPanel(new FlowLayout());
monitorBtn.addActionListener(this);
buttonPanel.add(monitorBtn);
refreshBtn.addActionListener(this);
buttonPanel.add(refreshBtn);
closeBtn.addActionListener(this);
buttonPanel.add(closeBtn);
mainPnl.add(buttonPanel,BorderLayout.SOUTH);
setContentPane(mainPnl);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we) {
enableMonitoring(false);
}
});
}
/**
* Override <code>setVisible()</code> to move the statistic window
* over the logging client and in front of other windows
*/
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
// Move the statistic win on top of jlog
if (visible && isShowing()) {
Point loggingPos = logging.getLocationOnScreen();
setLocation(loggingPos);
toFront();
refreshGUI();
}
if (!visible) {
enableMonitoring(false);
}
}
/**
* Refresh the values shown in the GUI
*
*/
private void refreshGUI() {
/**
* A class to refresh the labels of the dialog
* The thread is executed inside the swing thread
*
* @author acaproni
*
*/
class GuiRefresher implements Runnable {
long totLogs;
long visLogs;
long hidLogs;
long availMem;
long totMem;
String diskSize;
int totCacheFiles;
String timeFrameStr;
String inputRateStr;
String outputRateStr;
public void run() {
totNumOfLogsLbl.setText(Long.valueOf(totLogs).toString());
visibleLogsLbl.setText(Long.valueOf(visLogs).toString());
hiddenLogsLbl.setText(Long.valueOf(hidLogs).toString());
availMemLbl.setText(""+(availMem/1024)+"Kb");
usedMemLbl.setText(""+((totMem-availMem)/1024)+"Kb");
diskSpace.setText(diskSize);
numOfCacheFiles.setText(""+totCacheFiles);
timeFrameLbl.setText(timeFrameStr);
inRateLbl.setText(inputRateStr);
outRateLbl.setText(outputRateStr);
pack();
}
}
GuiRefresher refresher = new GuiRefresher();
refresher.totLogs = logging.getLogEntryTable().getLCModel().totalLogNumber();
refresher.visLogs = logging.getLogEntryTable().getViewRowCount();
refresher.hidLogs = refresher.totLogs-refresher.visLogs;
try {
refresher.diskSize= ""+logging.getLogEntryTable().getLCModel().usedDiskSpace();
} catch (Throwable t) {
System.err.println("Error getting the used disk space: "+t.getMessage());
t.printStackTrace(System.err);
refresher.diskSize=NotAvailable;
}
refresher.totCacheFiles=logging.getLogEntryTable().getLCModel().numberOfUsedFiles();
Runtime rt = Runtime.getRuntime();
refresher.availMem = rt.freeMemory();
refresher.totMem = rt.totalMemory();
Calendar timeFrame = logging.getLogEntryTable().getLCModel().getTimeFrame();
StringBuilder str = new StringBuilder();
str.append(timeFrame.get(Calendar.DAY_OF_YEAR)-1);
str.append("days - ");
str.append(timeFrame.get(Calendar.HOUR_OF_DAY));
str.append(":");
str.append(timeFrame.get(Calendar.MINUTE));
str.append(":");
str.append(timeFrame.get(Calendar.SECOND));
str.append(".");
str.append(timeFrame.get(Calendar.MILLISECOND));
refresher.timeFrameStr=str.toString();
StringBuilder in = new StringBuilder();
in.append(logging.getEngine().getActualInputRate());
in.append(" (");
if (logging.getEngine().getMaxInputRate()==Integer.MAX_VALUE) {
in.append("unlimited)");
} else {
in.append("limted to ");
in.append(logging.getEngine().getMaxInputRate());
in.append(')');
}
refresher.inputRateStr=in.toString();
StringBuilder out = new StringBuilder();
out.append(logging.getEngine().getActualOutputRate());
out.append(" (");
if (logging.getEngine().getMaxOutputRate()==Integer.MAX_VALUE) {
out.append("unlimited)");
} else {
out.append("limted to ");
out.append(logging.getEngine().getMaxOutputRate());
out.append(')');
}
refresher.outputRateStr=out.toString();
// Start the swing thread
SwingUtilities.invokeLater(refresher);
}
/**
* @see <code>ActionListener<?code>
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource()==closeBtn) {
setVisible(false);
} if (e.getSource()==refreshBtn) {
Thread t = new Thread("Stats dialog updater") {
public void run() {
refreshGUI();
}
};
t.setDaemon(true);
t.start();
} if (e.getSource()==monitorBtn) {
enableMonitoring(refreshBtn.isEnabled());
}
}
/**
* Start or stop the monitoring
*
* @param start If <code>true</code> start monitoring
*/
private void enableMonitoring(boolean start) {
if (start) {
if (timer!=null) {
throw new IllegalStateException("Timer is already instantiated");
}
timer = new Timer("Statistics monitoring");
TimerTask task = new TimerTask() {
public void run() {
refreshGUI();
}
};
timer.schedule(task, 50, MONITORING_INTERVAL);
refreshBtn.setEnabled(false);
monitorBtn.setText("Stop monitoring");
} else {
if (timer!=null) {
timer.cancel();
}
timer=null;
refreshBtn.setEnabled(true);
monitorBtn.setText("Start monitoring");
}
}
}