/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* 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 scouter.client.views;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.*;
import org.eclipse.ui.part.ViewPart;
import scouter.client.Images;
import scouter.client.model.AgentDataProxy;
import scouter.client.model.RefreshThread;
import scouter.client.model.RefreshThread.Refreshable;
import scouter.client.model.TextProxy;
import scouter.client.model.ThreadData;
import scouter.client.server.ServerManager;
import scouter.client.sorter.TableLabelSorter;
import scouter.client.util.ColorUtil;
import scouter.client.util.ExUtil;
import scouter.client.util.ImageUtil;
import scouter.lang.counters.CounterEngine;
import scouter.lang.pack.MapPack;
import scouter.lang.pack.Pack;
import scouter.lang.value.DecimalValue;
import scouter.lang.value.ListValue;
import scouter.util.CastUtil;
import scouter.util.FormatUtil;
import scouter.util.Hexa32;
import scouter.util.StringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ObjectActiveServiceListView extends ViewPart implements Refreshable {
public static final String ID = ObjectActiveServiceListView.class.getName();
private int serverId;
private String objType;
private int objHash = 0;
CounterEngine counterEngine;
private TableViewer tableViewer;
private TableColumnLayout tableColumnLayout;
private Label errorLbl;
RefreshThread thread;
boolean autoRefresh = false;
public void init(IViewSite site) throws PartInitException {
super.init(site);
String secId = site.getSecondaryId();
String ids[] = secId.split("&");
this.serverId = CastUtil.cint(ids[0]);
this.objType = ids[1];
if (ids.length > 2) {
this.objHash = CastUtil.cint(ids[2]);
}
}
public void createPartControl(Composite parent) {
counterEngine = ServerManager.getInstance().getServer(serverId).getCounterEngine();
if (this.objHash == 0) {
this.setPartName("Active Service List[" + counterEngine.getDisplayNameObjectType(objType) + "]");
} else {
this.setPartName("Active Service List[" + TextProxy.object.getText(this.objHash) + "]");
}
initialLayout(parent);
IToolBarManager man = getViewSite().getActionBars().getToolBarManager();
man.add(new Action("reload", ImageUtil.getImageDescriptor(Images.refresh)) {
public void run() {
manulRefresh = true;
thread.interrupt();
}
});
man.add(new Separator());
Action actAutoRefresh = new Action("Auto Refresh in 5 sec.", IAction.AS_CHECK_BOX){
public void run() {
autoRefresh = isChecked();
if (autoRefresh) {
thread.interrupt();
}
}
};
actAutoRefresh.setImageDescriptor(ImageUtil.getImageDescriptor(Images.refresh_auto));
man.add(actAutoRefresh);
thread = new RefreshThread(this, 5000);
thread.start();
}
private void initialLayout(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(1, true));
errorLbl = new Label(composite, SWT.NONE);
errorLbl.setForeground(ColorUtil.getInstance().getColor(SWT.COLOR_RED));
GridData gr = new GridData(SWT.FILL, SWT.FILL, true, false);
gr.exclude = true;
errorLbl.setLayoutData(gr);
errorLbl.setVisible(false);
Composite tableComposite = new Composite(composite, SWT.NONE);
tableComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
tableComposite.setLayout(new GridLayout(1, true));
createTableViewer(tableComposite);
}
private void createTableViewer(Composite composite) {
tableViewer = new TableViewer(composite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
tableColumnLayout = new TableColumnLayout();
composite.setLayout(tableColumnLayout);
createColumns();
final Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
tableViewer.setContentProvider(new ArrayContentProvider());
tableViewer.setLabelProvider(new LabelProvider());
tableViewer.setComparator(new TableLabelSorter(tableViewer));
GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
tableViewer.getControl().setLayoutData(gridData);
tableViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
StructuredSelection sel = (StructuredSelection) event.getSelection();
Object o = sel.getFirstElement();
if (o instanceof ThreadData) {
ThreadData data = (ThreadData) o;
try {
IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
ObjectThreadDetailView view = (ObjectThreadDetailView) win.getActivePage().showView(ObjectThreadDetailView.ID, serverId + "&" + data.objHash, IWorkbenchPage.VIEW_ACTIVATE);
view.setInput(data.id, Hexa32.toLong32(data.txid));
} catch (Exception d) {
}
}
}
});
}
boolean manulRefresh = true;
public void refresh() {
if (manulRefresh == false && autoRefresh == false) {
return;
}
manulRefresh = false;
load();
}
private void load() {
List<Pack> packList = AgentDataProxy.getActiveThreadList(objType, objHash, serverId);
final ArrayList<ThreadData> datas = new ArrayList<ThreadData>();
final DecimalValue count = new DecimalValue();
final StringBuilder error = new StringBuilder();
for (Pack pack : packList) {
MapPack mpack = (MapPack) pack;
boolean complete = mpack.getBoolean("complete");
int objHash = mpack.getInt("objHash");
if (complete == false) {
String objName = TextProxy.object.getText(objHash);
if (objName != null) {
error.append(objName + " ");
}
}
ListValue idLv = mpack.getList("id");
ListValue nameLv = mpack.getList("name");
ListValue statLv = mpack.getList("stat");
ListValue cpuLv = mpack.getList("cpu");
ListValue txidLv = mpack.getList("txid");
ListValue elapsedLv = mpack.getList("elapsed");
ListValue serviceLv = mpack.getList("service");
ListValue ipLv = mpack.getList("ip");
ListValue sqlLv = mpack.getList("sql");
ListValue subcallLv = mpack.getList("subcall");
if (idLv != null) {
int size = idLv.size();
count.value = count.value + size;
for (int i = 0; i < size; i++) {
ThreadData data = new ThreadData();
data.id = idLv.getLong(i);
data.objHash = objHash;
data.name = nameLv.getString(i);
data.state = statLv.getString(i);
data.cpu = cpuLv.getLong(i);
data.txid = txidLv.getString(i);
data.elapsed = elapsedLv.getLong(i);
data.serviceName = serviceLv.getString(i);
String sql = sqlLv.getString(i);
if (StringUtil.isNotEmpty(sql)) {
data.note = sql;
} else {
data.note = subcallLv.getString(i);
}
if (ipLv != null)
data.ip = ipLv.getString(i);
datas.add(data);
}
}
Collections.sort(datas, new Comparator<ThreadData>() {
public int compare(ThreadData o1, ThreadData o2) {
return o1.elapsed > o2.elapsed ? -1 : 1;
}
});
}
if (error.length() > 0) {
error.append("may be not loaded.");
}
ExUtil.exec(tableViewer.getTable(), new Runnable() {
public void run() {
ObjectActiveServiceListView.this.setContentDescription("Count = " + count.value);
if (error.length() > 0) {
GridData gr = (GridData) errorLbl.getLayoutData();
gr.exclude = false;
errorLbl.setVisible(true);
errorLbl.setText(error.toString());
} else {
GridData gr = (GridData) errorLbl.getLayoutData();
gr.exclude = true;
errorLbl.setVisible(false);
errorLbl.setText("");
}
errorLbl.getParent().layout(false);
tableViewer.setInput(datas);
}
});
}
private void createColumns() {
for (ColumnEnum column : ColumnEnum.values()) {
createTableViewerColumn(column.getTitle(), column.getWidth(), column.getAlignment(), column.isResizable(), column.isMoveable(), column.isNumber());
}
}
private TableViewerColumn createTableViewerColumn(String title, int width, int alignment, boolean resizable, boolean moveable, final boolean isNumber) {
final TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
column.setText(title);
column.setAlignment(alignment);
column.setMoveable(moveable);
tableColumnLayout.setColumnData(column, new ColumnWeightData(width, width, resizable));
column.setData("isNumber", isNumber);
column.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
TableLabelSorter sorter = (TableLabelSorter) tableViewer.getComparator();
TableColumn selectedColumn = (TableColumn) e.widget;
sorter.setColumn(selectedColumn);
}
});
return viewerColumn;
}
class LabelProvider implements ITableLabelProvider, IColorProvider {
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
public Color getBackground(Object element) {
return null;
}
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public Color getForeground(Object element) {
if (element instanceof ThreadData) {
ThreadData t = (ThreadData) element;
if (t.elapsed > 8000) {
return ColorUtil.getInstance().getColor(SWT.COLOR_RED);
} else if (t.elapsed > 3000) {
return ColorUtil.getInstance().getColor(SWT.COLOR_MAGENTA);
} else {
return ColorUtil.getInstance().getColor(SWT.COLOR_BLUE);
}
}
return null;
}
public String getColumnText(Object element, int columnIndex) {
if (element instanceof ThreadData) {
if (columnIndex == ColumnEnum.NO.getIndex()) {
return FormatUtil.print(((ThreadData) element).id, "000");
} else if (columnIndex == ColumnEnum.OBJNAME.getIndex()) {
return TextProxy.object.getText(((ThreadData) element).objHash);
} else if (columnIndex == ColumnEnum.NAME.getIndex()) {
return ((ThreadData) element).name;
} else if (columnIndex == ColumnEnum.STATE.getIndex()) {
return ((ThreadData) element).state;
} else if (columnIndex == ColumnEnum.CPU.getIndex()) {
return FormatUtil.print(((ThreadData) element).cpu, "#,##0");
} else if (columnIndex == ColumnEnum.ELAPSED.getIndex()) {
return FormatUtil.print(((ThreadData) element).elapsed, "#,##0");
} else if (columnIndex == ColumnEnum.TXID.getIndex()) {
return ((ThreadData) element).txid;
} else if (columnIndex == ColumnEnum.SERVICE.getIndex()) {
return ((ThreadData) element).serviceName;
} else if (columnIndex == ColumnEnum.NOTE.getIndex()) {
return ((ThreadData) element).note;
} else if (columnIndex == ColumnEnum.IP.getIndex()) {
return ((ThreadData) element).ip;
}
}
return null;
}
}
public void setFocus() {
}
enum ColumnEnum {
OBJNAME("ObjectName", 150, SWT.LEFT, true, true, false, 0),
SERVICE("Service", 200, SWT.LEFT, true, true, false, 1),
ELAPSED("Elapsed", 60, SWT.RIGHT, true, true, true, 2),
NOTE("Note", 200, SWT.LEFT, true, true, false, 3),
CPU("Cpu", 60, SWT.RIGHT, true, true, true, 4),
IP("IP", 100, SWT.LEFT, true, true, false, 5),
STATE("State", 100, SWT.LEFT, true, true, false, 6),
NAME("Name", 250, SWT.LEFT, true, true, false, 7),
NO("No", 40, SWT.RIGHT, true, true, true, 8),
TXID("TxId", 70, SWT.LEFT, true, true, false, 9);
private final String title;
private final int width;
private final int alignment;
private final boolean resizable;
private final boolean moveable;
private final boolean isNumber;
private final int index;
private ColumnEnum(String text, int width, int alignment, boolean resizable, boolean moveable, boolean isNumber, int index) {
this.title = text;
this.width = width;
this.alignment = alignment;
this.resizable = resizable;
this.moveable = moveable;
this.isNumber = isNumber;
this.index = index;
}
public String getTitle(){
return title;
}
public int getAlignment(){
return alignment;
}
public boolean isResizable(){
return resizable;
}
public boolean isMoveable(){
return moveable;
}
public int getWidth() {
return width;
}
public boolean isNumber() {
return this.isNumber;
}
public int getIndex() {
return this.index;
}
}
}