/*
* File : OverallStatsImpl.java
* Created : 2 mars 2004
* By : Olivier
*
* Azureus - a Java Bittorrent client
*
* 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.
*
* 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 ( see the LICENSE file ).
*
* 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
*/
package org.gudy.azureus2.core3.stats.transfer.impl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.gudy.azureus2.core3.global.*;
import org.gudy.azureus2.core3.stats.transfer.OverallStats;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginManager;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreComponent;
import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
import com.aelitis.azureus.core.dht.DHT;
import com.aelitis.azureus.core.dht.transport.DHTTransportStats;
import com.aelitis.azureus.core.stats.AzureusCoreStats;
import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider;
import com.aelitis.azureus.plugins.dht.DHTPlugin;
/**
* @author Olivier
*
*/
public class
OverallStatsImpl
extends GlobalManagerAdapter
implements OverallStats
{
// sizes in MB
private static final long TEN_YEARS = 60*60*24*365*10L;
private static final int STATS_PERIOD = 60*1000; // 1 min
private static final int SAVE_PERIOD = 10*60*1000; // 10 min
private static final int SAVE_TICKS = SAVE_PERIOD / STATS_PERIOD;
private AzureusCore core;
private GlobalManagerStats gm_stats;
private DHT[] dhts;
private long totalDownloaded;
private long totalUploaded;
private long totalUptime;
private long markTime;
private long markTotalDownloaded;
private long markTotalUploaded;
private long markTotalUptime;
private long totalDHTUploaded;
private long totalDHTDownloaded;
private long lastDownloaded;
private long lastUploaded;
private long lastUptime;
private long lastDHTUploaded;
private long lastDHTDownloaded;
// separate stats
private long totalProtocolUploaded;
private long totalDataUploaded;
private long totalProtocolDownloaded;
private long totalDataDownloaded;
private long lastProtocolUploaded;
private long lastDataUploaded;
private long lastProtocolDownloaded;
private long lastDataDownloaded;
private long[] lastSnapshot;
private long session_start_time = SystemTime.getCurrentTime();
protected AEMonitor this_mon = new AEMonitor( "OverallStats" );
private int tick_count;
private Map
load(String filename)
{
return( FileUtil.readResilientConfigFile( filename ));
}
private Map load() {
return( load("azureus.statistics"));
}
private void
save(String filename,
Map map )
{
try{
this_mon.enter();
FileUtil.writeResilientConfigFile( filename, map );
}finally{
this_mon.exit();
}
}
private void save( Map map ) {
save("azureus.statistics", map);
}
private void validateAndLoadValues(
Map statisticsMap ) {
lastUptime = SystemTime.getCurrentTime() / 1000;
Map overallMap = (Map) statisticsMap.get("all");
totalDownloaded = getLong( overallMap, "downloaded" );
totalUploaded = getLong( overallMap, "uploaded" );
totalUptime = getLong( overallMap, "uptime" );
markTime = getLong( overallMap, "mark_time" );
markTotalDownloaded = getLong( overallMap, "mark_downloaded" );
markTotalUploaded = getLong( overallMap, "mark_uploaded" );
markTotalUptime = getLong( overallMap, "mark_uptime" );
totalDHTDownloaded = getLong( overallMap, "dht_down" );
totalDHTUploaded = getLong( overallMap, "dht_up" );
totalProtocolUploaded = getLong( overallMap, "p_uploaded" );
totalDataUploaded = getLong( overallMap, "d_uploaded" );
totalProtocolDownloaded = getLong( overallMap, "p_downloaded" );
totalDataDownloaded = getLong( overallMap, "d_downloaded" );
long current_total_d_received = gm_stats.getTotalDataBytesReceived();
long current_total_p_received = gm_stats.getTotalProtocolBytesReceived();
long current_total_d_sent = gm_stats.getTotalDataBytesSent();
long current_total_p_sent = gm_stats.getTotalProtocolBytesSent();
lastSnapshot =
new long[]{ totalProtocolUploaded, totalDataUploaded,
totalProtocolDownloaded, totalDataDownloaded,
totalDHTUploaded, totalDHTDownloaded,
current_total_p_sent, current_total_d_sent,
current_total_p_received, current_total_d_received,
0, 0 };
}
protected long
getLong(
Map map,
String name )
{
if ( map == null ){
return( 0 );
}
Object obj = map.get(name);
if (!(obj instanceof Long )){
return(0);
}
return(((Long)obj).longValue());
}
public
OverallStatsImpl(
AzureusCore _core,
GlobalManagerStats _gm_stats )
{
core = _core;
gm_stats = _gm_stats;
Map stats = load();
validateAndLoadValues(stats);
Set types = new HashSet();
types.add( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES );
types.add( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES );
types.add( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES );
types.add( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES );
AzureusCoreStats.registerProvider(
types,
new AzureusCoreStatsProvider()
{
public void
updateStats(
Set types,
Map values )
{
try{
this_mon.enter();
if ( core.isStarted()){
if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES )){
values.put(
AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES,
new Long( totalProtocolUploaded + ( gm_stats.getTotalProtocolBytesSent() - lastProtocolUploaded )));
}
if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES )){
values.put(
AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES,
new Long( totalDataUploaded + ( gm_stats.getTotalDataBytesSent() - lastDataUploaded )));
}
if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES )){
values.put(
AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES,
new Long( totalProtocolDownloaded + ( gm_stats.getTotalProtocolBytesReceived() - lastProtocolDownloaded )));
}
if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES )){
values.put(
AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES,
new Long( totalDataDownloaded + ( gm_stats.getTotalDataBytesReceived() - lastDataDownloaded )));
}
}
}finally{
this_mon.exit();
}
}
});
core.addLifecycleListener(
new AzureusCoreLifecycleAdapter()
{
public void
componentCreated(
AzureusCore core,
AzureusCoreComponent component )
{
if ( component instanceof GlobalManager ){
GlobalManager gm = (GlobalManager)component;
gm.addListener( OverallStatsImpl.this, false );
SimpleTimer.addPeriodicEvent(
"OverallStats",
STATS_PERIOD,
new TimerEventPerformer()
{
public void
perform(TimerEvent event)
{
updateStats( false );
}
});
}
}
});
}
public int getAverageDownloadSpeed() {
if(totalUptime > 1) {
return (int)(totalDownloaded / totalUptime);
}
return 0;
}
public int getAverageUploadSpeed() {
if(totalUptime > 1) {
return (int)(totalUploaded / totalUptime);
}
return 0;
}
public long getDownloadedBytes() {
return totalDownloaded;
}
public long getUploadedBytes() {
return totalUploaded;
}
public long getTotalUpTime() {
return totalUptime;
}
public long getDownloadedBytes( boolean since_mark )
{
if ( since_mark ){
if ( markTotalDownloaded > totalDownloaded ){
markTotalDownloaded = totalDownloaded;
}
return( totalDownloaded - markTotalDownloaded );
}else{
return( totalDownloaded );
}
}
public long getUploadedBytes( boolean since_mark )
{
if ( since_mark ){
if ( markTotalUploaded > totalUploaded ){
markTotalUploaded = totalUploaded;
}
return( totalUploaded - markTotalUploaded );
}else{
return( totalUploaded );
}
}
public long getTotalUpTime( boolean since_mark ){
if ( since_mark ){
if ( markTotalUptime > totalUptime ){
markTotalUptime = totalUptime;
}
return( totalUptime - markTotalUptime );
}else{
return( totalUptime );
}
}
public int getAverageDownloadSpeed( boolean since_mark ){
if ( since_mark ){
long up_time = getTotalUpTime( true );
long down = getDownloadedBytes( true );
if( up_time > 1 ){
return (int)(down / up_time);
}
return 0;
}else{
return(getAverageDownloadSpeed());
}
}
public int getAverageUploadSpeed( boolean since_mark ){
if ( since_mark ){
long up_time = getTotalUpTime( true );
long up = getUploadedBytes( true );
if( up_time > 1 ){
return (int)(up / up_time);
}
return 0;
}else{
return(getAverageUploadSpeed());
}
}
public long
getMarkTime()
{
return( markTime );
}
public void
setMark(){
markTime = SystemTime.getCurrentTime();
markTotalDownloaded = totalDownloaded;
markTotalUploaded = totalUploaded;
markTotalUptime = totalUptime;
}
public void
clearMark()
{
markTime = 0;
markTotalDownloaded = 0;
markTotalUploaded = 0;
markTotalUptime = 0;
}
public long getSessionUpTime() {
return (SystemTime.getCurrentTime() - session_start_time) / 1000;
}
public void destroyInitiated() {
updateStats( true );
}
protected long[]
getLastSnapshot()
{
try{
this_mon.enter();
return( lastSnapshot );
}finally{
this_mon.exit();
}
}
private void updateStats( boolean force )
{
try{
this_mon.enter();
long current_time = SystemTime.getCurrentTime() / 1000;
if ( current_time < lastUptime ) { //time went backwards
lastUptime = current_time;
return;
}
long current_total_d_received = gm_stats.getTotalDataBytesReceived();
long current_total_p_received = gm_stats.getTotalProtocolBytesReceived();
long current_total_d_sent = gm_stats.getTotalDataBytesSent();
long current_total_p_sent = gm_stats.getTotalProtocolBytesSent();
long current_total_received = current_total_d_received + current_total_p_received;
long current_total_sent = current_total_d_sent + current_total_p_sent;
// overall totals
totalDownloaded += current_total_received - lastDownloaded;
lastDownloaded = current_total_received;
if( totalDownloaded < 0 ) totalDownloaded = 0;
totalUploaded += current_total_sent - lastUploaded;
lastUploaded = current_total_sent;
if( totalUploaded < 0 ) totalUploaded = 0;
// split totals
totalDataDownloaded += current_total_d_received - lastDataDownloaded;
lastDataDownloaded = current_total_d_received;
if( totalDataDownloaded < 0 ) totalDataDownloaded = 0;
totalProtocolDownloaded += current_total_p_received - lastProtocolDownloaded;
lastProtocolDownloaded = current_total_p_received;
if( totalProtocolDownloaded < 0 ) totalProtocolDownloaded = 0;
totalDataUploaded += current_total_d_sent - lastDataUploaded;
lastDataUploaded = current_total_d_sent;
if( totalDataUploaded < 0 ) totalDataUploaded = 0;
totalProtocolUploaded += current_total_p_sent - lastProtocolUploaded;
lastProtocolUploaded = current_total_p_sent;
if( totalProtocolUploaded < 0 ) totalProtocolUploaded = 0;
// DHT
if ( dhts == null ){
try{
PluginManager pm = core.getPluginManager();
if ( pm.isInitialized()){
PluginInterface dht_pi = pm.getPluginInterfaceByClass( DHTPlugin.class );
if ( dht_pi == null ){
dhts = new DHT[0];
}else{
DHTPlugin plugin = (DHTPlugin)dht_pi.getPlugin();
if ( !plugin.isInitialising()){
if ( plugin.isEnabled()){
dhts = ((DHTPlugin)dht_pi.getPlugin()).getDHTs();
}else{
dhts = new DHT[0];
}
}
}
}
}catch( Throwable e ){
dhts = new DHT[0];
}
}
long current_total_dht_up = 0;
long current_total_dht_down = 0;
if ( dhts != null ){
for ( DHT dht: dhts ){
DHTTransportStats stats = dht.getTransport().getStats();
current_total_dht_up += stats.getBytesSent();
current_total_dht_down += stats.getBytesReceived();
}
}
totalDHTUploaded += current_total_dht_up - lastDHTUploaded;
lastDHTUploaded = current_total_dht_up;
if( totalDHTUploaded < 0 ) totalDHTUploaded = 0;
totalDHTDownloaded += current_total_dht_down - lastDHTDownloaded;
lastDHTDownloaded = current_total_dht_down;
if( totalDHTDownloaded < 0 ) totalDHTDownloaded = 0;
// TIME
long delta = current_time - lastUptime;
if( delta > 100 || delta < 0 ) { //make sure the time diff isn't borked
lastUptime = current_time;
return;
}
if( totalUptime > TEN_YEARS ) { //total uptime > 10years is an error, reset
totalUptime = 0;
}
if( totalUptime < 0 ) totalUptime = 0;
totalUptime += delta;
lastUptime = current_time;
lastSnapshot =
new long[]{ totalProtocolUploaded, totalDataUploaded,
totalProtocolDownloaded, totalDataDownloaded,
totalDHTUploaded,
totalDHTDownloaded,
current_total_p_sent, current_total_d_sent,
current_total_p_received, current_total_d_received,
current_total_dht_up,
current_total_dht_down };
HashMap overallMap = new HashMap();
overallMap.put("downloaded",new Long(totalDownloaded));
overallMap.put("uploaded",new Long(totalUploaded));
overallMap.put("uptime",new Long(totalUptime));
overallMap.put("mark_time",new Long(markTime));
overallMap.put("mark_downloaded",new Long(markTotalDownloaded));
overallMap.put("mark_uploaded",new Long(markTotalUploaded));
overallMap.put("mark_uptime",new Long(markTotalUptime));
overallMap.put("dht_down",new Long(totalDHTDownloaded));
overallMap.put("dht_up",new Long(totalDHTUploaded));
overallMap.put("p_uploaded",new Long(totalProtocolUploaded));
overallMap.put("d_uploaded",new Long(totalDataUploaded));
overallMap.put("p_downloaded",new Long(totalProtocolDownloaded));
overallMap.put("d_downloaded",new Long(totalDataDownloaded));
Map map = new HashMap();
map.put( "all", overallMap );
tick_count++;
if ( force || tick_count % SAVE_TICKS == 0 ){
save( map );
}
}finally{
this_mon.exit();
}
}
}