/*
* 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.group.view;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import scouter.client.Images;
import scouter.client.group.GroupManager;
import scouter.client.model.AgentModelThread;
import scouter.client.model.AgentObject;
import scouter.client.model.XLogData;
import scouter.client.model.XLogDataComparator;
import scouter.client.net.INetReader;
import scouter.client.net.TcpProxy;
import scouter.client.popup.CalendarDialog;
import scouter.client.popup.TimeRangeDialog;
import scouter.client.preferences.PManager;
import scouter.client.preferences.PreferenceConstants;
import scouter.client.server.Server;
import scouter.client.server.ServerManager;
import scouter.client.util.ConsoleProxy;
import scouter.client.util.ExUtil;
import scouter.client.util.ImageUtil;
import scouter.client.xlog.XLogUtil;
import scouter.client.xlog.views.XLogViewCommon;
import scouter.io.DataInputX;
import scouter.lang.pack.MapPack;
import scouter.lang.pack.Pack;
import scouter.lang.pack.XLogPack;
import scouter.lang.value.BooleanValue;
import scouter.lang.value.ListValue;
import scouter.net.RequestCmd;
import scouter.util.DateUtil;
public class XLogLoadTimeGroupView extends XLogViewCommon implements TimeRangeDialog.ITimeRange, CalendarDialog.ILoadCalendarDialog {
public static final String ID = XLogLoadTimeGroupView.class.getName();
private String grpName;
private Server defaultServer = ServerManager.getInstance().getDefaultServer();
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
private Map<Integer, ListValue> serverObjMap = new HashMap<Integer, ListValue>();
private long stime;
private long etime;
LoadXLogJob loadJob;
public void init(IViewSite site) throws PartInitException {
super.init(site);
String secId = site.getSecondaryId();
String[] datas = secId.split("&");
grpName = datas[0];
objType = datas[1];
}
public void createPartControl(final Composite parent) {
display = Display.getCurrent();
shell = new Shell(display);
this.setPartName("XLog - " + grpName);
IToolBarManager man = getViewSite().getActionBars().getToolBarManager();
create(parent, man);
man.add(new Action("zoom in", ImageUtil.getImageDescriptor(Images.zoomin)) {
public void run() {
TimeRangeDialog dialog = new TimeRangeDialog(display, XLogLoadTimeGroupView.this, DateUtil.yyyymmdd(stime));
dialog.show(stime, etime);
}
});
man.add(new Action("zoom out", ImageUtil.getImageDescriptor(Images.zoomout)) {
public void run() {
if (viewPainter.isZoomMode()) {
viewPainter.endZoom();
} else {
viewPainter.keyPressed(16777261);
viewPainter.build();
}
canvas.redraw();
}
});
man.add(new Separator());
createContextMenu(parent, new IMenuListener() {
public void menuAboutToShow(IMenuManager manager){
if(viewPainter.isZoomMode() == false){
manager.add(new Action("Load") {
public void run() {
CalendarDialog dialog = new CalendarDialog(display, XLogLoadTimeGroupView.this);
dialog.showWithEndTime();
}
});
manager.add(new Action("Zoom In", ImageDescriptor.createFromImage(Images.zoomin)) {
public void run() {
TimeRangeDialog dialog = new TimeRangeDialog(display, XLogLoadTimeGroupView.this, DateUtil.yyyymmdd(stime));
dialog.show(stime, etime);
}
});
}
}
});
canvas.addControlListener(new ControlListener() {
public void controlResized(ControlEvent e) {
viewPainter.set(canvas.getClientArea());
viewPainter.build();
}
public void controlMoved(ControlEvent e) {
}
});
setObjType(objType);
}
private void createContextMenu(Composite parent, IMenuListener listener){
MenuManager contextMenu = new MenuManager();
contextMenu.setRemoveAllWhenShown(true);
contextMenu.addMenuListener(listener);
Menu menu = contextMenu.createContextMenu(parent);
canvas.setMenu(menu);
}
public void setFocus() {
super.setFocus();
}
public void setInput(long stime, long etime) {
this.stime = stime;
this.etime = etime;
viewPainter.setEndTime(etime);
viewPainter.setTimeRange(etime - stime);
setDate(DateUtil.yyyymmdd(stime));
String objTypeDisplay = defaultServer.getCounterEngine().getDisplayNameObjectType(objType);
setContentDescription(grpName +" | "+objTypeDisplay+"\'s "+"XLog Pasttime"
+ " | " + DateUtil.format(stime, "yyyy-MM-dd") + "(" + DateUtil.format(stime, "HH:mm")
+ "~" + DateUtil.format(etime, "HH:mm") + ")");
try {
loadJob = new LoadXLogJob();
loadJob.schedule();
} catch (Exception e) {
MessageDialog.openError(shell, "Error", e.getMessage());
}
}
private GroupManager manager = GroupManager.getInstance();
private void collectObj() {
serverObjMap.clear();
Set<Integer> objHashs = manager.getObjectsByGroup(grpName);
for (int objHash : objHashs) {
AgentObject agentObj = AgentModelThread.getInstance().getAgentObject(objHash);
if (agentObj == null || agentObj.isAlive() == false) {
continue;
}
int serverId = agentObj.getServerId();
ListValue lv = serverObjMap.get(serverId);
if (lv == null) {
lv = new ListValue();
serverObjMap.put(serverId, lv);
}
lv.add(objHash);
}
}
public void loadAdditinalData(long stime, long etime, final boolean reverse) {
collectObj();
Iterator<Integer> serverIds = serverObjMap.keySet().iterator();
final TreeSet<XLogData> tempSet = new TreeSet<XLogData>(new XLogDataComparator());
int limit = PManager.getInstance().getInt(PreferenceConstants.P_XLOG_IGNORE_TIME);
final int max = getMaxCount();
while (serverIds.hasNext()) {
final int serverId = serverIds.next();
TcpProxy tcp = TcpProxy.getTcpProxy(serverId);
try {
MapPack param = new MapPack();
param.put("date", DateUtil.yyyymmdd(stime));
param.put("stime", stime);
param.put("etime", etime);
param.put("objHash", serverObjMap.get(serverId));
param.put("reverse", new BooleanValue(reverse));
if (limit > 0) {
param.put("limit", limit);
}
if (max > 0) {
param.put("max", max);
}
twdata.setMax(max);
tcp.process(RequestCmd.TRANX_LOAD_TIME_GROUP, param, new INetReader() {
public void process(DataInputX in) throws IOException {
Pack p = in.readPack();
XLogPack x = XLogUtil.toXLogPack(p);
if (tempSet.size() < max) {
tempSet.add(new XLogData(x, serverId));
}
}
});
} catch (Throwable t) {
ConsoleProxy.errorSafe(t.toString());
} finally {
TcpProxy.putTcpProxy(tcp);
}
}
if (reverse) {
Iterator<XLogData> itr = tempSet.descendingIterator();
while (itr.hasNext()) {
XLogData d = itr.next();
twdata.putFirst(d.p.txid, d);
}
} else {
Iterator<XLogData> itr = tempSet.iterator();
while (itr.hasNext()) {
XLogData d = itr.next();
twdata.putLast(d.p.txid, d);
}
}
}
public void setTimeRange(long stime, long etime) {
if (viewPainter.zoomIn(stime, etime)) {
canvas.redraw();
}
}
public void onPressedOk(long startTime, long endTime) {
setInput(startTime, endTime);
}
public void onPressedOk(String date) {}
public void onPressedCancel() {}
class LoadXLogJob extends Job{
int count = 0;
public LoadXLogJob() {
super("XLog Loading...("
+ DateUtil.format(stime, "yyyy-MM-dd")
+ " "
+ DateUtil.format(stime, "HH:mm")
+ "~"
+ DateUtil.format(etime, "HH:mm") + ")");
}
protected IStatus run(final IProgressMonitor monitor) {
monitor.beginTask("Loading...", IProgressMonitor.UNKNOWN);
twdata.clear();
collectObj();
Iterator<Integer> serverIds = serverObjMap.keySet().iterator();
final TreeSet<XLogData> tempSet = new TreeSet<XLogData>(new XLogDataComparator());
int limit = PManager.getInstance().getInt(PreferenceConstants.P_XLOG_IGNORE_TIME);
final int max = getMaxCount();
twdata.setMax(max);
while (serverIds.hasNext()) {
final int serverId = serverIds.next();
final Server server = ServerManager.getInstance().getServer(serverId);
monitor.subTask(server.getName() + " data loading...");
TcpProxy tcp = TcpProxy.getTcpProxy(serverId);
try {
MapPack param = new MapPack();
param.put("date", DateUtil.yyyymmdd(stime));
param.put("stime", stime);
param.put("etime", etime);
param.put("objHash", serverObjMap.get(serverId));
if (limit > 0) {
param.put("limit", limit);
}
if (max > 0) {
param.put("max", max);
}
tcp.process(RequestCmd.TRANX_LOAD_TIME_GROUP, param, new INetReader() {
public void process(DataInputX in) throws IOException {
Pack p = in.readPack();
if (monitor.isCanceled()) {
throw new IOException("User cancelled");
}
XLogPack x = XLogUtil.toXLogPack(p);
if (tempSet.size() < max) {
tempSet.add(new XLogData(x, serverId));
count++;
}
if (count % 10000 == 0) {
monitor.subTask(count + " XLog data received.");
}
}
});
} catch(Throwable e){
ConsoleProxy.errorSafe(e.toString());
} finally {
TcpProxy.putTcpProxy(tcp);
}
}
for (XLogData d : tempSet) {
twdata.putLast(d.p.txid, d);
}
monitor.done();
refresh();
return Status.OK_STATUS;
}
private void refresh() {
viewPainter.build();
ExUtil.exec(canvas, new Runnable() {
public void run() {
canvas.redraw();
}
});
}
}
public void dispose() {
super.dispose();
if (loadJob != null && (loadJob.getState() == Job.WAITING || loadJob.getState() == Job.RUNNING)) {
loadJob.cancel();
}
}
}