/*
* Created on Feb 1, 2013
* Created by Paul Gardner
*
* Copyright 2013 Azureus Software, Inc. 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; version 2 of the License only.
*
* 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.
*/
package org.gudy.azureus2.core3.stats.transfer.impl;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerStats;
import org.gudy.azureus2.core3.stats.transfer.LongTermStats;
import org.gudy.azureus2.core3.stats.transfer.LongTermStatsListener;
import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AsyncDispatcher;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.core3.util.SimpleTimer;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TimerEvent;
import org.gudy.azureus2.core3.util.TimerEventPerformer;
import org.gudy.azureus2.core3.util.TimerEventPeriodic;
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.util.CopyOnWriteList;
import com.aelitis.azureus.core.util.average.Average;
import com.aelitis.azureus.core.util.average.AverageFactory;
import com.aelitis.azureus.plugins.dht.DHTPlugin;
public class
LongTermStatsImpl
implements LongTermStats
{
private static final int VERSION = 1;
private static final long MIN_IN_MILLIS = 60*1000;
private static final long DAY_IN_MILLIS = 24*60*60*1000;
public static final int RT_SESSION_START = 1;
public static final int RT_SESSION_STATS = 2;
public static final int RT_SESSION_END = 3;
private AzureusCore core;
private GlobalManagerStats gm_stats;
private DHT[] dhts;
private final int STAT_ENTRY_COUNT = 6;
// totals at start of session
private long st_p_sent;
private long st_d_sent;
private long st_p_received;
private long st_d_received;
private long st_dht_sent;
private long st_dht_received;
// session offsets at start of session
private long ss_p_sent;
private long ss_d_sent;
private long ss_p_received;
private long ss_d_received;
private long ss_dht_sent;
private long ss_dht_received;
private long[] line_stats_prev = new long[STAT_ENTRY_COUNT];
private Average[] stat_averages = new Average[STAT_ENTRY_COUNT];
{
for ( int i=0;i<STAT_ENTRY_COUNT;i++){
stat_averages[i] = AverageFactory.MovingImmediateAverage( 3 );
}
}
private boolean active;
private boolean closing;
private TimerEventPeriodic event;
private PrintWriter writer;
private String writer_rel_file;
private DayCache day_cache;
private final int MONTH_CACHE_MAX = 3;
private Map<String,MonthCache> month_cache_map =
new LinkedHashMap<String,MonthCache>(MONTH_CACHE_MAX,0.75f,true)
{
protected boolean
removeEldestEntry(
Map.Entry<String,MonthCache> eldest)
{
return size() > MONTH_CACHE_MAX;
}
};
private static SimpleDateFormat debug_utc_format = new SimpleDateFormat( "yyyy,MM,dd:HH:mm" );
private static SimpleDateFormat utc_date_format = new SimpleDateFormat( "yyyy,MM,dd" );
static{
debug_utc_format.setTimeZone( TimeZone.getTimeZone( "UTC" ));
utc_date_format.setTimeZone( TimeZone.getTimeZone( "UTC" ));
}
private final File stats_dir;
private long session_total;
private CopyOnWriteList<Object[]> listeners = new CopyOnWriteList<Object[]>();
private AsyncDispatcher dispatcher = new AsyncDispatcher( "lts", 5000 );
private int start_of_week = -1;
private int start_of_month = -1;
private
LongTermStatsImpl(
File _stats_dir )
{
stats_dir = _stats_dir;
}
public
LongTermStatsImpl(
AzureusCore _core,
GlobalManagerStats _gm_stats )
{
core = _core;
gm_stats = _gm_stats;
stats_dir = FileUtil.getUserFile( "stats" );
COConfigurationManager.addParameterListener(
"long.term.stats.enable",
new ParameterListener()
{
public void
parameterChanged(
String name)
{
boolean enabled = COConfigurationManager.getBooleanParameter( name );
synchronized( LongTermStatsImpl.this ){
if ( enabled ){
if ( !active ){
sessionStart();
}
}else{
if ( active ){
sessionEnd();
}
}
}
}
});
_core.addLifecycleListener(
new AzureusCoreLifecycleAdapter()
{
public void
componentCreated(
AzureusCore core,
AzureusCoreComponent component )
{
if ( component instanceof GlobalManager ){
synchronized( LongTermStatsImpl.this ){
sessionStart();
}
}
}
public void
stopped(
AzureusCore core )
{
synchronized( LongTermStatsImpl.this ){
closing = true;
if ( active ){
sessionEnd();
}
}
}
});
}
public boolean
isEnabled()
{
synchronized( this ){
return( active );
}
}
private DHT[]
getDHTs()
{
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];
}
}
return( dhts );
}
private void
sessionStart()
{
OverallStatsImpl stats = (OverallStatsImpl)StatsFactory.getStats();
synchronized( this ){
if ( closing ){
return;
}
boolean enabled = COConfigurationManager.getBooleanParameter( "long.term.stats.enable" );
if ( active || !enabled ){
return;
}
active = true;
long[] snap = stats.getLastSnapshot();
ss_d_received = gm_stats.getTotalDataBytesReceived();
ss_p_received = gm_stats.getTotalProtocolBytesReceived();
ss_d_sent = gm_stats.getTotalDataBytesSent();
ss_p_sent = gm_stats.getTotalProtocolBytesSent();
ss_dht_sent = 0;
ss_dht_received = 0;
if ( core.isStarted()){
DHT[] dhts = getDHTs();
if ( dhts != null ){
for ( DHT dht: dhts ){
DHTTransportStats dht_stats = dht.getTransport().getStats();
ss_dht_sent += dht_stats.getBytesSent();
ss_dht_received += dht_stats.getBytesReceived();
}
}
}
st_p_sent = snap[0] + ( ss_p_sent - snap[6]);
st_d_sent = snap[1] + ( ss_d_sent - snap[7]);
st_p_received = snap[2] + ( ss_p_received - snap[8]);
st_d_received = snap[3] + ( ss_d_received - snap[9]);
st_dht_sent = snap[4] + ( ss_dht_sent - snap[10]);
st_dht_received = snap[5] + ( ss_dht_received - snap[11]);
write( RT_SESSION_START,
new long[]{
st_p_sent,
st_d_sent,
st_p_received,
st_d_received,
st_dht_sent,
st_dht_received });
if ( event == null ){ // should always be null but hey ho
event =
SimpleTimer.addPeriodicEvent(
"LongTermStats",
MIN_IN_MILLIS,
new TimerEventPerformer()
{
public void
perform(TimerEvent event)
{
updateStats();
}
});
}
}
}
private void
sessionEnd()
{
synchronized( this ){
if ( !active ){
return;
}
updateStats( RT_SESSION_END );
active = false;
if ( event != null ){
event.cancel();
event = null;
}
}
}
private void
updateStats()
{
updateStats( RT_SESSION_STATS );
}
private void
updateStats(
int record_type )
{
long current_d_received = gm_stats.getTotalDataBytesReceived();
long current_p_received = gm_stats.getTotalProtocolBytesReceived();
long current_d_sent = gm_stats.getTotalDataBytesSent();
long current_p_sent = gm_stats.getTotalProtocolBytesSent();
long current_dht_sent = 0;
long current_dht_received = 0;
DHT[] dhts = getDHTs();
if ( dhts != null ){
for ( DHT dht: dhts ){
DHTTransportStats dht_stats = dht.getTransport().getStats();
current_dht_sent += dht_stats.getBytesSent();
current_dht_received += dht_stats.getBytesReceived();
}
}
write( record_type,
new long[]{
( current_p_sent - ss_p_sent ),
( current_d_sent - ss_d_sent ),
( current_p_received - ss_p_received ),
( current_d_received - ss_d_received ),
( current_dht_sent - ss_dht_sent ),
( current_dht_received - ss_dht_received )});
}
private void
write(
int record_type,
long[] line_stats )
{
synchronized( this ){
try{
final long now = SystemTime.getCurrentTime();
final long now_mins = now/(1000*60);
String[] bits = utc_date_format.format( new Date( now )).split( "," );
String year = bits[0];
String month = bits[1];
String day = bits[2];
String current_rel_file = year + File.separator + month + File.separator + day + ".dat";
String line;
String stats_str = "";
if ( record_type == RT_SESSION_START ){
// absolute values
for ( int i=0;i<line_stats.length;i++ ){
stats_str += "," + line_stats[i];
line_stats_prev[i] = 0;
}
day_cache = null;
}else{
// relative values
long[] diffs = new long[STAT_ENTRY_COUNT];
for ( int i=0;i<line_stats.length;i++ ){
long diff = line_stats[i] - line_stats_prev[i];
session_total += diff;
diffs[i] = diff;
stats_str += "," + diff;
line_stats_prev[i] = line_stats[i];
stat_averages[i].update( diff );
}
if ( day_cache != null ){
if ( day_cache.isForDay( year, month, day )){
day_cache.addRecord( now_mins, diffs );
}
}
}
if ( record_type != RT_SESSION_STATS ){
line = (record_type==RT_SESSION_START?"s,":"e,") + VERSION + "," + now_mins + stats_str;
}else{
line = stats_str.substring(1);
}
if ( writer == null || !writer_rel_file.equals( current_rel_file )){
// first open of a file or file switch
if ( writer != null ){
// file switch
if ( record_type != RT_SESSION_START ){
writer.println( line );
}
writer.close();
if ( writer.checkError()){
writer = null;
throw( new IOException( "Write faled" ));
}
writer = null;
}
// no point in opening a new file just to record the session-end
if ( record_type != RT_SESSION_END ){
File file = new File( stats_dir, current_rel_file );
file.getParentFile().mkdirs();
writer = new PrintWriter( new FileWriter( file, true ));
writer_rel_file = current_rel_file;
if ( record_type == RT_SESSION_START ){
writer.println( line );
}else{
// first entry in a new file, files always start with a session-start so they
// can be processed in isolation so reset the session data and start a new one
st_p_sent += line_stats[0];
st_d_sent += line_stats[1];
st_p_received += line_stats[2];
st_d_received += line_stats[3];
st_dht_sent += line_stats[4];
st_dht_received += line_stats[5];
ss_p_sent += line_stats[0];
ss_d_sent += line_stats[1];
ss_p_received += line_stats[2];
ss_d_received += line_stats[3];
ss_dht_sent += line_stats[4];
ss_dht_received += line_stats[5];
stats_str = "";
long[] st_stats = new long[]{ st_p_sent,st_d_sent, st_p_received,st_d_received, st_dht_sent, st_dht_received };
for ( int i=0;i<st_stats.length; i++ ){
stats_str += "," + st_stats[i];
line_stats_prev[i] = 0;
}
line = "s," + VERSION + "," + now_mins + stats_str;
writer.println( line );
}
}
}else{
writer.println( line );
}
}catch( Throwable e ){
Debug.out( "Failed to write long term stats", e );
}finally{
if ( writer != null ){
if ( record_type == RT_SESSION_END ){
writer.close();
}
if ( writer.checkError()){
Debug.out( "Failed to write long term stats" );
writer.close();
writer = null;
}else{
if ( record_type == RT_SESSION_END ){
writer = null;
}
}
}
}
}
if ( record_type != RT_SESSION_END ){
final List<LongTermStatsListener> to_fire = new ArrayList<LongTermStatsListener>();
for ( Object[] entry: listeners ){
long diff = session_total - (Long)entry[2];
if ( diff >= (Long)entry[1]){
entry[2] = session_total;
to_fire.add((LongTermStatsListener)entry[0]);
}
}
if ( to_fire.size() > 0 ){
dispatcher.dispatch(
new AERunnable()
{
@Override
public void
runSupport()
{
for ( LongTermStatsListener l: to_fire ){
try{
l.updated( LongTermStatsImpl.this );
}catch( Throwable e ){
Debug.out( e );
}
}
}
});
}
}
}
private static String
getString(
long[] stats )
{
String str = "";
for ( long s: stats ){
str += (str.length()==0?"":", ") + s;
}
return( str );
}
private MonthCache
getMonthCache(
String year,
String month )
{
String key = year + "_" + month;
MonthCache cache = month_cache_map.get( key );
if ( cache == null ){
cache = new MonthCache( year, month );
month_cache_map.put( key, cache );
}
return( cache );
}
public long[]
getTotalUsageInPeriod(
Date start_date,
Date end_date )
{
return( getTotalUsageInPeriod( start_date, end_date, null ));
}
public long[]
getTotalUsageInPeriod(
Date start_date,
Date end_date,
RecordAccepter accepter )
{
boolean enable_caching = accepter == null;
synchronized( this ){
long[] result = new long[STAT_ENTRY_COUNT];
long start_millis = start_date.getTime();
long end_millis = end_date.getTime();
long now = SystemTime.getCurrentTime();
long now_day = (now/DAY_IN_MILLIS)*DAY_IN_MILLIS;
if ( end_millis > now ){
end_millis = now;
}
long start_day = (start_millis/DAY_IN_MILLIS)*DAY_IN_MILLIS;
long end_day = (end_millis/DAY_IN_MILLIS)*DAY_IN_MILLIS;
if ( start_day > end_day ){
return( result );
}
long start_offset = start_millis - start_day;
start_offset = start_offset/MIN_IN_MILLIS;
boolean offset_cachable = start_offset % 60 == 0;
System.out.println( "start=" + debug_utc_format.format( start_date ) + ", end=" + debug_utc_format.format( end_date ) + ", offset=" + start_offset);
MonthCache month_cache = null;
for ( long this_day=start_day;this_day<=end_day;this_day+=DAY_IN_MILLIS ){
String[] bits = utc_date_format.format( new Date( this_day )).split( "," );
String year_str = bits[0];
String month_str = bits[1];
String day_str = bits[2];
int year = Integer.parseInt( year_str );
int month = Integer.parseInt( month_str );
int day = Integer.parseInt( day_str );
long cache_offset = this_day == start_day?start_offset:0;
boolean can_cache;
if ( enable_caching ){
if ( month_cache == null || !month_cache.isForMonth( year_str, month_str )){
if ( month_cache != null && month_cache.isDirty()){
month_cache.save();
}
month_cache = getMonthCache( year_str, month_str );
}
can_cache =
this_day != now_day &&
( this_day > start_day || ( this_day == start_day && offset_cachable )) &&
this_day < end_day;
if ( can_cache ){
long[] cached_totals = month_cache.getTotals( day, cache_offset );
if ( cached_totals != null ){
for ( int i=0;i<cached_totals.length;i++){
result[i] += cached_totals[i];
}
continue;
}
}else{
if ( this_day == now_day ){
if ( day_cache != null ){
if ( day_cache.isForDay( year_str, month_str, day_str )){
long[] cached_totals = day_cache.getTotals( cache_offset );
if ( cached_totals != null ){
for ( int i=0;i<cached_totals.length;i++){
result[i] += cached_totals[i];
}
continue;
}
}else{
day_cache = null;
}
}
}
}
}else{
can_cache = false;
}
String current_rel_file = bits[0] + File.separator + bits[1] + File.separator + bits[2] + ".dat";
File stats_file = new File( stats_dir, current_rel_file );
if ( !stats_file.exists()){
if ( can_cache ){
month_cache.setTotals( day, cache_offset, new long[0] );
}
}else{
LineNumberReader lnr = null;
try{
System.out.println( "Reading " + stats_file );
lnr = new LineNumberReader( new FileReader( stats_file ));
long file_start_time = 0;
long[] file_totals = null;
long[] file_result_totals = new long[STAT_ENTRY_COUNT];
long[] session_start_stats = null;
long session_start_time = 0;
long session_time = 0;
while( true ){
String line = lnr.readLine();
if ( line == null ){
break;
}
//System.out.println( line );
String[] fields = line.split( "," );
if ( fields.length < 6 ){
continue;
}
String first_field = fields[0];
if ( first_field.equals("s")){
session_start_time = Long.parseLong( fields[2] )*MIN_IN_MILLIS;
if ( file_totals == null ){
file_totals = new long[STAT_ENTRY_COUNT];
file_start_time = session_start_time;
}
session_time = session_start_time;
session_start_stats = new long[STAT_ENTRY_COUNT];
for ( int i=3;i<9;i++){
session_start_stats[i-3] = Long.parseLong( fields[i] );
}
}else if ( session_start_time > 0 ){
session_time += MIN_IN_MILLIS;
int field_offset = 0;
if ( first_field.equals( "e" )){
field_offset = 3;
}
long[] line_stats = new long[STAT_ENTRY_COUNT];
for ( int i=0;i<6;i++){
line_stats[i] = Long.parseLong( fields[i+field_offset] );
file_totals[i] += line_stats[i];
}
if ( session_time >= start_millis &&
session_time <= end_millis ){
if ( accepter == null || accepter.acceptRecord( session_time )){
for ( int i=0;i<6;i++){
result[i] += line_stats[i];
file_result_totals[i] += line_stats[i];
}
}
}
//System.out.println( getString( line_stats ));
}
}
if ( file_totals == null ){
file_totals = new long[0];
}
System.out.println( "File total: start=" + debug_utc_format.format(file_start_time) + ", end=" + debug_utc_format.format(session_time) + " - " + getString( file_totals ));
if ( can_cache ){
month_cache.setTotals( day, cache_offset, file_result_totals );
if ( cache_offset != 0 ){
month_cache.setTotals( day, 0, file_totals );
}
}else{
if ( enable_caching ){
if ( this_day == now_day ){
if ( day_cache == null ){
System.out.println( "Creating day cache" );
day_cache = new DayCache( year_str, month_str, day_str );
}
day_cache.setTotals( cache_offset, file_result_totals );
if ( cache_offset != 0 ){
day_cache.setTotals( 0, file_totals );
}
}
}
}
}catch( Throwable e ){
Debug.out( e );
}finally{
if ( lnr != null ){
try{
lnr.close();
}catch( Throwable e ){
}
}
}
}
}
if ( enable_caching ){
if ( month_cache != null && month_cache.isDirty()){
month_cache.save();
}
}
System.out.println( " -> " + getString( result ));
return( result );
}
}
public long[]
getTotalUsageInPeriod(
int period_type )
{
return( getTotalUsageInPeriod( period_type, null ));
}
public long[]
getTotalUsageInPeriod(
int period_type,
RecordAccepter accepter )
{
if ( start_of_week == -1 ){
COConfigurationManager.addAndFireParameterListeners(
new String[]{ "long.term.stats.weekstart", "long.term.stats.monthstart" },
new ParameterListener()
{
public void
parameterChanged(
String name )
{
start_of_week = COConfigurationManager.getIntParameter( "long.term.stats.weekstart" );
start_of_month = COConfigurationManager.getIntParameter( "long.term.stats.monthstart" );
}
});
}
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis( SystemTime.getCurrentTime());
calendar.set( Calendar.MILLISECOND, 0 );
calendar.set( Calendar.MINUTE, 0 );
calendar.set( Calendar.HOUR_OF_DAY, 0 );
long top_time = calendar.getTimeInMillis() + DAY_IN_MILLIS - 1;
if ( period_type == PT_CURRENT_DAY ){
}else if ( period_type == PT_CURRENT_WEEK ){
// sun = 1, mon = 2 etc
int day_of_week = calendar.get( Calendar.DAY_OF_WEEK );
if ( day_of_week == start_of_week ){
}else if ( day_of_week > start_of_week ){
calendar.add( Calendar.DAY_OF_WEEK, - ( day_of_week - start_of_week ));
}else{
calendar.add( Calendar.DAY_OF_WEEK, - ( 7 - ( start_of_week - day_of_week )));
}
}else{
if ( start_of_month == 1 ){
calendar.set( Calendar.DAY_OF_MONTH, 1 );
}else{
int day_of_month = calendar.get( Calendar.DAY_OF_MONTH );
if ( day_of_month == start_of_month ){
}else if ( day_of_month > start_of_month ){
calendar.set( Calendar.DAY_OF_MONTH, start_of_month );
}else{
calendar.add( Calendar.MONTH, -1 );
calendar.set( Calendar.DAY_OF_MONTH, start_of_month );
}
}
}
long bottom_time = calendar.getTimeInMillis();
return( getTotalUsageInPeriod( new Date( bottom_time ), new Date( top_time ), accepter ));
}
public long[]
getCurrentRateBytesPerSecond()
{
long[] result = new long[STAT_ENTRY_COUNT];
for ( int i=0;i<STAT_ENTRY_COUNT;i++){
result[i] = (long)( stat_averages[i].getAverage()/60 );
}
return( result );
}
public void
addListener(
long min_delta_bytes,
final LongTermStatsListener listener )
{
listeners.add( new Object[]{ listener, min_delta_bytes, session_total });
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
listener.updated( LongTermStatsImpl.this );
}
});
}
public void
removeListener(
LongTermStatsListener listener )
{
for ( Object[] entry: listeners ){
if ( entry[0] == listener ){
listeners.remove( entry );
break;
}
}
}
private class
DayCache
{
private String year;
private String month;
private String day;
private Map<Long,long[]> contents = new HashMap<Long, long[]>();
private
DayCache(
String _year,
String _month,
String _day )
{
year = _year;
month = _month;
day = _day;
}
private boolean
isForDay(
String _year,
String _month,
String _day )
{
return( year.equals( _year ) && month.equals( _month ) && day.equals( _day ));
}
private void
addRecord(
long offset,
long[] stats )
{
for ( Map.Entry<Long,long[]> entry: contents.entrySet()){
if ( offset >= entry.getKey()){
long[] old = entry.getValue();
for ( int i=0;i<old.length;i++){
old[i] += stats[i];
}
}
}
}
private long[]
getTotals(
long offset )
{
return( contents.get( offset ));
}
private void
setTotals(
long offset,
long[] value )
{
contents.put( offset, value );
}
}
private class
MonthCache
{
private String year;
private String month;
private boolean dirty;
private Map<String,List<Long>> contents;
private
MonthCache(
String _year,
String _month )
{
year = _year;
month = _month;
}
private File
getCacheFile()
{
return( new File( stats_dir, year + File.separator + month + File.separator + "cache.dat" ));
}
private boolean
isForMonth(
String _year,
String _month )
{
return( year.equals( _year ) && month.equals( _month ));
}
private Map<String,List<Long>>
getContents()
{
if ( contents == null ){
File file = getCacheFile();
if ( file.exists()){
System.out.println( "Reading cache: " + file );
contents = FileUtil.readResilientFile( file );
}else{
contents = new HashMap<String, List<Long>>();
}
}
return( contents );
}
private long[]
getTotals(
int day )
{
List<Long> records = getContents().get( String.valueOf( day ));
if ( records != null ){
long[] result = new long[STAT_ENTRY_COUNT];
if ( records.size() == STAT_ENTRY_COUNT ){
for ( int i=0;i<STAT_ENTRY_COUNT;i++){
result[i] = (Long)records.get(i);
}
}
return( result );
}
return( null );
}
private long[]
getTotals(
int day,
long start_offset )
{
if ( start_offset == 0 ){
return( getTotals( day ));
}else{
List<Long> records = getContents().get( day + "." + start_offset );
if ( records != null ){
long[] result = new long[STAT_ENTRY_COUNT];
if ( records.size() == STAT_ENTRY_COUNT ){
for ( int i=0;i<STAT_ENTRY_COUNT;i++){
result[i] = (Long)records.get(i);
}
}
return( result );
}
return( null );
}
}
private void
setTotals(
int day,
long[] totals )
{
List<Long> records = new ArrayList<Long>();
for ( Long l: totals ){
records.add( l );
}
getContents().put( String.valueOf( day ), records );
dirty = true;
}
private void
setTotals(
int day,
long start_offset,
long[] totals )
{
if ( start_offset == 0 ){
setTotals( day, totals );
}else{
List<Long> records = new ArrayList<Long>();
for ( Long l: totals ){
records.add( l );
}
getContents().put( day + "." + start_offset, records );
dirty = true;
}
}
private boolean
isDirty()
{
return( dirty );
}
private void
save()
{
File file = getCacheFile();
file.getParentFile().mkdirs();
System.out.println( "Writing cache: " + file );
FileUtil.writeResilientFile( file, contents );
dirty = false;
}
}
public static void
main(
String[] args )
{
try{
LongTermStatsImpl impl = new LongTermStatsImpl( new File( "C:\\Test\\plus2\\stats" ));
SimpleDateFormat local_format = new SimpleDateFormat( "yyyy,MM,dd" );
Date start_date = local_format.parse( "2013,07,10" );
Date end_date = local_format.parse( "2013,07,16" );
long[] usage =
impl.getTotalUsageInPeriod(
start_date,
end_date,
new RecordAccepter()
{
public boolean
acceptRecord(
long timestamp)
{
System.out.println( new Date( timestamp ));
return( false );
}
});
System.out.println( getString( usage ));
//System.out.println( getString(impl.getTotalUsageInPeriod( PT_CURRENT_DAY )));
//System.out.println( getString(impl.getTotalUsageInPeriod( PT_CURRENT_WEEK )));
//System.out.println( getString(impl.getTotalUsageInPeriod( PT_CURRENT_MONTH )));
}catch( Throwable e ){
e.printStackTrace();
}
}
}