/*
* 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.counter.views;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.csstudio.swt.xygraph.dataprovider.CircularBufferDataProvider;
import org.csstudio.swt.xygraph.dataprovider.ISample;
import org.csstudio.swt.xygraph.dataprovider.Sample;
import org.csstudio.swt.xygraph.figures.Trace;
import org.csstudio.swt.xygraph.figures.Trace.PointStyle;
import org.csstudio.swt.xygraph.figures.Trace.TraceType;
import org.csstudio.swt.xygraph.figures.XYGraph;
import org.csstudio.swt.xygraph.linearscale.Range;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.window.DefaultToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import scouter.client.Images;
import scouter.client.listeners.RangeMouseListener;
import scouter.client.model.AgentColorManager;
import scouter.client.model.AgentModelThread;
import scouter.client.model.AgentObject;
import scouter.client.model.RefreshThread;
import scouter.client.model.RefreshThread.Refreshable;
import scouter.client.model.TextProxy;
import scouter.client.net.INetReader;
import scouter.client.net.TcpProxy;
import scouter.client.preferences.PManager;
import scouter.client.preferences.PreferenceConstants;
import scouter.client.server.Server;
import scouter.client.server.ServerManager;
import scouter.client.threads.ObjectSelectManager;
import scouter.client.threads.ObjectSelectManager.IObjectCheckListener;
import scouter.client.util.ChartUtil;
import scouter.client.util.ColorUtil;
import scouter.client.util.ConsoleProxy;
import scouter.client.util.CounterUtil;
import scouter.client.util.ExUtil;
import scouter.client.util.ImageUtil;
import scouter.client.util.MenuUtil;
import scouter.client.util.ScouterUtil;
import scouter.client.util.TimeUtil;
import scouter.client.views.ScouterViewPart;
import scouter.io.DataInputX;
import scouter.lang.pack.MapPack;
import scouter.lang.value.ListValue;
import scouter.lang.value.Value;
import scouter.lang.value.ValueEnum;
import scouter.net.RequestCmd;
import scouter.util.CastUtil;
import scouter.util.DateUtil;
import scouter.util.FormatUtil;
import scouter.util.HashUtil;
import scouter.util.StringUtil;
public class CounterRealTimeAllView extends ScouterViewPart implements Refreshable, IObjectCheckListener {
public static final String ID = CounterRealTimeAllView.class.getName();
protected RefreshThread thread = null;
private int serverId;
private String objType;
private String counter;
private boolean manualRefresh = false;
boolean isActive = false;
protected XYGraph xyGraph;
protected Map<Integer, CircularBufferDataProvider> datas = new HashMap<Integer, CircularBufferDataProvider>();
protected FigureCanvas canvas;
Trace nearestTrace;
ArrayList<Trace> traces = new ArrayList<Trace>();
public void init(IViewSite site) throws PartInitException {
super.init(site);
String secId = site.getSecondaryId();
String[] ids = StringUtil.split(secId, "&");
this.serverId = CastUtil.cint(ids[0]);
this.objType = ids[1];
this.counter = ids[2];
}
public void createPartControl(Composite parent) {
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = 5;
layout.marginWidth = 5;
parent.setLayout(layout);
parent.setBackground(ColorUtil.getInstance().getColor(SWT.COLOR_WHITE));
parent.setBackgroundMode(SWT.INHERIT_FORCE);
canvas = new FigureCanvas(parent);
canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
canvas.setScrollBarVisibility(FigureCanvas.NEVER);
canvas.addControlListener(new ControlListener() {
boolean lock = false;
public void controlResized(ControlEvent e) {
org.eclipse.swt.graphics.Rectangle r = canvas.getClientArea();
if (!lock) {
lock = true;
if (ChartUtil.isShowLegendAllowSize(r.width, r.height)) {
xyGraph.setShowLegend(true);
} else {
xyGraph.setShowLegend(false);
}
if (ChartUtil.isShowDescriptionAllowSize(r.height)) {
CounterRealTimeAllView.this.setContentDescription(desc);
} else {
CounterRealTimeAllView.this.setContentDescription("");
}
r = canvas.getClientArea();
xyGraph.setSize(r.width, r.height);
lock = false;
}
}
public void controlMoved(ControlEvent e) {
}
});
xyGraph = new XYGraph();
xyGraph.setShowLegend(true);
xyGraph.setShowTitle(false);
canvas.setContents(xyGraph);
xyGraph.primaryXAxis.setDateEnabled(true);
xyGraph.primaryXAxis.setShowMajorGrid(true);
xyGraph.primaryYAxis.setAutoScale(true);
xyGraph.primaryYAxis.setShowMajorGrid(true);
xyGraph.primaryXAxis.setTitle("");
xyGraph.primaryYAxis.setTitle("");
xyGraph.primaryXAxis.setFormatPattern("HH:mm:ss");
xyGraph.primaryYAxis.setFormatPattern("#,##0");
xyGraph.primaryYAxis.addMouseListener(new RangeMouseListener(getViewSite().getShell(), xyGraph.primaryYAxis));
final DefaultToolTip toolTip = new DefaultToolTip(canvas, DefaultToolTip.RECREATE, true);
toolTip.setFont(new Font(null, "Arial", 10, SWT.BOLD));
toolTip.setBackgroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
canvas.addMouseListener(new MouseListener() {
public void mouseUp(MouseEvent e) {
if (nearestTrace != null) {
nearestTrace.setLineWidth(PManager.getInstance().getInt(PreferenceConstants.P_CHART_LINE_WIDTH));
nearestTrace = null;
}
toolTip.hide();
}
public void mouseDown(MouseEvent e) {
double x = xyGraph.primaryXAxis.getPositionValue(e.x, false);
double y = xyGraph.primaryYAxis.getPositionValue(e.y, false);
if (x < 0 || y < 0) {
return;
}
double minDistance = 30.0d;
long time = 0;
double value = 0;
for (Trace t : traces) {
ISample s = ScouterUtil.getNearestPoint(t.getDataProvider(), x);
if (s != null) {
int x2 = xyGraph.primaryXAxis.getValuePosition(s.getXValue(), false);
int y2 = xyGraph.primaryYAxis.getValuePosition(s.getYValue(), false);
double distance = ScouterUtil.getPointDistance(e.x, e.y, x2, y2);
if (minDistance > distance) {
minDistance = distance;
nearestTrace = t;
time = (long) s.getXValue();
value = s.getYValue();
}
}
}
if (nearestTrace != null) {
int width = PManager.getInstance().getInt(PreferenceConstants.P_CHART_LINE_WIDTH);
nearestTrace.setLineWidth(width + 2);
toolTip.setText(nearestTrace.getName()
+ "\nTime : " + DateUtil.format(time, "HH:mm:ss")
+ "\nValue : " + FormatUtil.print(value, "#,###.##"));
toolTip.show(new Point(e.x, e.y));
}
}
public void mouseDoubleClick(MouseEvent e) {}
});
canvas.addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.F5:
manualRefresh = true;
for (int i = 0; i < traces.size(); i++) {
xyGraph.removeTrace(traces.get(i));
}
thread.interrupt();
break;
}
}
});
IToolBarManager man = getViewSite().getActionBars().getToolBarManager();
man.add(new Action("Reload", ImageUtil.getImageDescriptor(Images.refresh)) {
public void run() {
manualRefresh = true;
for (int i = 0; i < traces.size(); i++) {
xyGraph.removeTrace(traces.get(i));
}
thread.interrupt();
}
});
Server server = ServerManager.getInstance().getServer(serverId);
String svrName = "";
String counterDisplay = "";
String counterUnit = "";
if (server != null) {
svrName = server.getName();
counterDisplay = server.getCounterEngine().getCounterDisplayName(objType, counter);
counterUnit = server.getCounterEngine().getCounterUnit(objType, counter);
}
desc = "ⓢ" + svrName + " | (Current All) " + counterDisplay + (!"".equals(counterUnit) ? " (" + counterUnit + ")" : "");
try {
setViewTab(objType, counter, serverId);
} catch (Exception e1) {
e1.printStackTrace();
}
MenuUtil.createCounterContextMenu(ID, canvas, serverId, objType, counter);
ObjectSelectManager.getInstance().addObjectCheckStateListener(this);
thread = new RefreshThread(this, 2000);
thread.setName(this.toString() + " - " + "objType:" + objType + ", counter:" + counter + ", serverId:" + serverId);
thread.start();
}
public void refresh() {
if (manualRefresh) {
manualRefresh = false;
traces.clear();
datas.clear();
getPrevAllPerf();
}
final HashMap<Integer, Value> values = new HashMap<Integer, Value>();
TcpProxy tcp = TcpProxy.getTcpProxy(serverId);
try {
MapPack param = new MapPack();
param.put("objType", objType);
param.put("counter", counter);
MapPack out = (MapPack) tcp.getSingle(RequestCmd.COUNTER_REAL_TIME_ALL, param);
isActive = false;
if (out != null) {
ListValue objHash = out.getList("objHash");
ListValue v = out.getList("value");
for (int i = 0; i < objHash.size(); i++) {
values.put(CastUtil.cint(objHash.get(i)), v.get(i));
isActive = true;
}
}
} catch (Throwable t) {
ConsoleProxy.errorSafe(t.toString());
} finally {
TcpProxy.putTcpProxy(tcp);
}
ExUtil.exec(canvas, new Runnable() {
public void run() {
if (isActive) {
setActive();
} else {
setInactive();
}
long now = TimeUtil.getCurrentTime(serverId);
xyGraph.primaryXAxis.setRange(now - DateUtil.MILLIS_PER_MINUTE * 5, now + 1);
Iterator<Integer> itr = values.keySet().iterator();
while (itr.hasNext()) {
int objHash = itr.next();
Value value = values.get(objHash);
if (value != null && value.getValueType() != ValueEnum.NULL) {
CircularBufferDataProvider data = getDataProvider(objHash);
data.addSample(new Sample(now, CastUtil.cdouble(value)));
}
}
if (CounterUtil.isPercentValue(objType, counter)) {
xyGraph.primaryYAxis.setRange(0, 100);
} else {
double max = getMaxValue();
xyGraph.primaryYAxis.setRange(0, max);
}
CounterRealTimeAllView.this.redraw();
}
});
checkSettingChange();
}
private void checkSettingChange() {
ExUtil.exec(canvas, new Runnable() {
public void run() {
int width = PManager.getInstance().getInt(PreferenceConstants.P_CHART_LINE_WIDTH);
synchronized (traces) {
for (Trace t : traces) {
if (nearestTrace == null && t.getLineWidth() != width) {
t.setLineWidth(width);
}
int objHash = HashUtil.hash(t.getName());
AgentObject agent = AgentModelThread.getInstance().getAgentObject(objHash);
if (agent == null || agent.isAlive() == false || agent.getColor() == null) {
return;
}
if (t.getTraceColor() != agent.getColor()) {
t.setTraceColor(agent.getColor());
}
}
}
}
});
}
private void getPrevAllPerf() {
final ArrayList<MapPack> values = new ArrayList<MapPack>();
TcpProxy tcp = TcpProxy.getTcpProxy(serverId);
try {
MapPack param = new MapPack();
long etime = TimeUtil.getCurrentTime(serverId);
long stime = etime - DateUtil.MILLIS_PER_MINUTE * 5;
param.put("stime", stime);
param.put("etime", etime);
param.put("objType", objType);
param.put("counter", counter);
tcp.process(RequestCmd.COUNTER_PAST_TIME_ALL, param,
new INetReader() {
public void process(DataInputX in) throws IOException {
MapPack mpack = (MapPack) in.readPack();
values.add(mpack);
};
});
} catch (Throwable t) {
ConsoleProxy.errorSafe(t.toString());
} finally {
TcpProxy.putTcpProxy(tcp);
}
ExUtil.exec(this.canvas, new Runnable() {
public void run() {
for (MapPack mpack : values) {
int objHash = mpack.getInt("objHash");
ListValue time = mpack.getList("time");
ListValue value = mpack.getList("value");
if (time == null || time.size() < 1) {
continue;
}
CircularBufferDataProvider provider = getDataProvider(objHash);
provider.clearTrace();
for (int i = 0; time != null && i < time.size(); i++) {
long x = time.getLong(i);
double y = value.getDouble(i);
provider.addSample(new Sample(x, y));
}
}
}
});
}
private CircularBufferDataProvider getDataProvider(int objHash) {
CircularBufferDataProvider data = datas.get(objHash);
if (data == null) {
data = new CircularBufferDataProvider(true);
datas.put(objHash, data);
data.setBufferSize(155);
data.setCurrentXDataArray(new double[] {});
data.setCurrentYDataArray(new double[] {});
String name = StringUtil.trimToEmpty(TextProxy.object.getLoadText(
DateUtil.yyyymmdd(TimeUtil.getCurrentTime(serverId)), objHash,
serverId));
final Trace trace = new Trace(name, xyGraph.primaryXAxis, xyGraph.primaryYAxis, data);
trace.setPointStyle(PointStyle.NONE);
trace.setLineWidth(PManager.getInstance().getInt(PreferenceConstants.P_CHART_LINE_WIDTH));
trace.setTraceType(TraceType.SOLID_LINE);
trace.setTraceColor(AgentColorManager.getInstance().assignColor(objType, objHash));
xyGraph.addTrace(trace);
traces.add(trace);
}
return data;
}
private double getMaxValue() {
Iterator<Integer> objHashs = datas.keySet().iterator();
double max = 0.0;
Range xRange = xyGraph.primaryXAxis.getRange();
double lower = xRange.getLower();
double upper = xRange.getUpper();
while (objHashs.hasNext()) {
int objHash = objHashs.next();
CircularBufferDataProvider data = datas.get(objHash);
if (data != null) {
for (int inx = 0; inx < data.getSize(); inx++) {
Sample sample = (Sample) data.getSample(inx);
double x = sample.getXValue();
if(x < lower || x > upper) {
continue;
}
double y = sample.getYValue();
if (y > max) {
max = y;
}
}
}
}
return ChartUtil.getMaxValue(max);
}
public void setFocus() {
statusMessage = desc + " - setInput(String objType:" + objType
+ ", String counter:" + counter + ", int serverId:" + serverId
+ ")";
super.setFocus();
}
@Override
public void dispose() {
super.dispose();
if (this.thread != null) {
this.thread.shutdown();
}
ObjectSelectManager.getInstance().removeObjectCheckStateListener(this);
}
public void redraw() {
if (canvas != null && canvas.isDisposed() == false) {
canvas.redraw();
xyGraph.repaint();
}
}
public void notifyChangeState() {
ExUtil.asyncRun(new Runnable() {
public void run() {
for (Trace t : traces) {
String objName = t.getName();
if (ObjectSelectManager.getInstance().isUnselectedObject(HashUtil.hash(objName))) {
t.setVisible(false);
} else {
t.setVisible(true);
}
}
ExUtil.exec(canvas, new Runnable() {
public void run() {
redraw();
}
});
}
});
}
}