/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
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.
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 com.bigdata.io.writecache;
import com.bigdata.counters.CAT;
import com.bigdata.counters.CounterSet;
import com.bigdata.counters.Instrument;
/**
* Performance counters for the {@link WriteCache}.
* <p>
* Note: thread-safety is required for: {@link #nhit} and {@link #nmiss}. The
* rest should be Ok without additional synchronization, CAS operators, etc
* (mainly because they are updated while holding a lock).
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
*/
public class WriteCacheCounters implements IWriteCacheCounters {
/*
* read on the cache.
*/
/**
* #of read requests that are satisfied by the write cache.
*/
public final CAT nhit = new CAT();
/**
* The #of read requests that are not satisfied by the write cache.
*/
public final CAT nmiss = new CAT();
/*
* write on the cache.
*/
/**
* #of records accepted for eventual write onto the backing channel.
*/
public long naccept;
/**
* #of bytes accepted for eventual write onto the backing channel.
*/
public long bytesAccepted;
/*
* write on the channel.
*/
// /**
// * #of times {@link IWriteCache#flush(boolean)} was called.
// */
// public long nflush;
/**
* #of writes on the backing channel. Note that some write cache
* implementations do ordered writes and will therefore do one write per
* record while others do append only and therefore do one write per write
* cache flush. Note that in both cases we may have to redo a write if the
* backing channel was concurrently closed, so the value here can diverge
* from the #of accepted records and the #of requested flushes.
*/
public long nchannelWrite;
/**
* #of bytes written onto the backing channel.
*/
public long bytesWritten;
/**
* Total elapsed time writing onto the backing channel.
*/
public long elapsedWriteNanos;
public CounterSet getCounters() {
final CounterSet root = new CounterSet();
/*
* read on the cache.
*/
root.addCounter(NHIT, new Instrument<Long>() {
public void sample() {
setValue(nhit.get());
}
});
root.addCounter(NMISS, new Instrument<Long>() {
public void sample() {
setValue(nmiss.get());
}
});
root.addCounter(HIT_RATE, new Instrument<Double>() {
public void sample() {
final long nhit = WriteCacheCounters.this.nhit.get();
final long ntests = nhit + nmiss.get();
setValue(ntests == 0L ? 0d : (double) nhit / ntests);
}
});
/*
* write on the cache.
*/
// #of records accepted by the write cache.
root.addCounter(NACCEPT, new Instrument<Long>() {
public void sample() {
setValue(naccept);
}
});
// #of bytes in records accepted by the write cache.
root.addCounter(BYTES_ACCEPTED, new Instrument<Long>() {
public void sample() {
setValue(bytesAccepted);
}
});
/*
* write on the channel.
*/
// // #of times this write cache was flushed to the backing channel.
// root.addCounter(NFLUSHED, new Instrument<Long>() {
// public void sample() {
// setValue(nflush);
// }
// });
// #of writes onto the backing channel.
root.addCounter(NCHANNEL_WRITE, new Instrument<Long>() {
public void sample() {
setValue(nchannelWrite);
}
});
// #of bytes written onto the backing channel.
root.addCounter(BYTES_WRITTEN, new Instrument<Long>() {
public void sample() {
setValue(bytesWritten);
}
});
// average bytes per write (will under report if we must retry
// writes).
root.addCounter(BYTES_PER_WRITE, new Instrument<Double>() {
public void sample() {
final double bytesPerWrite = (nchannelWrite == 0 ? 0d
: (bytesWritten / (double) nchannelWrite));
setValue(bytesPerWrite);
}
});
// elapsed time writing on the backing channel.
root.addCounter(WRITE_SECS, new Instrument<Double>() {
public void sample() {
setValue(elapsedWriteNanos / 1000000000.);
}
});
return root;
} // getCounters()
public String toString() {
return getCounters().toString();
}
} // class WriteCacheCounters