package com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.util.SystemTime; /** * Created on Jun 29, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * <p/> * 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. * <p/> * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class PingSpaceMonitor { PingSpaceMapper pingMap; long startTime; private static final long INTERVAL = 1000 * 60 * 5L; //five min interval. int maxGoodPing; int minBadPing; //ping counters int nBadPings,nGoodPings,nNeutralPings=0; //saturated mode counters int upNone,upLow,upMed,upHigh,upAtLimit=0; int downNone,downLow,downMed,downHigh,downAtLimit=0; TransferMode transferMode; //To get new limit back to application public static final int UPLOAD = 88; public static final int DOWNLOAD = 89; public static final int NONE = 0; boolean hasNewLimit=false; int newLimit=-2; int limitType=NONE; public PingSpaceMonitor(int _maxGoodPing,int _minBadPing, TransferMode mode) { maxGoodPing=_maxGoodPing; minBadPing=_minBadPing; reset(mode); } /** * * @param downRate - * @param upRate - */ public void setCurrentTransferRates(int downRate, int upRate){ pingMap.setCurrentTransferRates(downRate,upRate); } /** * Do a check and decide if the limits should be dropped. * @param lastMetricValue - * @param mode - the TransferMode * @return - true if the limits should be dropped. */ public boolean addToPingMapData(int lastMetricValue,TransferMode mode){ //reset if we are changing modes. if( transferMode==null ){ transferMode=mode; } //reset everything if we change modes. if( !transferMode.equals(mode) ){ reset(mode); transferMode = mode; return false; } transferMode = mode; if(lastMetricValue<maxGoodPing){ nGoodPings++; }else if(lastMetricValue>minBadPing){ nBadPings++; }else{ nNeutralPings++; } pingMap.addMetricToMap(lastMetricValue); //If the interval is up, we need to either recommend new limits or reset. long curr = SystemTime.getCurrentTime(); if( curr > startTime+INTERVAL ){ boolean needLowerLimts = checkForLowerLimits(); if( needLowerLimts ){ //prepare the package for lowering the limit. if( transferMode.isConfTestingLimits() ){ reset(mode); return false; }else if( transferMode.isDownloadMode() ){ //recommend a new downloading limit. newLimit = pingMap.guessDownloadLimit(); SpeedManagerLogger.trace("PingSpaceMonitor -> guessDownloadLimit: newLimit="+newLimit); //on cable modems uploads can be over-estimated by 3x. int uploadLimitGuess = pingMap.guessUploadLimit(); SpeedManagerLogger.trace("PingSpaceMonitor -> guessUploadLimit: guessUploadLimit="+uploadLimitGuess); //download limit cannot be less the 40k if(newLimit<40960){ newLimit=40960; } hasNewLimit = true; limitType = DOWNLOAD; reset(mode); return true; }else{ //only seeding mode is left recommend a new upload limit. newLimit = pingMap.guessUploadLimit(); //upload limit cannot be less the 20k if(newLimit<20480){ newLimit=20480; } hasNewLimit = true; limitType = UPLOAD; reset(mode); return true; } }else{ //No need for lower limits. reset(mode); } }//if return false; } //Simple test currently. 15% bad pings. private boolean checkForLowerLimits() { int totalPings = nGoodPings+nBadPings+nNeutralPings; float percentBad = (float)nBadPings/(float)totalPings; if(percentBad>0.15f){ return true; }else{ return false; } } public void reset(TransferMode mode){ //log results. StringBuffer sb = new StringBuffer("ping-monitor:"); sb.append("good=").append(nGoodPings).append(":"); sb.append("bad=").append(nBadPings).append(":"); sb.append("neutral=").append(nNeutralPings); SpeedManagerLogger.log( sb.toString() ); //reset all the counters. nBadPings=nGoodPings=nNeutralPings=0; //saturated mode counters upNone=upLow=upMed=upHigh=upAtLimit=0; downNone=downLow=downMed=downHigh=downAtLimit=0; pingMap = new PingSpaceMapper(maxGoodPing,minBadPing); startTime = SystemTime.getCurrentTime(); transferMode = mode; } /** * True if we have a new limit. * @return - true if there is a new limit. */ boolean hasNewLimit(){ return hasNewLimit; } public int getNewLimit(){ return newLimit; } public int limitType(){ return limitType; } /** * Call after getting new limits. */ public void resetNewLimit(){ hasNewLimit = false; newLimit = -2; limitType = NONE; } }//class