/* * Created on Sep 13, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.stats; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.control.DHTControlActivity; import com.aelitis.azureus.core.dht.control.DHTControlListener; import com.aelitis.azureus.core.dht.control.DHTControlStats; import com.aelitis.azureus.core.dht.db.DHTDBStats; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.router.DHTRouterStats; import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats; import com.aelitis.azureus.core.dht.transport.DHTTransportStats; import com.aelitis.azureus.plugins.dht.DHTPlugin; /** * */ public class DHTView extends AbstractIView { public static final int DHT_TYPE_MAIN = DHT.NW_MAIN; public static final int DHT_TYPE_CVS = DHT.NW_CVS; public static final int DHT_TYPE_MAIN_V6 = DHT.NW_MAIN_V6; DHT dht; Composite panel; String yes_str; String no_str; Label lblUpTime,lblNumberOfUsers; Label lblNodes,lblLeaves; Label lblContacts,lblReplacements,lblLive,lblUnknown,lblDying; Label lblRendezvous, lblReachable; Label lblKeys,lblValues; Label lblLocal,lblDirect,lblIndirect; Label lblDivFreq,lblDivSize; Label lblReceivedPackets,lblReceivedBytes; Label lblSentPackets,lblSentBytes; Label lblPings[] = new Label[4]; Label lblFindNodes[] = new Label[4]; Label lblFindValues[] = new Label[4]; Label lblStores[] = new Label[4]; Label lblData[] = new Label[4]; Canvas in,out; SpeedGraphic inGraph,outGraph; boolean activityChanged; DHTControlListener controlListener; Table activityTable; DHTControlActivity[] activities; private final int dht_type; public DHTView( int dht_type ) { this.dht_type = dht_type; init(); } private void init() { try { PluginInterface dht_pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi == null ){ return; } DHT[] dhts = ((DHTPlugin)dht_pi.getPlugin()).getDHTs(); for (int i=0;i<dhts.length;i++){ if ( dhts[i].getTransport().getNetwork() == dht_type ){ dht = dhts[i]; break; } } if ( dht == null ){ return; } controlListener = new DHTControlListener() { public void activityChanged(DHTControlActivity activity,int type) { activityChanged = true; } }; dht.getControl().addListener(controlListener); } catch(Exception e) { Debug.printStackTrace( e ); } } public void initialize(Composite composite) { panel = new Composite(composite,SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 2; panel.setLayout(layout); yes_str = MessageText.getString( "Button.yes").replaceAll("&", ""); no_str = MessageText.getString( "Button.no").replaceAll("&", ""); initialiseGeneralGroup(); initialiseDBGroup(); initialiseTransportDetailsGroup(); initialiseOperationDetailsGroup(); initialiseActivityGroup(); } private void initialiseGeneralGroup() { Group gGeneral = new Group(panel,SWT.NONE); Messages.setLanguageText(gGeneral, "DHTView.general.title" ); GridData data = new GridData(); data.verticalAlignment = SWT.BEGINNING; data.widthHint = 350; gGeneral.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = 6; gGeneral.setLayout(layout); Label label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.uptime"); lblUpTime = new Label(gGeneral,SWT.NONE); lblUpTime.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.users"); lblNumberOfUsers = new Label(gGeneral,SWT.NONE); lblNumberOfUsers.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.reachable"); lblReachable = new Label(gGeneral,SWT.NONE); lblReachable.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.nodes"); lblNodes = new Label(gGeneral,SWT.NONE); lblNodes.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.leaves"); lblLeaves = new Label(gGeneral,SWT.NONE); lblLeaves.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.rendezvous"); lblRendezvous = new Label(gGeneral,SWT.NONE); lblRendezvous.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.contacts"); lblContacts = new Label(gGeneral,SWT.NONE); lblContacts.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.replacements"); lblReplacements = new Label(gGeneral,SWT.NONE); lblReplacements.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.live"); lblLive= new Label(gGeneral,SWT.NONE); lblLive.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); label = new Label(gGeneral,SWT.NONE); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.unknown"); lblUnknown = new Label(gGeneral,SWT.NONE); lblUnknown.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gGeneral,SWT.NONE); Messages.setLanguageText(label,"DHTView.general.dying"); lblDying = new Label(gGeneral,SWT.NONE); lblDying.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } private void initialiseDBGroup() { Group gDB = new Group(panel,SWT.NONE); Messages.setLanguageText(gDB,"DHTView.db.title"); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.verticalAlignment = SWT.FILL; gDB.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = 6; layout.makeColumnsEqualWidth = true; gDB.setLayout(layout); Label label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.keys"); lblKeys = new Label(gDB,SWT.NONE); lblKeys.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.values"); lblValues = new Label(gDB,SWT.NONE); lblValues.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); label = new Label(gDB,SWT.NONE); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.local"); lblLocal = new Label(gDB,SWT.NONE); lblLocal.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.direct"); lblDirect = new Label(gDB,SWT.NONE); lblDirect.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.indirect"); lblIndirect = new Label(gDB,SWT.NONE); lblIndirect.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.divfreq"); lblDivFreq = new Label(gDB,SWT.NONE); lblDivFreq.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gDB,SWT.NONE); Messages.setLanguageText(label,"DHTView.db.divsize"); lblDivSize = new Label(gDB,SWT.NONE); lblDivSize.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } private void initialiseTransportDetailsGroup() { Group gTransport = new Group(panel,SWT.NONE); Messages.setLanguageText(gTransport,"DHTView.transport.title"); GridData data = new GridData(GridData.FILL_VERTICAL); data.widthHint = 350; data.verticalSpan = 2; gTransport.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.makeColumnsEqualWidth = true; gTransport.setLayout(layout); Label label = new Label(gTransport,SWT.NONE); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.packets"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.bytes"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.received"); lblReceivedPackets = new Label(gTransport,SWT.NONE); lblReceivedPackets.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); lblReceivedBytes = new Label(gTransport,SWT.NONE); lblReceivedBytes.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.sent"); lblSentPackets = new Label(gTransport,SWT.NONE); lblSentPackets.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); lblSentBytes = new Label(gTransport,SWT.NONE); lblSentBytes.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.in"); data = new GridData(); data.horizontalSpan = 3; label.setLayoutData(data); in = new Canvas(gTransport,SWT.NO_BACKGROUND); data = new GridData(GridData.FILL_BOTH); data.horizontalSpan = 3; in.setLayoutData(data); inGraph = SpeedGraphic.getInstance(); inGraph.initialize(in); label = new Label(gTransport,SWT.NONE); Messages.setLanguageText(label,"DHTView.transport.out"); data = new GridData(); data.horizontalSpan = 3; label.setLayoutData(data); out = new Canvas(gTransport,SWT.NO_BACKGROUND); data = new GridData(GridData.FILL_BOTH); data.horizontalSpan = 3; out.setLayoutData(data); outGraph = SpeedGraphic.getInstance(); outGraph.initialize(out); } private void initialiseOperationDetailsGroup() { Group gOperations = new Group(panel,SWT.NONE); Messages.setLanguageText(gOperations,"DHTView.operations.title"); gOperations.setLayoutData(new GridData(SWT.FILL,SWT.BEGINNING,true,false)); GridLayout layout = new GridLayout(); layout.numColumns = 5; layout.makeColumnsEqualWidth = true; gOperations.setLayout(layout); Label label = new Label(gOperations,SWT.NONE); label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.sent"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.ok"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.failed"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.received"); label.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.ping"); for(int i = 0 ; i < 4 ; i++) { lblPings[i] = new Label(gOperations,SWT.NONE); lblPings[i].setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.findNode"); for(int i = 0 ; i < 4 ; i++) { lblFindNodes[i] = new Label(gOperations,SWT.NONE); lblFindNodes[i].setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.findValue"); for(int i = 0 ; i < 4 ; i++) { lblFindValues[i] = new Label(gOperations,SWT.NONE); lblFindValues[i].setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.store"); for(int i = 0 ; i < 4 ; i++) { lblStores[i] = new Label(gOperations,SWT.NONE); lblStores[i].setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } label = new Label(gOperations,SWT.NONE); Messages.setLanguageText(label,"DHTView.operations.data"); for(int i = 0 ; i < 4 ; i++) { lblData[i] = new Label(gOperations,SWT.NONE); lblData[i].setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false)); } } private void initialiseActivityGroup() { Group gActivity = new Group(panel,SWT.NONE); Messages.setLanguageText(gActivity,"DHTView.activity.title"); gActivity.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true)); gActivity.setLayout(new GridLayout()); activityTable = new Table(gActivity,SWT.VIRTUAL | SWT.BORDER | SWT.FULL_SELECTION | SWT.SINGLE); activityTable.setLayoutData(new GridData(GridData.FILL_BOTH)); final TableColumn colStatus = new TableColumn(activityTable,SWT.LEFT); Messages.setLanguageText(colStatus,"DHTView.activity.status"); colStatus.setWidth(80); final TableColumn colType = new TableColumn(activityTable,SWT.LEFT); Messages.setLanguageText(colType,"DHTView.activity.type"); colType.setWidth(80); final TableColumn colName = new TableColumn(activityTable,SWT.LEFT); Messages.setLanguageText(colName,"DHTView.activity.target"); colName.setWidth(80); final TableColumn colDetails = new TableColumn(activityTable,SWT.LEFT); Messages.setLanguageText(colDetails,"DHTView.activity.details"); colDetails.setWidth(300); colDetails.setResizable(false); activityTable.setHeaderVisible(true); Listener computeLastRowWidthListener = new Listener() { // inUse flag to prevent a SWT stack overflow. For some reason // the setWidth call was triggering a resize. boolean inUse = false; public void handleEvent(Event event) { if (inUse) { return; } inUse = true; try { if(activityTable == null || activityTable.isDisposed()) return; int totalWidth = activityTable.getClientArea().width; int remainingWidth = totalWidth - colStatus.getWidth() - colType.getWidth() - colName.getWidth(); if(remainingWidth > 0) colDetails.setWidth(remainingWidth); } finally { inUse = false; } } }; activityTable.addListener(SWT.Resize, computeLastRowWidthListener); colStatus.addListener(SWT.Resize,computeLastRowWidthListener); colType.addListener(SWT.Resize,computeLastRowWidthListener); colName.addListener(SWT.Resize,computeLastRowWidthListener); activityTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = activityTable.indexOf (item); item.setText (0,MessageText.getString("DHTView.activity.status." + activities[index].isQueued())); item.setText (1,MessageText.getString("DHTView.activity.type." + activities[index].getType())); item.setText (2,ByteFormatter.nicePrint(activities[index].getTarget())); item.setText (3,activities[index].getDescription()); } }); } public void delete() { Utils.disposeComposite(panel); if (dht != null) { dht.getControl().removeListener(controlListener); } outGraph.dispose(); inGraph.dispose(); } public String getFullTitle() { if ( dht_type == DHT_TYPE_MAIN ){ return( "DHTView.title.full" ); }else if ( dht_type == DHT_TYPE_CVS ){ return( "DHTView.title.fullcvs" ); }else{ return( "DHTView.title.full_v6" ); } } public Composite getComposite() { return panel; } public void refresh() { if(dht == null) { init(); return; } inGraph.refresh(); outGraph.refresh(); refreshGeneral(); refreshDB(); refreshTransportDetails(); refreshOperationDetails(); refreshActivity(); } private void refreshGeneral() { DHTControlStats controlStats = dht.getControl().getStats(); DHTRouterStats routerStats = dht.getRouter().getStats(); lblUpTime.setText(TimeFormatter.format(controlStats.getRouterUptime() / 1000)); lblNumberOfUsers.setText("" + controlStats.getEstimatedDHTSize()); lblReachable.setText(dht.getTransport().isReachable()?yes_str:no_str); DHTNATPuncher puncher = dht.getNATPuncher(); String puncher_str; if ( puncher == null ){ puncher_str = ""; }else{ puncher_str = puncher.operational()?yes_str:no_str; } lblRendezvous.setText(dht.getTransport().isReachable()?"":puncher_str); long[] stats = routerStats.getStats(); lblNodes.setText("" + stats[DHTRouterStats.ST_NODES]); lblLeaves.setText("" + stats[DHTRouterStats.ST_LEAVES]); lblContacts.setText("" + stats[DHTRouterStats.ST_CONTACTS]); lblReplacements.setText("" + stats[DHTRouterStats.ST_REPLACEMENTS]); lblLive.setText("" + stats[DHTRouterStats.ST_CONTACTS_LIVE]); lblUnknown.setText("" + stats[DHTRouterStats.ST_CONTACTS_UNKNOWN]); lblDying.setText("" + stats[DHTRouterStats.ST_CONTACTS_DEAD]); } private int refreshIter = 0; private void refreshDB() { if(refreshIter == 0) { DHTDBStats dbStats = dht.getDataBase().getStats(); lblKeys.setText("" + dbStats.getKeyCount()); int[] stats = dbStats.getValueDetails(); lblValues.setText("" + stats[DHTDBStats.VD_VALUE_COUNT]); lblDirect.setText("" + stats[DHTDBStats.VD_DIRECT_SIZE]); lblIndirect.setText("" + stats[DHTDBStats.VD_INDIRECT_SIZE]); lblLocal.setText("" + stats[DHTDBStats.VD_LOCAL_SIZE]); lblDivFreq.setText("" + stats[DHTDBStats.VD_DIV_FREQ]); lblDivSize.setText("" + stats[DHTDBStats.VD_DIV_SIZE]); } else { refreshIter++; if(refreshIter == 100) refreshIter = 0; } } private void refreshTransportDetails() { DHTTransportStats transportStats = dht.getTransport().getStats(); lblReceivedBytes.setText(DisplayFormatters.formatByteCountToKiBEtc(transportStats.getBytesReceived())); lblSentBytes.setText(DisplayFormatters.formatByteCountToKiBEtc(transportStats.getBytesSent())); lblReceivedPackets.setText("" + transportStats.getPacketsReceived()); lblSentPackets.setText("" + transportStats.getPacketsSent()); } private void refreshOperationDetails() { DHTTransportStats transportStats = dht.getTransport().getStats(); long[] pings = transportStats.getPings(); for(int i = 0 ; i < 4 ; i++) { lblPings[i].setText("" + pings[i]); } long[] findNodes = transportStats.getFindNodes(); for(int i = 0 ; i < 4 ; i++) { lblFindNodes[i].setText("" + findNodes[i]); } long[] findValues = transportStats.getFindValues(); for(int i = 0 ; i < 4 ; i++) { lblFindValues[i].setText("" + findValues[i]); } long[] stores = transportStats.getStores(); for(int i = 0 ; i < 4 ; i++) { lblStores[i].setText("" + stores[i]); } long[] data = transportStats.getData(); for(int i = 0 ; i < 4 ; i++) { lblData[i].setText("" + data[i]); } } private void refreshActivity() { if(activityChanged) { activityChanged = false; activities = dht.getControl().getActivities(); activityTable.setItemCount(activities.length); activityTable.clearAll(); //Dunno if still needed? activityTable.redraw(); } } public void periodicUpdate() { if(dht == null) return; DHTTransportFullStats fullStats = dht.getTransport().getLocalContact().getStats(); inGraph.addIntValue((int)fullStats.getAverageBytesReceived()); outGraph.addIntValue((int)fullStats.getAverageBytesSent()); } public String getData() { return( getFullTitle()); } }