/**
* Copyright 2005-2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit.ui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.persistit.Management;
import com.persistit.Management.TaskStatus;
import com.persistit.Task;
import com.persistit.ui.AdminUI.AdminAction;
import com.persistit.util.Util;
public class AdminUITaskPanel extends AdminPanel implements AdminCommand {
private static final long serialVersionUID = 1L;
private final static int FAST_REFRESH_INTERVAL = 1;
AdminUI _adminUI;
private static double MAIN_SPLITPANE_RESIZE_WEIGHT = .20;
private ManagementTableModel _taskStatusArrayModel;
private final Map _menuMap = new TreeMap();
private boolean _refreshing;
private JPanel _taskListPanel;
private JPanel _detailPanel;
private JTable _taskTable;
private JTextField _taskIdField;
private JTextField _descriptionField;
private JTextField _ownerField;
private JTextField _stateField;
private JTextField _startTimeField;
private JTextField _endTimeField;
private JTextField _expirationTimeField;
private JTextArea _statusDetailArea;
private JTextField _lastExceptionField;
private JTextArea _messageLogArea;
private int _savedRefreshInterval;
private boolean _fastRefreshIntervalSet;
private long _selectedTaskId = -1;
@Override
protected void setup(final AdminUI ui) throws NoSuchMethodException, RemoteException {
_adminUI = ui;
_taskListPanel = new JPanel(new BorderLayout());
_taskStatusArrayModel = new ManagementTableModel(TaskStatus.class, "TaskStatus", ui);
_menuMap.put("TASK.1", _adminUI.createMenuArray(this, "TaskPanelMenu", "TASK"));
_taskTable = new JTable(_taskStatusArrayModel);
_taskTable.setAutoCreateRowSorter(true);
_taskTable.setPreferredScrollableViewportSize(new Dimension(800, 100));
_taskTable.setAutoCreateColumnsFromModel(false);
_taskTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
_taskStatusArrayModel.formatColumns(_taskTable, null);
_taskTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent lse) {
final int[] selectedRows = _taskTable.getSelectedRows();
if (!lse.getValueIsAdjusting() && !_refreshing) {
if (selectedRows.length == 1) {
final int index = selectedRows[0];
final TaskStatus[] array = (TaskStatus[]) _taskStatusArrayModel.getInfoArray();
if (array != null && index < array.length) {
selectTask(array[index]);
} else {
selectTask(null);
}
} else {
selectTask(null);
}
setTaskActionEnabledState(selectedRows.length > 0);
}
}
});
final JScrollPane treeScrollPane = new JScrollPane(_taskTable);
treeScrollPane.setBorder(null);
_taskListPanel.setBorder(_adminUI.createTitledBorder("TaskPanel.tasks"));
final JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(ui.getAction("START_NEW_TASK")));
buttonPanel.add(new JButton(ui.getAction("SUSPEND_TASKS")));
buttonPanel.add(new JButton(ui.getAction("RESUME_TASKS")));
buttonPanel.add(new JButton(ui.getAction("STOP_TASKS")));
buttonPanel.add(new JButton(ui.getAction("REMOVE_TASKS")));
_taskListPanel.add(treeScrollPane, BorderLayout.CENTER);
_taskListPanel.add(buttonPanel, BorderLayout.SOUTH);
final GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(3, 1, 1, 3);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
_detailPanel = new JPanel(new GridBagLayout());
_detailPanel.setBorder(_adminUI.createTitledBorder("TaskPanel.taskDetail"));
_taskIdField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(), "TaskPanel.taskId", false);
_stateField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(), "TaskPanel.state", false);
_descriptionField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(),
"TaskPanel.description", true);
_ownerField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(), "TaskPanel.owner", true);
_startTimeField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(), "TaskPanel.startTime",
false);
_endTimeField = (JTextField) ui
.addLabeledField(_detailPanel, gbc, new JTextField(), "TaskPanel.endTime", false);
_expirationTimeField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(),
"TaskPanel.expirationTime", true);
_lastExceptionField = (JTextField) ui.addLabeledField(_detailPanel, gbc, new JTextField(),
"TaskPanel.lastException", true);
_statusDetailArea = (JTextArea) ui.addLabeledField(_detailPanel, gbc, new JTextArea(),
"TaskPanel.statusDetail", true);
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.weighty = 1.0;
_messageLogArea = (JTextArea) ui.addLabeledField(_detailPanel, gbc, new JTextArea(), "TaskPanel.messageLog",
true);
final JSplitPane mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainSplitPane.setResizeWeight(MAIN_SPLITPANE_RESIZE_WEIGHT);
mainSplitPane.add(_taskListPanel);
mainSplitPane.add(_detailPanel);
setLayout(new BorderLayout());
add(mainSplitPane, BorderLayout.CENTER);
setTaskActionEnabledState(false);
_adminUI.registerTextComponent(_statusDetailArea);
_adminUI.registerTextComponent(_messageLogArea);
_adminUI.scheduleRefresh(-1);
}
@Override
public void actionPerformed(final AdminAction action, final ActionEvent ae) {
final Management management = _adminUI.getManagement();
if (management == null)
return;
try {
final String name = action.getName();
final boolean suspend = "SUSPEND_TASKS".equals(name);
final boolean resume = "RESUME_TASKS".equals(name);
final boolean stop = "STOP_TASKS".equals(name);
final boolean remove = "REMOVE_TASKS".equals(name);
if (suspend || resume || stop || remove) {
final int[] selectedRows = _taskTable.getSelectedRows();
final TaskStatus[] tsArray = new TaskStatus[selectedRows.length];
for (int index = 0; index < tsArray.length; index++) {
final int row = selectedRows[index];
final TaskStatus ts = (TaskStatus) _taskStatusArrayModel.getValueAt(row, -1);
tsArray[index] = ts;
}
for (int index = 0; index < tsArray.length; index++) {
final TaskStatus ts = tsArray[index];
final long taskId = ts.getTaskId();
if (suspend || resume) {
management.setTaskSuspended(taskId, suspend);
} else if (stop || remove) {
management.stopTask(taskId, remove);
}
}
}
_adminUI.scheduleRefresh(-1);
} catch (final Exception e) {
_adminUI.postException(e);
if (!(e instanceof RemoteException)) {
e.printStackTrace();
}
}
}
private boolean selectTask(final TaskStatus taskStatus) {
_selectedTaskId = -1;
if (taskStatus != null) {
_selectedTaskId = taskStatus.getTaskId();
}
updateDetailedTaskStatus();
return false;
}
private void updateDetailedTaskStatus() {
final Management management = _adminUI.getManagement();
if (_selectedTaskId == -1 || management == null) {
updateDetailedTaskStatus(null);
} else {
try {
final TaskStatus[] array = management.queryTaskStatus(_selectedTaskId, true, false, false);
if (array.length == 1) {
updateDetailedTaskStatus(array[0]);
}
} catch (final RemoteException re) {
_adminUI.postException(re);
}
}
}
private void updateDetailedTaskStatus(final TaskStatus taskStatus) {
if (taskStatus == null) {
_taskIdField.setText("");
_stateField.setText("");
_descriptionField.setText("");
_ownerField.setText("");
_startTimeField.setText("");
_endTimeField.setText("");
_expirationTimeField.setText("");
_lastExceptionField.setText("");
_statusDetailArea.setText("");
_messageLogArea.setText("");
} else {
_taskIdField.setText(Long.toString(taskStatus.getTaskId()));
_stateField.setText(_adminUI.getTaskStateString(taskStatus.getState()));
_descriptionField.setText(taskStatus.getDescription());
_ownerField.setText(taskStatus.getOwner());
_startTimeField.setText(_adminUI.formatDate(taskStatus.getStartTime()));
_endTimeField.setText(_adminUI.formatDate(taskStatus.getFinishTime()));
_expirationTimeField.setText(_adminUI.formatDate(taskStatus.getExpirationTime()));
_lastExceptionField.setText(taskStatus.getLastException() == null ? "" : taskStatus.getLastException()
.toString());
_statusDetailArea.setText(taskStatus.getStatusDetail());
final StringBuilder sb = new StringBuilder();
int size = 0;
if (taskStatus.getMessages() != null) {
size = taskStatus.getMessages().length;
}
for (int index = 0; index < size; index++) {
sb.append(taskStatus.getMessages()[index]);
sb.append(Util.NEW_LINE);
}
_messageLogArea.setText(sb.toString());
}
}
private boolean equals(final Object a, final Object b) {
if (a == null)
return b == null;
else
return a.equals(b);
}
private void setTaskActionEnabledState(final boolean enabled) {
AdminAction action;
action = _adminUI.getAction("SUSPEND_TASKS");
if (action != null)
action.setEnabled(enabled);
action = _adminUI.getAction("RESUME_TASKS");
if (action != null)
action.setEnabled(enabled);
action = _adminUI.getAction("STOP_TASKS");
if (action != null)
action.setEnabled(enabled);
action = _adminUI.getAction("REMOVE_TASKS");
if (action != null)
action.setEnabled(enabled);
}
@Override
protected void refresh(final boolean reset) {
synchronized (this) {
if (_refreshing)
return;
_refreshing = true;
}
try {
boolean liveTasks = false;
boolean stillSelected = false;
final Management management = _adminUI.getManagement();
if (management != null) {
final TaskStatus[] taskStatusArray = management.queryTaskStatus(-1, false, false, false);
_taskStatusArrayModel.setInfoArray(taskStatusArray);
setTaskActionEnabledState(_taskTable.getSelectedRowCount() > 0);
for (int index = 0; index < taskStatusArray.length; index++) {
final TaskStatus ts = taskStatusArray[index];
if (ts.getState() < Task.STATE_DONE)
liveTasks = true;
if (ts.getTaskId() == _selectedTaskId)
stillSelected = true;
}
}
if (!stillSelected)
selectTask(null);
updateDetailedTaskStatus();
scheduleFastRefresh(liveTasks);
} catch (final RemoteException re) {
_adminUI.postException(re);
} finally {
synchronized (this) {
_refreshing = false;
}
}
}
@Override
public void setIsShowing(final boolean isShowing) {
if (_fastRefreshIntervalSet) {
_adminUI.scheduleRefresh(isShowing ? FAST_REFRESH_INTERVAL : _savedRefreshInterval);
}
}
private void scheduleFastRefresh(final boolean liveTasks) {
if (liveTasks && !_fastRefreshIntervalSet) {
_savedRefreshInterval = _adminUI.getRefreshInterval();
_fastRefreshIntervalSet = true;
_adminUI.scheduleRefresh(FAST_REFRESH_INTERVAL);
} else if (!liveTasks && _fastRefreshIntervalSet) {
_fastRefreshIntervalSet = false;
_adminUI.scheduleRefresh(_savedRefreshInterval);
}
}
@Override
protected Map getMenuMap() {
return _menuMap;
}
@Override
protected void setDefaultButton() {
}
}