All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.persistit.TreeStatistics Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/**
 * Copyright © 2011-2012 Akiban Technologies, Inc.  All rights reserved.
 * 
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * This program may also be available under different license terms.
 * For more information, see www.akiban.com or contact [email protected].
 * 
 * Contributors:
 * Akiban Technologies, Inc.
 */

package com.persistit;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import com.persistit.util.Util;

/**
 * 

* Collection of AtomicLong counters representing interesting * statistics in a {@link Tree}. The {@link #store} and {@link #load} methods * are designed to serialize and deserialize evolving versions of this class, * therefore it is possible to add and remove new counters while remaining * compatible with prior versions. *

*

* Currently implemented counters include: *

    *
  • Fetch
  • *
  • Traverse
  • *
  • Store
  • *
  • Remove
  • *
*

* * @author peter */ public class TreeStatistics { final static int MAX_SERIALIZED_SIZE = 54; private final AtomicLong _fetchCounter = new AtomicLong(); private final AtomicLong _traverseCounter = new AtomicLong(); private final AtomicLong _storeCounter = new AtomicLong(); private final AtomicLong _removeCounter = new AtomicLong(); private final AtomicBoolean _dirty = new AtomicBoolean(); /* * Array of AtomicLong instances currently used in serializing and * deserializing statistics. To ensure correct evolution of serialized * values, (a) the length of this array is limited to 32, and (b) if a field * becomes obsolete, replace it in this array by null rather than reusing * its position. */ private final AtomicLong[] _statsArray = new AtomicLong[] { _fetchCounter, _traverseCounter, _storeCounter, _removeCounter }; private final static String[] _statsArrayNames = new String[] { "fetchCounter", "traverseCounter", "storeCounter", "removeCounter" }; @Override public String toString() { final StringBuilder sb = new StringBuilder(); for (int index = 0; index < _statsArrayNames.length; index++) { final String name = _statsArrayNames[index]; final AtomicLong value = _statsArray[index]; if (name != null) { if (sb.length() > 0) { sb.append(", "); } sb.append(name); sb.append("="); sb.append(value == null ? "" : String.format("%,d", value.get())); } } return sb.toString(); } /** * @return the count of {@link Exchange#fetch} operations, including * {@link Exchange#fetchAndStore} and * {@link Exchange#fetchAndRemove} operations */ public long getFetchCounter() { return _fetchCounter.get(); } /** * @return the count of {@link Exchange#traverse} operations including * {@link Exchange#next} and {@link Exchange#previous} */ public long getTraverseCounter() { return _traverseCounter.get(); } /** * @return the count of {@link Exchange#store} operations, including * {@link Exchange#fetchAndStore} */ public long getStoreCounter() { return _storeCounter.get(); } /** * @return the count of {@link Exchange#remove} operations, including * {@link Exchange#fetchAndRemove} operations */ public long getRemoveCounter() { return _removeCounter.get(); } boolean isDirty() { return _dirty.get(); } void setDirty(final boolean dirty) { _dirty.set(dirty); } /** * @return Approximate size in bytes of the overhead space consumed in this * Tree by multi-version-values */ void reset() { _fetchCounter.set(0); _traverseCounter.set(0); _storeCounter.set(0); _removeCounter.set(0); setDirty(true); } void bumpFetchCounter() { _fetchCounter.incrementAndGet(); setDirty(true); } void bumpTraverseCounter() { _traverseCounter.incrementAndGet(); setDirty(true); } void bumpStoreCounter() { _storeCounter.incrementAndGet(); setDirty(true); } void bumpRemoveCounter() { _removeCounter.incrementAndGet(); setDirty(true); } /** *

* Serialize the statistics value in a variable-length byte array. The * format is designed to allow more fields to be added and existing fields * to be removed. Up to 64 field could eventually be allocated. The first * eight bytes of the serialized form include a bit map; a bit set in the * bit map indicates that the corresponding field is present in the * remaining bytes of the serialized form. Each field is stored as an 8-byte * long value. *

* * @param bytes * byte array into which statistics are serialized * @param index * at which serialization starts in byte array * @return length of serialized statistics */ int store(final byte[] bytes, final int index) { long bits = 0; int offset = index + 8; int field = 0; for (final AtomicLong a : _statsArray) { if (a != null) { final long v = a.get(); bits |= 1 << field; Util.putLong(bytes, offset, v); offset += 8; } field++; } Util.putLong(bytes, index, bits); return offset - index; } /** * Deserialize stored statistics values from the supplied byte array * starting at index. The first eight bytes contain a bit map * described in {@link #save(byte[], int)}. * * @param bytes * serialized statistics * @param index * at which serialized statistics start in the byte array */ int load(final byte[] bytes, final int index, final int length) { int offset = index + 8; final int end = index + length; final long bits = Util.getLong(bytes, index); for (int field = 0; field < 64; field++) { final AtomicLong a = field < _statsArray.length ? _statsArray[field] : null; if ((bits & (1 << field)) != 0) { if (a != null) { checkEnd(offset + 8, end); a.set(Util.getLong(bytes, offset)); } offset += 8; } } return length; } private void checkEnd(final int index, final int end) { if (index > end) { throw new IllegalStateException("TreeStatistics record is too short at offset " + index); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy