Added support for adding/removing periods to already existing RateStats.

This commit is contained in:
dev
2011-07-20 13:27:44 +00:00
parent 9a6888d7f9
commit 085ca76bcc
2 changed files with 100 additions and 31 deletions

View File

@ -119,7 +119,8 @@ public class Rate {
public void setRateStat(RateStat rs) { _stat = rs; } public void setRateStat(RateStat rs) { _stat = rs; }
/** /**
* * A rate with period shorter than Router.COALESCE_TIME = 50*1000 has to
* be manually coalesced before values are fetched from it.
* @param period number of milliseconds in the period this rate deals with * @param period number of milliseconds in the period this rate deals with
* @throws IllegalArgumentException if the period is not greater than 0 * @throws IllegalArgumentException if the period is not greater than 0
*/ */

View File

@ -3,9 +3,12 @@ package net.i2p.stat;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.Log; import net.i2p.util.Log;
/** coordinate a moving rate over various periods */ /** coordinate a moving rate over various periods */
@ -18,7 +21,7 @@ public class RateStat {
/** describe the stat */ /** describe the stat */
private final String _description; private final String _description;
/** actual rate objects for this statistic */ /** actual rate objects for this statistic */
private final Rate _rates[]; private final ConcurrentHashMap<Long, Rate> _rates;
/** component we tell about events as they occur */ /** component we tell about events as they occur */
private StatLog _statLog; private StatLog _statLog;
@ -26,10 +29,11 @@ public class RateStat {
_statName = name; _statName = name;
_description = description; _description = description;
_groupName = group; _groupName = group;
_rates = new Rate[periods.length]; _rates = new ConcurrentHashMap<Long, Rate>();
for (int i = 0; i < periods.length; i++) { for (int i = 0; i < periods.length; i++) {
_rates[i] = new Rate(periods[i]); Rate rate = new Rate(periods[i]);
_rates[i].setRateStat(this); rate.setRateStat(this);
_rates.put(rate.getPeriod(),rate);;
} }
} }
public void setStatLog(StatLog sl) { _statLog = sl; } public void setStatLog(StatLog sl) { _statLog = sl; }
@ -39,14 +43,18 @@ public class RateStat {
*/ */
public void addData(long value, long eventDuration) { public void addData(long value, long eventDuration) {
if (_statLog != null) _statLog.addData(_groupName, _statName, value, eventDuration); if (_statLog != null) _statLog.addData(_groupName, _statName, value, eventDuration);
for (int i = 0; i < _rates.length; i++) for (Entry<Long, Rate> e: _rates.entrySet())
_rates[i].addData(value, eventDuration); e.getValue().addData(value, eventDuration);
} }
/** coalesce all the stats */ /** coalesce all the stats */
public void coalesceStats() { public void coalesceStats() {
for (int i = 0; i < _rates.length; i++) for (Entry<Long, Rate> e: _rates.entrySet()){
_rates[i].coalesce(); e.getValue().coalesce();
if (_statName == "bw.sendRate"){
System.out.println("Coalescing Rate(" + e.getValue().getPeriod() + ")");
}
}
} }
public String getName() { public String getName() {
@ -62,26 +70,68 @@ public class RateStat {
} }
public long[] getPeriods() { public long[] getPeriods() {
long rv[] = new long[_rates.length]; long rv[] = new long[_rates.size()];
for (int i = 0; i < _rates.length; i++) int counter = 0;
rv[i] = _rates[i].getPeriod(); for (Entry<Long, Rate> e: _rates.entrySet())
rv[counter++] = e.getValue().getPeriod();
return rv; return rv;
} }
public double getLifetimeAverageValue() { public double getLifetimeAverageValue() {
if ( (_rates == null) || (_rates.length <= 0) ) return 0; if ( (_rates == null) || (_rates.size() <= 0) ) return 0;
return _rates[0].getLifetimeAverageValue(); return _rates.entrySet().iterator().next().getValue().getLifetimeAverageValue();
} }
public long getLifetimeEventCount() { public long getLifetimeEventCount() {
if ( (_rates == null) || (_rates.length <= 0) ) return 0; if ( (_rates == null) || (_rates.size() <= 0) ) return 0;
return _rates[0].getLifetimeEventCount(); return _rates.entrySet().iterator().next().getValue().getLifetimeEventCount();
} }
/**
* Returns rate with requested period if it exists,
* otherwise creates new rate with requested period, adds it to list of rates and returns it.
* @param period
* @return
*/
public Rate getRate(long period) { public Rate getRate(long period) {
for (int i = 0; i < _rates.length; i++) { if (_rates.containsKey(period)){
if (_rates[i].getPeriod() == period) return _rates[i]; return _rates.get(period);
} else {
Rate rate = new Rate(period);
rate.setRateStat(this);
System.out.println("New Rate(" + _statName + ", " + rate.getPeriod() + ")");
_rates.put(period, rate);
return rate;
} }
return null; }
/**
* Adds a new rate with the requested period, provided that
* a rate with that period does not already exist.
* @param period
*/
public void addRate(long period) {
if (!_rates.containsKey(period)){
Rate rate = new Rate(period);
rate.setRateStat(this);
_rates.put(period, rate);
}
}
/**
* If a rate with the provided period exists, remove it.
* @param period
*/
public void removeRate(long period) {
_rates.remove(period);
}
/**
* Tests if a rate with the provided period exists within this RateStat.
* @param period
* @return
*/
public boolean containsRate(long period) {
return _rates.containsKey(period);
} }
@Override @Override
@ -112,8 +162,8 @@ public class RateStat {
RateStat rs = (RateStat) obj; RateStat rs = (RateStat) obj;
if (DataHelper.eq(getGroupName(), rs.getGroupName()) && DataHelper.eq(getDescription(), rs.getDescription()) if (DataHelper.eq(getGroupName(), rs.getGroupName()) && DataHelper.eq(getDescription(), rs.getDescription())
&& DataHelper.eq(getName(), rs.getName())) { && DataHelper.eq(getName(), rs.getName())) {
for (int i = 0; i < _rates.length; i++) for (Entry<Long, Rate> e: _rates.entrySet())
if (!_rates[i].equals(rs.getRate(_rates[i].getPeriod()))) return false; if (!e.getValue().equals(rs.getRate(e.getValue().getPeriod()))) return false;
return true; return true;
} }
@ -129,13 +179,13 @@ public class RateStat {
buf.append("# ").append(NL).append(NL); buf.append("# ").append(NL).append(NL);
out.write(buf.toString().getBytes()); out.write(buf.toString().getBytes());
buf.setLength(0); buf.setLength(0);
for (int i = 0; i < _rates.length; i++) { for (Entry<Long, Rate> e: _rates.entrySet()){
buf.append("#######").append(NL); buf.append("#######").append(NL);
buf.append("# Period : ").append(DataHelper.formatDuration(_rates[i].getPeriod())).append(" for rate ") buf.append("# Period : ").append(DataHelper.formatDuration(e.getValue().getPeriod())).append(" for rate ")
.append(_groupName).append(" - ").append(_statName).append(NL); .append(_groupName).append(" - ").append(_statName).append(NL);
buf.append(NL); buf.append(NL);
String curPrefix = prefix + "." + DataHelper.formatDuration(_rates[i].getPeriod()); String curPrefix = prefix + "." + DataHelper.formatDuration(e.getValue().getPeriod());
_rates[i].store(curPrefix, buf); e.getValue().store(curPrefix, buf);
out.write(buf.toString().getBytes()); out.write(buf.toString().getBytes());
buf.setLength(0); buf.setLength(0);
} }
@ -156,14 +206,15 @@ public class RateStat {
* @throws IllegalArgumentException if the data was formatted incorrectly * @throws IllegalArgumentException if the data was formatted incorrectly
*/ */
public void load(Properties props, String prefix, boolean treatAsCurrent) throws IllegalArgumentException { public void load(Properties props, String prefix, boolean treatAsCurrent) throws IllegalArgumentException {
for (int i = 0; i < _rates.length; i++) { for (Entry<Long, Rate> e: _rates.entrySet()) {
long period = _rates[i].getPeriod(); long period = e.getValue().getPeriod();
String curPrefix = prefix + "." + DataHelper.formatDuration(period); String curPrefix = prefix + "." + DataHelper.formatDuration(period);
try { try {
_rates[i].load(props, curPrefix, treatAsCurrent); e.getValue().load(props, curPrefix, treatAsCurrent);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
_rates[i] = new Rate(period); Rate rate = new Rate(period);
_rates[i].setRateStat(this); rate.setRateStat(this);
_rates.put(rate.getPeriod(), rate);
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Rate for " + prefix + " is corrupt, reinitializing that period"); _log.warn("Rate for " + prefix + " is corrupt, reinitializing that period");
} }
@ -171,17 +222,33 @@ public class RateStat {
} }
/********* /*********
*/
public static void main(String args[]) { public static void main(String args[]) {
RateStat rs = new RateStat("moo", "moo moo moo", "cow trueisms", new long[] { 60 * 1000, 60 * 60 * 1000, RateStat rs = new RateStat("moo", "moo moo moo", "cow trueisms", new long[] { 60 * 1000, 60 * 60 * 1000,
24 * 60 * 60 * 1000}); 24 * 60 * 60 * 1000});
for (int i = 0; i < 50; i++) {
rs.getRate(5500L);
System.out.println("Adding data..");
for (int i = 0; i < 500; i++) {
try { try {
Thread.sleep(20); Thread.sleep(20);
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
rs.addData(i * 100, 20); rs.addData(i * 100, 20);
} }
Rate rate5500 = rs.getRate(5500L);
System.out.println("Nbr of events: " + rate5500.getCurrentEventCount());
System.out.println("Average :" + rate5500.getAverageValue());
System.out.println("Coalescing stats..");
rs.coalesceStats(); rs.coalesceStats();
System.out.println("Average :" + rate5500.getAverageValue());
System.out.println("Coalescing this rate..");
rate5500.coalesce();
System.out.println("Average :" + rate5500.getAverageValue());
System.out.println("Lifetime average :" + rate5500.getLifetimeAverageValue());
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(2048); java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(2048);
try { try {
rs.store(baos, "rateStat.test"); rs.store(baos, "rateStat.test");
@ -207,5 +274,6 @@ public class RateStat {
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
} }
/**
*********/ *********/
} }