package edu.brown.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.voltdb.catalog.Catalog;
import org.voltdb.utils.Pair;
import edu.brown.gui.stats.TableListPanel;
import edu.brown.gui.stats.TableStatsPanel;
import edu.brown.statistics.TableStatistics;
import edu.brown.statistics.WorkloadStatistics;
import edu.brown.utils.ArgumentsParser;
/**
*
* @author pavlo
*
*/
public class StatsViewer extends AbstractViewer {
private static final long serialVersionUID = 1L;
// ----------------------------------------------
// MENU OPTIONS
// ----------------------------------------------
public enum MenuOptions {
CATALOG_OPEN_FILE,
CATALOG_OPEN_JAR,
WORKLOAD_STATS_OPEN,
WORKLOAD_STATS_SAVE,
WORKLOAD_STATS_SAVE_AS,
QUIT,
};
// ----------------------------------------------
// GUI ELEMENTS
// ----------------------------------------------
protected JPanel summaryPanel;
protected JPanel tableStatsWrapperPanel;
protected TableListPanel tableSelectPanel;
protected Map<String, TableStatsPanel> tableStatsPanels = new HashMap<String, TableStatsPanel>();
protected String last_table_key;
protected JPanel procStatsPanel;
/**
*
* @param args
*/
public StatsViewer(ArgumentsParser args) {
super(args, "H-Store Workload Statistics Viewer");
this.menuHandler = new StatsViewer.MenuHandler();
this.init();
if (this.args.catalog != null) {
this.update();
}
}
@Override
protected void viewerInit() {
// ----------------------------------------------
// MENU
// ----------------------------------------------
JMenu menu;
JMenuItem menuItem;
//
// File Menu
//
menu = new JMenu("File");
menu.getPopupMenu().setLightWeightPopupEnabled(false);
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("File Menu");
menuBar.add(menu);
menuItem = new JMenuItem("Open Catalog File...");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Open Catalog From File");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.CATALOG_OPEN_FILE);
menu.add(menuItem);
menuItem = new JMenuItem("Open Catalog Jar...");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Open Catalog From Project Jar");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.CATALOG_OPEN_JAR);
menu.add(menuItem);
menu.addSeparator();
menuItem = new JMenuItem("Open Stats");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Open Workload Statistics File");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.WORKLOAD_STATS_OPEN);
menu.add(menuItem);
menuItem = new JMenuItem("Save Stats");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Save Workload Statistics File");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.WORKLOAD_STATS_SAVE);
menu.add(menuItem);
menuItem = new JMenuItem("Save Stats As...");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Save Workload Statistics File");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.WORKLOAD_STATS_SAVE_AS);
menu.add(menuItem);
menu.addSeparator();
menuItem = new JMenuItem("Quit", KeyEvent.VK_Q);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Quit Program");
menuItem.addActionListener(this.menuHandler);
menuItem.putClientProperty(MenuHandler.MENU_ID, MenuOptions.QUIT);
menu.add(menuItem);
// ----------------------------------------------
// SUMMARY PANEL
// ----------------------------------------------
this.summaryPanel = new JPanel();
// ----------------------------------------------
// PROC STATS PANEL
// ----------------------------------------------
this.procStatsPanel = new JPanel();
// ----------------------------------------------
// TABLE STATS PANEL
// ----------------------------------------------
//
// TOP: Stats Viewers
//
TableStatsPanel firstPanel = null;
for (String table_key : this.args.stats.table_stats.keySet()) {
TableStatistics stats = this.args.stats.getTableStatistics(table_key);
TableStatsPanel statsPanel = new TableStatsPanel(stats);
this.tableStatsPanels.put(table_key, statsPanel);
if (firstPanel == null) firstPanel = statsPanel;
} // FOR
//
// BOTTOM: Table Selection
//
final TableListPanel tableSelectionPanel = new TableListPanel();
tableSelectionPanel.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
String table_key = tableSelectionPanel.getSelectedTable();
updateTableStatsPanel(table_key);
}
});
tableSelectionPanel.setTables(args.catalog_db.getTables());
this.tableStatsWrapperPanel = new JPanel(new BorderLayout());
this.tableStatsWrapperPanel.add(firstPanel, BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, this.tableStatsWrapperPanel, tableSelectionPanel);
splitPane.setDividerLocation(500);
tableSelectionPanel.getSelectionModel().setSelectionInterval(0, 0);
// ----------------------------------------------
// TABBED PANE
// ----------------------------------------------
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
}
});
tabbedPane.add(this.summaryPanel, "Summary");
tabbedPane.add(this.procStatsPanel, "Procedure Stats");
tabbedPane.add(splitPane, "Table Stats");
this.add(tabbedPane, BorderLayout.CENTER);
tabbedPane.setSelectedIndex(2);
}
private void update() {
assert(this.args.catalog != null);
assert(this.args.stats != null);
}
private void updateTableStatsPanel(String table_key) {
if (table_key == null || table_key.equals(last_table_key)) return;
if (this.last_table_key != null) {
TableStatsPanel old_panel = this.tableStatsPanels.get(this.last_table_key);
old_panel.setEnabled(false);
old_panel.setVisible(false);
}
TableStatsPanel new_panel = this.tableStatsPanels.get(table_key);
new_panel.setEnabled(true);
new_panel.setVisible(true);
this.tableStatsWrapperPanel.add(new_panel, BorderLayout.CENTER);
this.tableStatsWrapperPanel.revalidate();
this.last_table_key = table_key;
}
/**
* @param args
*/
public static void main(final String[] vargs) throws Exception {
final ArgumentsParser args = ArgumentsParser.load(vargs);
assert(args.catalog != null);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
StatsViewer viewer = new StatsViewer(args);
viewer.setVisible(true);
} // RUN
});
}
protected class MenuHandler extends AbstractMenuHandler {
/**
*
*/
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem source = (JMenuItem)(e.getSource());
//
// Process the event
//
MenuOptions opt = MenuOptions.valueOf(source.getClientProperty(MENU_ID).toString());
switch (opt) {
// --------------------------------------------------------
// OPEN CATALOG FILE
// --------------------------------------------------------
case CATALOG_OPEN_FILE: {
Pair<Catalog, String> result = openCatalogFile();
if (result != null) {
args.catalog = result.getFirst();
args.catalog_path = new File(result.getSecond());
}
break;
}
// --------------------------------------------------------
// OPEN CATALOG JAR
// --------------------------------------------------------
case CATALOG_OPEN_JAR: {
Pair<Catalog, String> result = openCatalogJar();
if (result != null) {
args.catalog = result.getFirst();
args.catalog_path = new File(result.getSecond());
}
break;
}
// --------------------------------------------------------
// OPEN WORKLOAD STATS
// --------------------------------------------------------
case WORKLOAD_STATS_OPEN: {
Pair<WorkloadStatistics, File> result = openWorkloadStats();
if (result != null) {
args.stats = result.getFirst();
args.stats_path = result.getSecond();
update();
}
break;
}
// --------------------------------------------------------
// WORKLOAD STATS SAVE
// --------------------------------------------------------
case WORKLOAD_STATS_SAVE: {
//
// First call all of the objects to update themselves based on the fields
//
LOG.info("Invoking stats panels to update underlying objects");
for (TableStatsPanel statsPanel : StatsViewer.this.tableStatsPanels.values()) {
statsPanel.save();
} // FOR
LOG.info("Saving workload stats...");
try {
args.stats.save(args.stats_path);
} catch (Exception ex) {
ex.printStackTrace();
showErrorDialog("Failed to save workload stats file", ex.getMessage());
}
break;
}
// --------------------------------------------------------
// WORKLOAD STATS SAVE AS
// --------------------------------------------------------
case WORKLOAD_STATS_SAVE_AS: {
//
// First call all of the objects to update themselves based on the fields
//
LOG.info("Invoking stats panels to update underlying objects");
for (TableStatsPanel statsPanel : StatsViewer.this.tableStatsPanels.values()) {
statsPanel.save();
} // FOR
LOG.info("Saving workload stats...");
String path = saveWorkloadStats();
break;
}
// --------------------------------------------------------
// QUIT
// --------------------------------------------------------
case QUIT: {
quit();
break;
}
// --------------------------------------------------------
// UNKNOWN
// --------------------------------------------------------
default:
System.err.println("Invalid Menu Action: " + source.getName());
} // SWITCH
}
} // END CLASS
}