Revision: 90973b6c9be8
Author: troy.k...@gmail.com
Date: Sun Jun 19 21:26:01 2011
Log: Created FastPutsLinkedMap as another fast-puts implementation
similar ...
http://code.google.com/p/stajistics/source/detail?r=90973b6c9be8
Revision: 2f12e45d8925
Author: troy.k...@gmail.com
Date: Sun Jun 19 21:52:08 2011
Log: Created new io package containing filter streams for collecting
io sta...
http://code.google.com/p/stajistics/source/detail?r=2f12e45d8925
==============================================================================
Revision: 90973b6c9be8
Author: troy.k...@gmail.com
Date: Sun Jun 19 21:26:01 2011
Log: Created FastPutsLinkedMap as another fast-puts implementation
similar to FastPutsArrayMap (formerly FastPutsTableMap). Created
ServiceLifeCycle interface and Support class for reusable life cycle state
management. Improved escaping abilities of the open type StatsKey format.
http://code.google.com/p/stajistics/source/detail?r=90973b6c9be8
Added:
/stajistics-core/src/main/java/org/stajistics/util/FastPutsArrayMap.java
/stajistics-core/src/main/java/org/stajistics/util/FastPutsLinkedMap.java
/stajistics-core/src/main/java/org/stajistics/util/ServiceLifeCycle.java
/stajistics-core/src/test/java/org/stajistics/util/AbstractFastPutsMapTestCase.java
/stajistics-core/src/test/java/org/stajistics/util/FastPutsArrayMapTest.java
/stajistics-core/src/test/java/org/stajistics/util/FastPutsLinkedMapTest.java
/stajistics-core/src/test/java/org/stajistics/util/ServiceLifeCycleSupportTest.java
Deleted:
/stajistics-core/src/main/java/org/stajistics/util/FastPutsTableMap.java
/stajistics-core/src/test/java/org/stajistics/util/FastPutsTableMapTest.java
Modified:
/stajistics-core/src/main/java/org/stajistics/DefaultStatsKeyBuilder.java
/stajistics-core/src/main/java/org/stajistics/DefaultStatsManager.java
/stajistics-core/src/main/java/org/stajistics/StatsManager.java
/stajistics-core/src/main/java/org/stajistics/StatsManagerRegistry.java
/stajistics-core/src/main/java/org/stajistics/configuration/DefaultStatsConfigManager.java
/stajistics-core/src/main/java/org/stajistics/configuration/StatsConfigManager.java
/stajistics-core/src/main/java/org/stajistics/event/EventManager.java
/stajistics-core/src/main/java/org/stajistics/event/SynchronousEventManager.java
/stajistics-core/src/main/java/org/stajistics/management/StatsKeyOpenTypeConverter.java
/stajistics-core/src/main/java/org/stajistics/management/beans/DefaultStatsManagerMXBean.java
/stajistics-core/src/main/java/org/stajistics/management/beans/StatsManagerMXBean.java
/stajistics-core/src/main/java/org/stajistics/session/AbstractStatsSession.java
/stajistics-core/src/main/java/org/stajistics/session/DefaultSessionManager.java
/stajistics-core/src/main/java/org/stajistics/session/StatsSessionManager.java
/stajistics-core/src/main/java/org/stajistics/task/DebugTaskService.java
/stajistics-core/src/main/java/org/stajistics/task/TaskService.java
/stajistics-core/src/main/java/org/stajistics/task/ThreadPoolTaskService.java
/stajistics-core/src/test/java/org/stajistics/DefaultStatsManagerTest.java
/stajistics-core/src/test/java/org/stajistics/StatsTest.java
/stajistics-core/src/test/java/org/stajistics/management/StatsKeyOpenTypeConverterTest.java
/stajistics-core/src/test/java/org/stajistics/management/StatsManagementFactoryTest.java
/stajistics-core/src/test/java/org/stajistics/session/AsynchronousSessionTest.java
=======================================
--- /dev/null
+++
/stajistics-core/src/main/java/org/stajistics/util/FastPutsArrayMap.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,190 @@
+package org.stajistics.util;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Optimised for very small data sets, allowing compact size and fast puts
at the expense of O(n) lookups. This implementation
+ * may store duplicate entries for the same key. TODO: explain more.
+ *
+ * @author The Stajistics Project
+ */
+public class FastPutsArrayMap<K,V> extends AbstractMap<K,V> implements
Serializable {
+
+ private static final int UNKNOWN_SIZE = 0; // Zero so that the size is
unknown after deserialization
+
+ protected final ArrayList<Entry<K,V>> entries;
+ protected transient int size = UNKNOWN_SIZE;
+ protected transient Set<Entry<K,V>> entrySet = null;
+
+ public FastPutsArrayMap() {
+ this(4);
+ }
+
+ public FastPutsArrayMap(final int initialCapacity) {
+ entries = new ArrayList<Entry<K,V>>(initialCapacity);
+ }
+
+ public FastPutsArrayMap(final Map<K, V> map) {
+ this(map.size());
+ putAll(map);
+ }
+
+ public void compact() {
+
+ // Iterate forwards looking for duplicate entries and deleting the
old ones
+ Entry<K,V> e;
+ Entry<K,V> possibleDup;
+ for (final Iterator<Entry<K,V>> itr = entries.iterator();
itr.hasNext(); ) {
+ e = itr.next();
+ possibleDup = getEntry(e.getKey()); // Returns the newest entry
+ if (possibleDup != null && e != possibleDup) {
+ itr.remove();
+ }
+ }
+
+ size = entries.size(); // We now know the size
+
+ // Compact the underlying array
+ entries.trimToSize();
+ }
+
+ @Override
+ public int size() {
+ if (entries.isEmpty()) {
+ return 0;
+ }
+
+ if (size > 0) {
+ return size;
+ }
+
+ compact();
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return entries.isEmpty();
+ }
+
+ @Override
+ public boolean containsValue(final Object aValue) {
+ V value;
+ if (aValue == null) {
+ for (int i = entries.size() - 1; i >= 0; i--) {
+ value = entries.get(i).getValue();
+ if (value == null) {
+ return true;
+ }
+ }
+ } else {
+ for (int i = entries.size() - 1; i >= 0; i--) {
+ value = entries.get(i).getValue();
+ if (aValue.equals(value)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsKey(final Object key) {
+ return getEntry(key) != null;
+ }
+
+ @Override
+ public V get(final Object key) {
+ Entry<K,V> e = getEntry(key);
+ if (e != null) {
+ return e.getValue();
+ }
+ return null;
+ }
+
+ protected Entry<K,V> getEntry(final Object key) {
+ Entry<K,V> e;
+
+ // Search in reverse so we find the most up to date value in the
event of duplicates
+ for (int i = entries.size() - 1; i >= 0; i--) {
+ e = entries.get(i);
+ if (e.getKey().equals(key)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Note: contract broken! Always returns null.
+ */
+ @Override
+ public V put(final K key, final V value) {
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
+ entries.add(new SimpleEntry<K,V>(key, value));
+ size = UNKNOWN_SIZE;
+ return null;
+ }
+
+ @Override
+ public void putAll(final Map<? extends K, ? extends V> map) {
+ for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public V remove(final Object key) {
+ if (key == null) {
+ return null;
+ }
+
+ Entry<K,V> e;
+ V value = null;
+
+ // Search in reverse so we find the most up to date value in the
event of duplicates
+ ListIterator<Entry<K,V>> itr =
entries.listIterator(entries.size());
+ while (itr.hasPrevious()) {
+ e = itr.previous();
+ if (e.getKey().equals(key)) {
+ if (value == null) {
+ value = e.getValue(); // Keep the newest value
+ }
+ itr.remove();
+ size = UNKNOWN_SIZE;
+ // Keep searching for duplicates
+ }
+ }
+
+ return value;
+ }
+
+ @Override
+ public void clear() {
+ entries.clear();
+ size = 0;
+ }
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ if (entrySet == null) {
+ entrySet = new AbstractSet<Entry<K,V>>() {
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ compact();
+ return entries.iterator();
+ }
+
+ @Override
+ public int size() {
+ return FastPutsArrayMap.this.size();
+ }
+ };
+ }
+
+ return entrySet;
+ }
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/main/java/org/stajistics/util/FastPutsLinkedMap.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,173 @@
+package org.stajistics.util;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @author The Stajistics Project
+ */
+public class FastPutsLinkedMap<K,V> extends AbstractMap<K,V> implements
Serializable {
+
+ private final transient LinkedEntry<K,V> header = new
LinkedEntry<K,V>(null, null, null, null);
+ {
+ header.next = header;
+ header.prev = header;
+ }
+
+ private transient int size = 0;
+ private transient Set<Map.Entry<K,V>> entrySet = null;
+
+ public FastPutsLinkedMap() {}
+
+ public FastPutsLinkedMap(final Map<? extends K, ? extends V> map) {
+ putAll(map);
+ }
+
+ public void compact() {
+ int size = 0;
+
+ LinkedEntry<K,V> entry = header.next;
+ LinkedEntry<K,V> newerEntry;
+ LinkedEntry<K,V> next;
+ while (entry != header) {
+ size++;
+ next = entry.next;
+ newerEntry = getEntry(entry.getKey());
+ if (newerEntry != null && newerEntry != entry) {
+ remove(entry);
+ size--;
+ }
+ entry = next;
+ }
+
+ this.size = size;
+ }
+
+ @Override
+ public void clear() {
+ header.next = header.prev = header;
+ size = 0;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return header.prev == header && header.next == header;
+ }
+
+ @Override
+ public int size() {
+ if (isEmpty()) {
+ return 0;
+ }
+
+ if (size > 0) {
+ return size;
+ }
+
+ compact(); // Updates size
+
+ return size;
+ }
+
+
+
+ @Override
+ public V get(final Object key) {
+ LinkedEntry<K,V> entry = getEntry(key);
+ if (entry != null) {
+ return entry.getValue();
+ }
+ return null;
+ }
+
+ @Override
+ public V put(final K key, final V value) {
+ size = 0;
+ LinkedEntry<K,V> newEntry = new LinkedEntry(key, value, header,
header.prev);
+ newEntry.prev.next = newEntry;
+ newEntry.next.prev = newEntry;
+ return null;
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public V remove(final Object key) {
+ LinkedEntry<K,V> entry = getEntry(key);
+ if (entry != null) {
+ size = 0;
+ final V value = entry.getValue();
+ do {
+ remove(entry);
+ entry = getEntry(key);
+ } while (entry != null);
+ return value;
+ }
+ return null;
+ }
+
+ protected LinkedEntry<K,V> getEntry(final Object key) {
+ LinkedEntry<K,V> entry = header.prev;
+ while (entry != header) {
+ if (entry.getKey().equals(key)) {
+ return entry;
+ }
+ entry = entry.prev;
+ }
+
+ return null;
+ }
+
+ private void remove(final LinkedEntry<K,V> e) {
+ if (e == header) {
+ throw new NoSuchElementException();
+ }
+ e.prev.next = e.next;
+ e.next.prev = e.prev;
+ e.next = e.prev = null;
+ }
+
+ @Override
+ public Set<Map.Entry<K,V>> entrySet() {
+ if (entrySet == null) {
+ entrySet = new AbstractSet<Map.Entry<K,V>>() {
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator() {
+ compact();
+
+ final List<Map.Entry<K,V>> list = new
ArrayList<Map.Entry<K,V>>(size());
+ for (LinkedEntry<K,V> entry = header.next; entry !=
null && entry != header; entry = entry.next) {
+ list.add(entry);
+ }
+ return list.iterator();
+ }
+
+ @Override
+ public int size() {
+ return FastPutsLinkedMap.this.size();
+ }
+ };
+ }
+
+ return entrySet;
+ }
+
+ /* NESTED CLASSES */
+
+ public static final class LinkedEntry<K,V> extends SimpleEntry<K,V> {
+
+ private transient LinkedEntry<K,V> next;
+ private transient LinkedEntry<K,V> prev;
+
+ private LinkedEntry(final K key, final V value, final
LinkedEntry<K,V> next, final LinkedEntry<K,V> prev) {
+ super(key, value);
+ this.next = next;
+ this.prev = prev;
+ }
+ }
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/main/java/org/stajistics/util/ServiceLifeCycle.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,64 @@
+package org.stajistics.util;
+
+import java.io.Serializable;
+import java.util.concurrent.Callable;
+
+/**
+ * @author The Stajistics Project
+ */
+public interface ServiceLifeCycle {
+
+ void initialize();
+
+ boolean isRunning();
+
+ void shutdown();
+
+ public static class Support implements Serializable {
+
+ private volatile boolean initalized;
+ private volatile boolean shutdown;
+
+ public Support() {}
+
+ public synchronized void initialize(final Callable<Void>
initCallable) {
+ if (!initalized) {
+ try {
+ if (initCallable != null) {
+ initCallable.call();
+ }
+ initalized = true;
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public synchronized void shutdown(final Callable<Void>
shutdownCallable) {
+ if (!initalized) {
+ throw new IllegalStateException("Attempted shutdown when
service has not yet started");
+ }
+ if (!shutdown) {
+ shutdown = true;
+ try {
+ if (shutdownCallable != null) {
+ shutdownCallable.call();
+ }
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public boolean isRunning() {
+ return initalized && !shutdown;
+ }
+ }
+
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/test/java/org/stajistics/util/AbstractFastPutsMapTestCase.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,159 @@
+package org.stajistics.util;
+
+import org.junit.Test;
+import org.stajistics.AbstractStajisticsTestCase;
+import org.stajistics.StajisticsAssert;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ *
+ * @author The Stajistics Project
+ */
+@SuppressWarnings({"unchecked","rawtypes"})
+public abstract class AbstractFastPutsMapTestCase extends
AbstractStajisticsTestCase {
+
+ protected abstract Map createFastPutsMap();
+
+ protected abstract Map createFastPutsMap(Map map);
+
+ protected abstract void compact(Map map);
+
+ @Test
+ public void testConstruct() {
+ Map m = createFastPutsMap();
+ assertContents(Collections.emptyMap(), m);
+ }
+
+ @Test
+ public void testConstructWithMap() {
+
+ Map m1 = new HashMap();
+ m1.put("one", 1);
+ m1.put("two", 2);
+
+ Map m2 = createFastPutsMap(m1);
+
+ assertContents(m1, m2);
+ }
+
+ @Test
+ public void testSizeWithDuplicates() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("one", -1);
+ m.put("two", 2);
+
+ assertEquals(2, m.size());
+ }
+
+ @Test
+ public void testSizeAfterPuts() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ assertEquals(1, m.size());
+ m.put("two", 2);
+ assertEquals(2, m.size());
+ m.put("three", 3);
+ assertEquals(3, m.size());
+ }
+
+ @Test
+ public void testSizeAfterRemove() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("two", 2);
+ m.remove("one");
+
+ assertEquals(1, m.size());
+ }
+
+ @Test
+ public void testGetWithDuplicates() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("one", -1);
+ m.put("two", 2);
+
+ assertEquals(-1, m.get("one"));
+ assertEquals(2, m.get("two"));
+ }
+
+ @Test
+ public void testCompact() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("one", -1);
+ m.put("two", 2);
+
+ compact(m);
+
+ Map expectedContents = new HashMap();
+ expectedContents.put("one", -1);
+ expectedContents.put("two", 2);
+
+ assertContents(expectedContents, m);
+ }
+
+ @Test
+ public void testRemove() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("one", -1);
+ m.put("two", 2);
+
+ m.remove("one");
+
+ // Ensure duplicates removed
+ int s = m.size();
+ compact(m);
+ assertEquals(s, m.size());
+
+ assertContents(Collections.singletonMap("two", 2), m);
+ }
+
+ @Test
+ public void testClear() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("two", 2);
+
+ m.clear();
+
+ assertContents(Collections.emptyMap(), m);
+ }
+
+ @Test
+ public void testSerializableDeserializable() {
+ Map m = createFastPutsMap();
+ m.put("one", 1);
+ m.put("two", 2);
+ m.put("three", 3);
+
+ StajisticsAssert.assertSerializable(m);
+ }
+
+ private void assertContents(final Map expectedContents, final Map
fastPutsMap) {
+ assertEquals(expectedContents.isEmpty(), fastPutsMap.isEmpty());
+ assertEquals(expectedContents.size(), fastPutsMap.size());
+
+ assertEquals(expectedContents.isEmpty(),
fastPutsMap.entrySet().isEmpty());
+ assertEquals(expectedContents.size(),
fastPutsMap.entrySet().size());
+
+ assertEquals(expectedContents.isEmpty(),
fastPutsMap.keySet().isEmpty());
+ assertEquals(expectedContents.size(), fastPutsMap.keySet().size());
+
+ assertEquals(expectedContents.isEmpty(),
fastPutsMap.values().isEmpty());
+ assertEquals(expectedContents.size(), fastPutsMap.values().size());
+
+ for (Map.Entry e : (Set<Map.Entry>) expectedContents.entrySet()) {
+ assertEquals(e.getValue(), fastPutsMap.get(e.getKey()));
+ }
+ }
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/test/java/org/stajistics/util/FastPutsArrayMapTest.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,24 @@
+package org.stajistics.util;
+
+import java.util.Map;
+
+/**
+ * @author The Stajistics Project
+ */
+public class FastPutsArrayMapTest extends AbstractFastPutsMapTestCase {
+
+ @Override
+ protected Map createFastPutsMap() {
+ return new FastPutsArrayMap();
+ }
+
+ @Override
+ protected Map createFastPutsMap(Map map) {
+ return new FastPutsArrayMap(map);
+ }
+
+ @Override
+ protected void compact(Map map) {
+ ((FastPutsArrayMap)map).compact();
+ }
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/test/java/org/stajistics/util/FastPutsLinkedMapTest.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,24 @@
+package org.stajistics.util;
+
+import java.util.Map;
+
+/**
+ * @author The Stajistics Project
+ */
+public class FastPutsLinkedMapTest extends AbstractFastPutsMapTestCase {
+
+ @Override
+ protected Map createFastPutsMap() {
+ return new FastPutsLinkedMap();
+ }
+
+ @Override
+ protected Map createFastPutsMap(Map map) {
+ return new FastPutsLinkedMap(map);
+ }
+
+ @Override
+ protected void compact(Map map) {
+ ((FastPutsLinkedMap)map).compact();
+ }
+}
=======================================
--- /dev/null
+++
/stajistics-core/src/test/java/org/stajistics/util/ServiceLifeCycleSupportTest.java
Sun Jun 19 21:26:01 2011
@@ -0,0 +1,83 @@
+package org.stajistics.util;
+
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Test;
+import org.stajistics.AbstractStajisticsTestCase;
+
+import java.util.concurrent.Callable;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author The Stajistics Project
+ */
+public class ServiceLifeCycleSupportTest extends
AbstractStajisticsTestCase {
+
+ private ServiceLifeCycle.Support support;
+
+ @Before
+ public void setUp() {
+ support = new ServiceLifeCycle.Support();
+ }
+
+ @Test
+ public void testInitialState() {
+ assertFalse(support.isRunning());
+ }
+
+ @Test
+ public void testInitialize() throws Exception {
+
+ final Callable<Void> mockCallable = mockery.mock(Callable.class);
+
+ mockery.checking(new Expectations() {{
+ one(mockCallable).call();
+ }});
+
+ support.initialize(mockCallable);
+
+ assertTrue(support.isRunning());
+
+ // Try again to ensure no effect
+ support.initialize(mockCallable);
+ }
+
+ @Test
+ public void testInitializeWithNull() {
+ support.initialize(null);
+ assertTrue(support.isRunning());
+ }
+
+ @Test
+ public void testShutdown() throws Exception {
+
+ support.initialize(null);
+
+ final Callable<Void> mockCallable = mockery.mock(Callable.class);
+
+ mockery.checking(new Expectations() {{
+ one(mockCallable).call();
+ }});
+
+ support.shutdown(mockCallable);
+
+ assertFalse(support.isRunning());
+
+ // Try again to ensure no effect
+ support.shutdown(mockCallable);
+ }
+
+ @Test
+ public void testShutdownWithNull() {
+ support.initialize(null);
+ support.shutdown(null);
+ assertFalse(support.isRunning());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testShutdownWithoutInitialize() {
+ support.shutdown(null);
+ }
+}
=======================================
---
/stajistics-core/src/main/java/org/stajistics/util/FastPutsTableMap.java
Sun Jun 19 13:23:35 2011
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.stajistics.util;
-
-import java.util.*;
-
-/**
- * Optimised for very small data sets, allowing compact size and fast puts
at the expense of O(n) lookups. This implementation
- * may store duplicate entries for the same key. TODO: explain more.
- *
- * @author The Stajistics Project
- */
-public class FastPutsTableMap<K,V> extends AbstractMap<K,V> {
-
- private static final int UNKNOWN_SIZE = 0; // Zero so that the size is
unknown after deserialization
-
- protected final ArrayList<Entry<K,V>> entries;
- protected transient int size = UNKNOWN_SIZE;
- protected transient Set<Entry<K,V>> entrySet = null;
-
- public FastPutsTableMap() {
- this(4);
- }
-
- public FastPutsTableMap(final int initialCapacity) {
- entries = new ArrayList<Entry<K,V>>(initialCapacity);
- }
-
- public FastPutsTableMap(final Map<K,V> map) {
- this(map.size());
- putAll(map);
- }
-
- public void compact() {
-
- // Iterate forwards looking for duplicate entries and deleting the
old ones
- Entry<K,V> e;
- Entry<K,V> possibleDup;
- for (final Iterator<Entry<K,V>> itr = entries.iterator();
itr.hasNext(); ) {
- e = itr.next();
- possibleDup = getEntry(e.getKey()); // Returns the newest entry
- if (possibleDup != null && e != possibleDup) {
- itr.remove();
- }
- }
-
- size = entries.size(); // We now know the size
-
- // Compact the underlying array
- entries.trimToSize();
- }
-
- @Override
- public int size() {
- if (entries.isEmpty()) {
- return 0;
- }
-
- if (size > 0) {
- return size;
- }
-
- compact();
- return size;
- }
-
- @Override
- public boolean isEmpty() {
- return entries.isEmpty();
- }
-
- @Override
- public boolean containsValue(final Object aValue) {
- V value;
- if (aValue == null) {
- for (int i = entries.size() - 1; i >= 0; i--) {
- value = entries.get(i).getValue();
- if (value == null) {
- return true;
- }
- }
- } else {
- for (int i = entries.size() - 1; i >= 0; i--) {
- value = entries.get(i).getValue();
- if (aValue.equals(value)) {
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public boolean containsKey(final Object key) {
- return getEntry(key) != null;
- }
-
- @Override
- public V get(final Object key) {
- Entry<K,V> e = getEntry(key);
- if (e != null) {
- return e.getValue();
- }
- return null;
- }
-
- protected Entry<K,V> getEntry(final Object key) {
- Entry<K,V> e;
-
- // Search in reverse so we find the most up to date value in the
event of duplicates
- for (int i = entries.size() - 1; i >= 0; i--) {
- e = entries.get(i);
- if (e.getKey().equals(key)) {
- return e;
- }
- }
- return null;
- }
-
- /**
- * Note: contract broken! Always returns null.
- */
- @Override
- public V put(final K key, final V value) {
- if (key == null) {
- throw new NullPointerException("key");
- }
- entries.add(new SimpleEntry<K,V>(key, value));
- size = UNKNOWN_SIZE;
- return null;
- }
-
- @Override
- public void putAll(final Map<? extends K, ? extends V> map) {
- for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
- put(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- public V remove(final Object key) {
- if (key == null) {
- return null;
- }
-
- Entry<K,V> e;
- V value = null;
-
- // Search in reverse so we find the most up to date value in the
event of duplicates
- ListIterator<Entry<K,V>> itr =
entries.listIterator(entries.size());
- while (itr.hasPrevious()) {
- e = itr.previous();
- if (e.getKey().equals(key)) {
- if (value == null) {
- value = e.getValue(); // Keep the newest value
- }
- itr.remove();
- size = UNKNOWN_SIZE;
- // Keep searching for duplicates
- }
- }
-
- return value;
- }
-
- @Override
- public void clear() {
- entries.clear();
- size = 0;
- }
-
- @Override
- public Set<Entry<K, V>> entrySet() {
- if (entrySet == null) {
- entrySet = new AbstractSet<Entry<K,V>>() {
- @Override
- public Iterator<Entry<K, V>> iterator() {
- compact();
- return entries.iterator();
- }
-
- @Override
- public int size() {
- return FastPutsTableMap.this.size();
- }
- };
- }
-
- return entrySet;
- }
-}
=======================================
---
/stajistics-core/src/test/java/org/stajistics/util/FastPutsTableMapTest.java
Sun Jun 19 13:23:35 2011
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.stajistics.util;
-
-import org.junit.Test;
-import org.stajistics.AbstractStajisticsTestCase;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- *
- *
- * @author The Stajistics Project
- */
-@SuppressWarnings({"unchecked","rawtypes"})
-public class FastPutsTableMapTest extends AbstractStajisticsTestCase {
-
- @Test
- public void testConstruct() {
- FastPutsTableMap m = new FastPutsTableMap();
- assertContents(Collections.emptyMap(), m);
- }
-
- @Test
- public void testConstructWithMap() {
-
- Map m1 = new HashMap();
- m1.put("one", 1);
- m1.put("two", 2);
-
- FastPutsTableMap m2 = new FastPutsTableMap(m1);
-
- assertContents(m1, m2);
- }
-
- @Test
- public void testSizeWithDuplicates() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- m.put("one", -1);
- m.put("two", 2);
-
- assertEquals(2, m.size());
- }
-
- @Test
- public void testSizeAfterPuts() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- assertEquals(1, m.size());
- m.put("two", 2);
- assertEquals(2, m.size());
- m.put("three", 3);
- assertEquals(3, m.size());
- }
-
- @Test
- public void testSizeAfterRemove() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- m.put("two", 2);
- m.remove("one");
-
- assertEquals(1, m.size());
- }
-
- @Test
- public void testGetWithDuplicates() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- m.put("one", -1);
- m.put("two", 2);
-
- assertEquals(-1, m.get("one"));
- assertEquals(2, m.get("two"));
- }
-
- @Test
- public void testCompact() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- m.put("one", -1);
- m.put("two", 2);
-
- assertEquals(3, m.entries.size());
-
- m.compact();
-
- assertEquals(2, m.entries.size());
-
- Map expectedContents = new HashMap();
- expectedContents.put("one", -1);
- expectedContents.put("two", 2);
-
- assertContents(expectedContents, m);
- }
-
- @Test
- public void testRemove() {
- FastPutsTableMap m = new FastPutsTableMap();
- m.put("one", 1);
- m.put("one", -1);
- m.put("two", 2);
-
- m.remove("one");
-
- assertEquals(1, m.entries.size()); // Ensure duplicates removed
- assertContents(Collections.singletonMap("two", 2), m);
- }
-
- private void assertContents(final Map expectedContents, final
FastPutsTableMap fastPutsTableMap) {
- assertEquals(expectedContents.isEmpty(),
fastPutsTableMap.isEmpty());
- assertEquals(expectedContents.size(), fastPutsTableMap.size());
-
- assertEquals(expectedContents.isEmpty(),
fastPutsTableMap.entrySet().isEmpty());
- assertEquals(expectedContents.size(),
fastPutsTableMap.entrySet().size());
-
- assertEquals(expectedContents.isEmpty(),
fastPutsTableMap.keySet().isEmpty());
- assertEquals(expectedContents.size(),
fastPutsTableMap.keySet().size());
-
- assertEquals(expectedContents.isEmpty(),
fastPutsTableMap.values().isEmpty());
- assertEquals(expectedContents.size(),
fastPutsTableMap.values().size());
-
- for (Map.Entry e : (Set<Map.Entry>) expectedContents.entrySet()) {
- assertEquals(e.getValue(), fastPutsTableMap.get(e.getKey()));
- }
- }
-}
=======================================
---
/stajistics-core/src/main/java/org/stajistics/DefaultStatsKeyBuilder.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/main/java/org/stajistics/DefaultStatsKeyBuilder.java
Sun Jun 19 21:26:01 2011
@@ -14,7 +14,7 @@
*/
package org.stajistics;
-import org.stajistics.util.FastPutsTableMap;
+import org.stajistics.util.FastPutsArrayMap;
import java.util.Map;
@@ -79,7 +79,7 @@
if (template.getAttributeCount() > 0) {
Map<String,Object> attrs = template.getAttributes();
if (attrs != null && !attrs.isEmpty()) {
- attributes = new FastPutsTableMap<String,Object>(attrs);
+ attributes = new FastPutsArrayMap<String,Object>(attrs);
}
}
}
@@ -153,7 +153,7 @@
firstAttrName = name;
firstAttrValue = value;
} else {
- attributes = new FastPutsTableMap<String,Object>();
+ attributes = new FastPutsArrayMap<String,Object>();
attributes.put(firstAttrName, firstAttrValue);
firstAttrName = null;
firstAttrValue = null;
=======================================
--- /stajistics-core/src/main/java/org/stajistics/DefaultStatsManager.java
Wed Jun 15 16:30:39 2011
+++ /stajistics-core/src/main/java/org/stajistics/DefaultStatsManager.java
Sun Jun 19 21:26:01 2011
@@ -28,6 +28,9 @@
import org.stajistics.tracker.DefaultTrackerLocator;
import org.stajistics.tracker.NullTrackerLocator;
import org.stajistics.tracker.TrackerLocator;
+import org.stajistics.util.ServiceLifeCycle;
+
+import java.util.concurrent.Callable;
/**
* The default implementation of {@link StatsManager}. Clients typically
do not
@@ -48,6 +51,8 @@
protected final StatsConfigBuilderFactory configBuilderFactory;
protected final TaskService taskService;
+ private final ServiceLifeCycle.Support lifeCycleSupport = new
Support();
+
/**
* Construct a DefaultStatsManager using the given set of managers.
*
@@ -107,25 +112,48 @@
@Override
public void initialize() {
- StatsManagerRegistry.registerStatsManager(this);
-
- eventManager.fireEvent(EventType.TASK_SERVICE_INITIALIZED, null,
taskService);
- eventManager.fireEvent(EventType.CONFIG_MANAGER_INITIALIZED, null,
configManager);
- eventManager.fireEvent(EventType.SESSION_MANAGER_INITIALIZED,
null, sessionManager);
- eventManager.fireEvent(EventType.STATS_MANAGER_INITIALIZED, null,
this);
+ lifeCycleSupport.initialize(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
+
StatsManagerRegistry.registerStatsManager(DefaultStatsManager.this);
+
+ eventManager.initialize();
+ taskService.initialize();
+ configManager.initialize();
+ sessionManager.initialize();
+
+
eventManager.fireEvent(EventType.STATS_MANAGER_INITIALIZED, null,
DefaultStatsManager.this);
+
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public boolean isRunning() {
+ return lifeCycleSupport.isRunning();
}
@Override
public void shutdown() {
- eventManager.fireEvent(EventType.STATS_MANAGER_SHUTTING_DOWN,
null, this);
-
- setEnabled(false);
-
- sessionManager.shutdown();
- configManager.shutdown();
- taskService.shutdown();
-
- StatsManagerRegistry.removeStatsManager(this);
+ lifeCycleSupport.shutdown(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.STATS_MANAGER_SHUTTING_DOWN, null,
DefaultStatsManager.this);
+
+ setEnabled(false);
+
+ sessionManager.shutdown();
+ configManager.shutdown();
+ taskService.shutdown();
+ eventManager.shutdown();
+
+
StatsManagerRegistry.removeStatsManager(DefaultStatsManager.this);
+
+ return null;
+ }
+ });
}
@Override
=======================================
--- /stajistics-core/src/main/java/org/stajistics/StatsManager.java Wed Jun
15 16:30:39 2011
+++ /stajistics-core/src/main/java/org/stajistics/StatsManager.java Sun Jun
19 21:26:01 2011
@@ -20,6 +20,7 @@
import org.stajistics.session.StatsSessionManager;
import org.stajistics.task.TaskService;
import org.stajistics.tracker.TrackerLocator;
+import org.stajistics.util.ServiceLifeCycle;
import java.io.Serializable;
@@ -29,9 +30,13 @@
*
* @author The Stajistics Project
*/
-public interface StatsManager extends Serializable {
-
-
+public interface StatsManager extends Serializable,ServiceLifeCycle {
+
+ /**
+ * Get the unique namespace identifier for this <tt>StatsManager</tt>.
+ *
+ * @return The namespace, never <tt>null</tt>.
+ */
String getNamespace();
/**
@@ -97,15 +102,21 @@
*/
void setEnabled(boolean enabled);
-
+ /**
+ * Initialize sub-components and fire initialization events. Clients
do not need to call this method.
+ * Called internally as part of instance creation by a {@link
org.stajistics.bootstrap.StatsManagerFactory}.
+ * After this method is called for the first time, subsequent calls
will have no effect.
+ */
+ @Override
void initialize();
-
+
/**
* Firstly, set the manager state to disabled, then proceed to clean
up any resources
* associated with statistics collection. A future call to {@link
#setEnabled(boolean)} passing
* <tt>true</tt>, followed by any request to collect statistics will
reinitialize any
* necessary resources.
*/
+ @Override
void shutdown();
}
=======================================
--- /stajistics-core/src/main/java/org/stajistics/StatsManagerRegistry.java
Wed Jun 15 16:30:39 2011
+++ /stajistics-core/src/main/java/org/stajistics/StatsManagerRegistry.java
Sun Jun 19 21:26:01 2011
@@ -27,7 +27,14 @@
}
public static void removeStatsManager(final StatsManager manager) {
- registry.remove(manager.getNamespace());
+ removeStatsManager(manager.getNamespace());
+ }
+
+ public static void removeStatsManager(final String namespace) {
+ if (namespace == null) {
+ throw new NullPointerException("namespace");
+ }
+ registry.remove(namespace);
}
public static StatsManager getStatsManager(final String namespace) {
=======================================
---
/stajistics-core/src/main/java/org/stajistics/configuration/DefaultStatsConfigManager.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/configuration/DefaultStatsConfigManager.java
Sun Jun 19 21:26:01 2011
@@ -6,9 +6,11 @@
import org.stajistics.session.DefaultSessionFactory;
import org.stajistics.session.recorder.DefaultDataRecorderFactory;
import org.stajistics.tracker.span.TimeDurationTracker;
+import org.stajistics.util.ServiceLifeCycle;
import java.io.Serializable;
import java.util.*;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
@@ -39,6 +41,8 @@
private final EventManager eventManager;
private final StatsKeyFactory keyFactory;
+ private final ServiceLifeCycle.Support lifeCycleSupport = new
Support();
+
/**
* Create a new DefaultStatsConfigManager instance containing no
initial configurations.
*
@@ -122,6 +126,34 @@
return new ConcurrentHashMap<String,KeyEntry>(initialCapacity,
loadFactor, concurrencyLevel);
}
+
+ @Override
+ public void initialize() {
+ lifeCycleSupport.initialize(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.CONFIG_MANAGER_INITIALIZED, null,
DefaultStatsConfigManager.this);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public boolean isRunning() {
+ return lifeCycleSupport.isRunning();
+ }
+
+ @Override
+ public synchronized void shutdown() {
+ lifeCycleSupport.shutdown(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.CONFIG_MANAGER_SHUTTING_DOWN, null, this);
+ clearConfigs();
+ return null;
+ }
+ });
+ }
@Override
public StatsConfig getRootConfig() {
@@ -221,12 +253,6 @@
public void clearConfigs() {
destroyEntry(rootKeyEntry);
}
-
- @Override
- public void shutdown() {
- eventManager.fireEvent(EventType.CONFIG_MANAGER_SHUTTING_DOWN,
null, this);
- clearConfigs();
- }
/* PRIVATE METHODS */
=======================================
---
/stajistics-core/src/main/java/org/stajistics/configuration/StatsConfigManager.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/configuration/StatsConfigManager.java
Sun Jun 19 21:26:01 2011
@@ -16,6 +16,7 @@
import org.stajistics.StatsKey;
import org.stajistics.StatsKeyMatcher;
+import org.stajistics.util.ServiceLifeCycle;
import java.io.Serializable;
import java.util.Map;
@@ -40,7 +41,7 @@
*
* @author The Stajistics Project
*/
-public interface StatsConfigManager extends Serializable {
+public interface StatsConfigManager extends Serializable,ServiceLifeCycle {
/**
* Get the root configuration.
@@ -145,7 +146,5 @@
* Delete all known configurations except for the root configuration.
*/
void clearConfigs();
-
-
- void shutdown();
-}
+
+}
=======================================
--- /stajistics-core/src/main/java/org/stajistics/event/EventManager.java
Wed Jun 2 21:28:40 2010
+++ /stajistics-core/src/main/java/org/stajistics/event/EventManager.java
Sun Jun 19 21:26:01 2011
@@ -16,6 +16,7 @@
import org.stajistics.StatsKey;
import org.stajistics.StatsKeyMatcher;
+import org.stajistics.util.ServiceLifeCycle;
import java.io.Serializable;
import java.util.Collection;
@@ -27,7 +28,7 @@
*
* @author The Stajistics Project
*/
-public interface EventManager extends Serializable {
+public interface EventManager extends Serializable,ServiceLifeCycle {
Collection<EventHandler> getGlobalEventHandlers();
=======================================
---
/stajistics-core/src/main/java/org/stajistics/event/SynchronousEventManager.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/event/SynchronousEventManager.java
Sun Jun 19 21:26:01 2011
@@ -39,9 +39,26 @@
private final ConcurrentMap<StatsKey,List<EventHandler>>
sessionEventHandlers =
new ConcurrentHashMap<StatsKey,List<EventHandler>>();
+ private final Support lifeCycleSupport = new Support();
+
protected List<EventHandler> createEventHandlerList() {
return new CopyOnWriteArrayList<EventHandler>();
}
+
+ @Override
+ public void initialize() {
+ lifeCycleSupport.initialize(null);
+ }
+
+ @Override
+ public boolean isRunning() {
+ return lifeCycleSupport.isRunning();
+ }
+
+ @Override
+ public void shutdown() {
+ lifeCycleSupport.shutdown(null);
+ }
@Override
public Collection<EventHandler> getGlobalEventHandlers() {
=======================================
---
/stajistics-core/src/main/java/org/stajistics/management/StatsKeyOpenTypeConverter.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/main/java/org/stajistics/management/StatsKeyOpenTypeConverter.java
Sun Jun 19 21:26:01 2011
@@ -23,6 +23,7 @@
private static final String ATTR_NAME_VALUE_PAIR_DELIMITER = "&";
private static final String ATTR_NAME_VALUE_DELIMITER = "=";
+ private static final String ATTR_PREFIX_ESACPE = "\\";
private static final String ATTR_PREFIX_BOOLEAN = "b_";
private static final String ATTR_PREFIX_INTEGER = "i_";
private static final String ATTR_PREFIX_LONG = "l_";
@@ -62,7 +63,9 @@
String strValue = value.toString();
- if (valueClass == Boolean.class) {
+ if (valueClass == String.class) {
+ strValue = escapeAttrTypePrefix(strValue);
+ } else if (valueClass == Boolean.class) {
Boolean b = (Boolean) value;
strValue = ATTR_PREFIX_BOOLEAN + (b ? 't' : 'f');
} else if (valueClass == Integer.class) {
@@ -120,7 +123,7 @@
}
final String name =
unescapeAttrNameValueDelimiter(nameValueParts[0]);
- final String strValue =
unescapeAttrNameValueDelimiter(nameValueParts[1]);
+ String strValue =
unescapeAttrNameValueDelimiter(nameValueParts[1]);
if (strValue.startsWith(ATTR_PREFIX_BOOLEAN)) {
Boolean value =
strValue.substring(ATTR_PREFIX_BOOLEAN.length()).equals("t");
@@ -135,6 +138,7 @@
builder.withAttribute(name, value);
} else {
+ strValue = unescapeAttrTypePrefix(strValue);
builder.withAttribute(name, strValue);
}
}
@@ -142,6 +146,25 @@
return builder.newKey();
}
+
+ private String escapeAttrTypePrefix(String attrValue) {
+ if (attrValue.startsWith(ATTR_PREFIX_BOOLEAN) ||
+ attrValue.startsWith(ATTR_PREFIX_INTEGER) ||
+ attrValue.startsWith(ATTR_PREFIX_LONG)) {
+ return ATTR_PREFIX_ESACPE + attrValue;
+ }
+ return attrValue;
+ }
+
+ private String unescapeAttrTypePrefix(String attrValue) {
+ if (attrValue.startsWith(ATTR_PREFIX_ESACPE) &&
+ !attrValue.startsWith(ATTR_PREFIX_ESACPE +
ATTR_PREFIX_ESACPE)) {
+ String v = attrValue.substring(ATTR_PREFIX_ESACPE.length());
+ return v;
+ }
+
+ return attrValue;
+ }
private String escapePart(String part) {
Matcher m = KEY_ATTRS_SPLITTER.matcher(part);
=======================================
---
/stajistics-core/src/main/java/org/stajistics/management/beans/DefaultStatsManagerMXBean.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/management/beans/DefaultStatsManagerMXBean.java
Sun Jun 19 21:26:01 2011
@@ -29,6 +29,31 @@
}
this.statsManager = statsManager;
}
+
+ @Override
+ public String getNamespace() {
+ return statsManager.getNamespace();
+ }
+
+ @Override
+ public String getSessionManagerImpl() {
+ return statsManager.getSessionManager().getClass().getName();
+ }
+
+ @Override
+ public String getConfigManagerImpl() {
+ return statsManager.getConfigManager().getClass().getName();
+ }
+
+ @Override
+ public String getEventManagerImpl() {
+ return statsManager.getEventManager().getClass().getName();
+ }
+
+ @Override
+ public String getTaskServiceImpl() {
+ return statsManager.getTaskService().getClass().getName();
+ }
@Override
public boolean getEnabled() {
=======================================
---
/stajistics-core/src/main/java/org/stajistics/management/beans/StatsManagerMXBean.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/management/beans/StatsManagerMXBean.java
Sun Jun 19 21:26:01 2011
@@ -8,6 +8,16 @@
@MXBean
public interface StatsManagerMXBean {
+ String getNamespace();
+
+ String getSessionManagerImpl();
+
+ String getConfigManagerImpl();
+
+ String getEventManagerImpl();
+
+ String getTaskServiceImpl();
+
boolean getEnabled();
void setEnabled(boolean enabled);
=======================================
---
/stajistics-core/src/main/java/org/stajistics/session/AbstractStatsSession.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/main/java/org/stajistics/session/AbstractStatsSession.java
Sun Jun 19 21:26:01 2011
@@ -22,7 +22,7 @@
import org.stajistics.data.DefaultDataSet;
import org.stajistics.event.EventManager;
import org.stajistics.session.recorder.DataRecorder;
-import org.stajistics.util.FastPutsTableMap;
+import org.stajistics.util.FastPutsLinkedMap;
import org.stajistics.util.Misc;
import java.text.DecimalFormat;
@@ -166,15 +166,12 @@
* @return
*/
protected DataSet createDataSet(final boolean drainedSession) {
-
- final int estimatedSize = 10 + (dataRecorders.length * 4);
-
- DataSet dataSet = new DefaultDataSet(System.currentTimeMillis(),
+ DataSet dataSet = new DefaultDataSet(System.currentTimeMillis(),
drainedSession,
- new
FastPutsTableMap<String,Object>(estimatedSize)) {
+ new
FastPutsLinkedMap<String,Object>()) {
@Override
protected Map<String, Object> createMetaDataMap() {
- return new FastPutsTableMap<String,Object>(8);
+ return new FastPutsLinkedMap<String,Object>();
}
};
=======================================
---
/stajistics-core/src/main/java/org/stajistics/session/DefaultSessionManager.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/main/java/org/stajistics/session/DefaultSessionManager.java
Sun Jun 19 21:26:01 2011
@@ -29,6 +29,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -54,8 +55,10 @@
protected final StatsConfigManager configManager;
protected final EventManager eventManager;
+ private final Support lifeCycleSupport = new Support();
+
public DefaultSessionManager(final StatsConfigManager configManager,
- final EventManager eventManager) {
+ final EventManager eventManager) {
if (configManager == null) {
throw new NullPointerException("configManager");
}
@@ -66,6 +69,34 @@
this.configManager = configManager;
this.eventManager = eventManager;
}
+
+ @Override
+ public void initialize() {
+ lifeCycleSupport.initialize(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.SESSION_MANAGER_INITIALIZED, null,
DefaultSessionManager.this);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public boolean isRunning() {
+ return lifeCycleSupport.isRunning();
+ }
+
+ @Override
+ public void shutdown() {
+ lifeCycleSupport.shutdown(new Callable<Void>() {;
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.SESSION_MANAGER_SHUTTING_DOWN, null,
DefaultSessionManager.this);
+ clear();
+ return null;
+ }
+ });
+ }
/**
* A factory method for creating the ConcurrentMap that will store
{@link StatsSession}s.
@@ -187,11 +218,5 @@
session.clear();
}
}
-
- @Override
- public void shutdown() {
- eventManager.fireEvent(EventType.SESSION_MANAGER_SHUTTING_DOWN,
null, this);
- clear();
- }
}
=======================================
---
/stajistics-core/src/main/java/org/stajistics/session/StatsSessionManager.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/main/java/org/stajistics/session/StatsSessionManager.java
Sun Jun 19 21:26:01 2011
@@ -16,6 +16,7 @@
import org.stajistics.StatsKey;
import org.stajistics.StatsKeyMatcher;
+import org.stajistics.util.ServiceLifeCycle;
import java.io.Serializable;
import java.util.Collection;
@@ -26,7 +27,7 @@
*
* @author The Stajistics Project
*/
-public interface StatsSessionManager extends Serializable {
+public interface StatsSessionManager extends Serializable,ServiceLifeCycle
{
/**
* Get the total number of {@link StatsSession} instance being managed.
@@ -96,7 +97,7 @@
/**
* Remove the given <tt>session</tt> instance from this manager.
*
- * @param statsSession The {@link StatsSession} instance to remove.
+ * @param session The {@link StatsSession} instance to remove.
* @return <tt>true</tt> if <tt>session</tt> was found and removed,
<tt>false</tt> if not found.
*/
boolean remove(StatsSession session);
@@ -111,5 +112,4 @@
*/
void clearAllSessions();
- void shutdown();
-}
+}
=======================================
---
/stajistics-core/src/main/java/org/stajistics/task/DebugTaskService.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/task/DebugTaskService.java
Sun Jun 19 21:26:01 2011
@@ -14,14 +14,9 @@
*/
package org.stajistics.task;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
import org.stajistics.event.EventManager;
-import org.stajistics.event.EventType;
+
+import java.util.concurrent.*;
/**
* @author The Stajistics Project
@@ -37,7 +32,18 @@
this.eventManager = eventManager;
}
-
+
+ @Override
+ public void initialize() {}
+
+ @Override
+ public boolean isRunning() {
+ return true;
+ }
+
+ @Override
+ public void shutdown() {}
+
@Override
public void execute(final Class<?> source,
final Runnable task) {
@@ -56,10 +62,7 @@
}
}
- @Override
- public void shutdown() {
- eventManager.fireEvent(EventType.TASK_SERVICE_SHUTTING_DOWN, null,
this);
- }
+
private final static class FinishedFuture<T> implements Future<T> {
=======================================
--- /stajistics-core/src/main/java/org/stajistics/task/TaskService.java Wed
Mar 10 21:05:16 2010
+++ /stajistics-core/src/main/java/org/stajistics/task/TaskService.java Sun
Jun 19 21:26:01 2011
@@ -14,6 +14,8 @@
*/
package org.stajistics.task;
+import org.stajistics.util.ServiceLifeCycle;
+
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -23,12 +25,10 @@
*
* @author The Stajistics Project
*/
-public interface TaskService extends Serializable {
+public interface TaskService extends Serializable,ServiceLifeCycle {
void execute(Class<?> source, Runnable task);
<T> Future<T> submit(Class<?> source, Callable<T> task);
- void shutdown();
-
-}
+}
=======================================
---
/stajistics-core/src/main/java/org/stajistics/task/ThreadPoolTaskService.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/main/java/org/stajistics/task/ThreadPoolTaskService.java
Sun Jun 19 21:26:01 2011
@@ -14,19 +14,12 @@
*/
package org.stajistics.task;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
import org.stajistics.StatsProperties;
import org.stajistics.event.EventManager;
import org.stajistics.event.EventType;
+import java.util.concurrent.*;
+
/**
* @author The Stajistics Project
*/
@@ -48,6 +41,8 @@
// TODO: persist and restore upon de/serialization
private transient final ThreadPoolExecutor executor;
+ private final Support lifeCycleSupport = new Support();
+
public ThreadPoolTaskService(final EventManager eventManager) {
if (eventManager == null) {
throw new NullPointerException("null eventManager");
@@ -76,8 +71,6 @@
keepAliveTimeUnit,
createWorkQueue(),
createThreadFactory());
-
- executor.prestartCoreThread();
}
public ThreadPoolTaskService(final EventManager eventManager, final
ThreadPoolExecutor executor) {
@@ -108,6 +101,35 @@
protected ThreadFactory createThreadFactory() {
return new TaskServiceThreadFactory();
}
+
+ @Override
+ public void initialize() {
+ lifeCycleSupport.initialize(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ executor.prestartCoreThread();
+ eventManager.fireEvent(EventType.TASK_SERVICE_INITIALIZED,
null, this);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public boolean isRunning() {
+ return lifeCycleSupport.isRunning();
+ }
+
+ @Override
+ public void shutdown() {
+ lifeCycleSupport.shutdown(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+
eventManager.fireEvent(EventType.TASK_SERVICE_SHUTTING_DOWN, null, this);
+ executor.shutdown();
+ return null;
+ }
+ });
+ }
@Override
public <T> Future<T> submit(final Class<?> source,
@@ -119,10 +141,4 @@
public void execute(Class<?> source, Runnable task) {
executor.execute(task);
}
-
- @Override
- public void shutdown() {
- eventManager.fireEvent(EventType.TASK_SERVICE_SHUTTING_DOWN, null,
this);
- executor.shutdown();
- }
-}
+}
=======================================
---
/stajistics-core/src/test/java/org/stajistics/DefaultStatsManagerTest.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/test/java/org/stajistics/DefaultStatsManagerTest.java
Sun Jun 19 21:26:01 2011
@@ -14,22 +14,19 @@
*/
package org.stajistics;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
+import org.jmock.Expectations;
import org.junit.Test;
import org.stajistics.bootstrap.DefaultStatsManagerFactory;
import org.stajistics.configuration.StatsConfigBuilderFactory;
import org.stajistics.configuration.StatsConfigManager;
import org.stajistics.event.EventManager;
+import org.stajistics.event.EventType;
import org.stajistics.session.StatsSessionManager;
import org.stajistics.task.TaskService;
import org.stajistics.tracker.TrackerLocator;
+import static org.junit.Assert.*;
+
/**
*
*
@@ -200,6 +197,93 @@
assertEquals("taskService", npe.getMessage());
}
}
+
+ private void expectInitialize(final StatsManager statsManager,
+ final EventManager eventManager,
+ final TaskService taskService,
+ final StatsConfigManager configManager,
+ final StatsSessionManager
sessionManager) {
+ mockery.checking(new Expectations() {{
+ one(eventManager).initialize();
+ one(taskService).initialize();
+ one(configManager).initialize();
+ one(sessionManager).initialize();
+
+
one(eventManager).fireEvent(EventType.STATS_MANAGER_INITIALIZED, null,
statsManager);
+ }});
+ }
+
+ @Test
+ public void testInitialize() {
+ final StatsConfigManager configManager =
mockery.mock(StatsConfigManager.class);
+ final StatsSessionManager sessionManager =
mockery.mock(StatsSessionManager.class);
+ final EventManager eventManager = mockery.mock(EventManager.class);
+ final TrackerLocator trackerLocator =
mockery.mock(TrackerLocator.class);
+ final StatsKeyFactory keyFactory =
mockery.mock(StatsKeyFactory.class);
+ final StatsConfigBuilderFactory configBuilderFactory =
mockery.mock(StatsConfigBuilderFactory.class);
+ final TaskService taskService = mockery.mock(TaskService.class);
+
+ final StatsManager mgr = new DefaultStatsManager("ns",
+ configManager,
+ sessionManager,
+ eventManager,
+ trackerLocator,
+ keyFactory,
+
configBuilderFactory,
+ taskService);
+
+ expectInitialize(mgr, eventManager, taskService, configManager,
sessionManager);
+
+ assertEquals(null, StatsManagerRegistry.getStatsManager("ns"));
+
+ try {
+ mgr.initialize();
+
+ assertEquals(mgr, StatsManagerRegistry.getStatsManager("ns"));
+
+ // Try again to test no effect
+ mgr.initialize();
+ } finally {
+ StatsManagerRegistry.removeStatsManager("ns");
+ }
+ }
+
+ @Test
+ public void testShutdown() {
+
+ final StatsConfigManager configManager =
mockery.mock(StatsConfigManager.class);
+ final StatsSessionManager sessionManager =
mockery.mock(StatsSessionManager.class);
+ final EventManager eventManager = mockery.mock(EventManager.class);
+ final TrackerLocator trackerLocator =
mockery.mock(TrackerLocator.class);
+ final StatsKeyFactory keyFactory =
mockery.mock(StatsKeyFactory.class);
+ final StatsConfigBuilderFactory configBuilderFactory =
mockery.mock(StatsConfigBuilderFactory.class);
+ final TaskService taskService = mockery.mock(TaskService.class);
+
+ final StatsManager mgr = new DefaultStatsManager("ns",
+ configManager,
+ sessionManager,
+ eventManager,
+ trackerLocator,
+ keyFactory,
+
configBuilderFactory,
+ taskService);
+
+ expectInitialize(mgr, eventManager, taskService, configManager,
sessionManager);
+ mgr.initialize();
+
+ mockery.checking(new Expectations() {{
+
one(eventManager).fireEvent(EventType.STATS_MANAGER_SHUTTING_DOWN, null,
mgr);
+
+ one(sessionManager).shutdown();
+ one(configManager).shutdown();
+ one(taskService).shutdown();
+ one(eventManager).shutdown();
+ }});
+
+ mgr.shutdown();
+
+ assertFalse(mgr.isEnabled());
+ }
@Test
public void testGetConfigManager() {
=======================================
--- /stajistics-core/src/test/java/org/stajistics/StatsTest.java Wed Jun 15
16:30:39 2011
+++ /stajistics-core/src/test/java/org/stajistics/StatsTest.java Sun Jun 19
21:26:01 2011
@@ -393,6 +393,11 @@
@Override
public void initialize() {}
+
+ @Override
+ public boolean isRunning() {
+ return true;
+ }
@Override
public void shutdown() {}
=======================================
---
/stajistics-core/src/test/java/org/stajistics/management/StatsKeyOpenTypeConverterTest.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/test/java/org/stajistics/management/StatsKeyOpenTypeConverterTest.java
Sun Jun 19 21:26:01 2011
@@ -126,6 +126,33 @@
assertConvertUnconvertSame(key);
}
+
+ @Test
+ public void
testConvertKeyWithStringAttrValueHavingBooleanAttrTypeEscape() {
+ StatsKey key = new DefaultStatsKey("test", null,
Collections.<String,Object>singletonMap("name", "b_not_really_a_boolean"));
+ String openKey = converter.toOpenType(key);
+ assertEquals("test:name=\\b_not_really_a_boolean", openKey);
+
+ assertConvertUnconvertSame(key);
+ }
+
+ @Test
+ public void
testConvertKeyWithStringAttrValueHavingIntegerAttrTypeEscape() {
+ StatsKey key = new DefaultStatsKey("test", null,
Collections.<String,Object>singletonMap("name", "i_not_really_an_integer"));
+ String openKey = converter.toOpenType(key);
+ assertEquals("test:name=\\i_not_really_an_integer", openKey);
+
+ assertConvertUnconvertSame(key);
+ }
+
+ @Test
+ public void
testConvertKeyWithStringAttrValueHavingLongAttrTypeEscape() {
+ StatsKey key = new DefaultStatsKey("test", null,
Collections.<String,Object>singletonMap("name", "l_not_really_a_long"));
+ String openKey = converter.toOpenType(key);
+ assertEquals("test:name=\\l_not_really_a_long", openKey);
+
+ assertConvertUnconvertSame(key);
+ }
private void assertConvertUnconvertSame(final StatsKey key) {
String openTypeKey = converter.toOpenType(key);
=======================================
---
/stajistics-core/src/test/java/org/stajistics/management/StatsManagementFactoryTest.java
Sun Jun 19 13:23:35 2011
+++
/stajistics-core/src/test/java/org/stajistics/management/StatsManagementFactoryTest.java
Sun Jun 19 21:26:01 2011
@@ -2,19 +2,23 @@
import org.junit.Before;
import org.junit.Test;
+import org.stajistics.DefaultStatsKeyFactory;
import org.stajistics.DefaultStatsManager;
import org.stajistics.StatsKey;
import org.stajistics.StatsManager;
-import org.stajistics.management.beans.DefaultStatsManagerMXBean;
-import org.stajistics.management.beans.DefaultStatsSessionManagerMXBean;
-import org.stajistics.management.beans.StatsManagerMXBean;
-import org.stajistics.management.beans.StatsSessionManagerMXBean;
+import org.stajistics.configuration.DefaultStatsConfigManager;
+import org.stajistics.configuration.StatsConfigManager;
+import org.stajistics.event.EventManager;
+import org.stajistics.event.SynchronousEventManager;
+import org.stajistics.management.beans.*;
+import org.stajistics.session.DefaultSessionManager;
import org.stajistics.session.StatsSessionManager;
import javax.management.ObjectName;
import java.util.Set;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
*
@@ -42,7 +46,6 @@
Set<String> namespaces = factory.getNamespaces();
assertNotNull(namespaces);
- assertFalse(namespaces.isEmpty());
assertEquals(1, namespaces.size());
assertEquals("test", namespaces.iterator().next());
}
@@ -55,10 +58,44 @@
Set<ObjectName> objectNames = factory.getStatsManagerObjectNames();
assertNotNull(objectNames);
- assertFalse(objectNames.isEmpty());
assertEquals(1, objectNames.size());
assertEquals(objectName, objectNames.iterator().next());
}
+
+ @Test
+ public void testGetSessionManagerObjectNames() throws Exception {
+ ObjectName objectName =
StatsMXBeanUtil.getSessionManagerObjectName("test");
+ registerSessionManagerMXBean(objectName, null);
+
+ Set<ObjectName> objectNames =
factory.getSessionManagerObjectNames();
+
+ assertNotNull(objectNames);
+ assertEquals(1, objectNames.size());
+ assertEquals(objectName, objectNames.iterator().next());
+ }
+
+ @Test
+ public void testGetConfigManagerObjectNames() throws Exception {
+ ObjectName objectName =
StatsMXBeanUtil.getConfigManagerObjectName("test");
+ registerConfigManagerMXBean(objectName, null);
+
+ Set<ObjectName> objectNames =
factory.getConfigManagerObjectNames();
+
+ assertNotNull(objectNames);
+ assertEquals(1, objectNames.size());
+ assertEquals(objectName, objectNames.iterator().next());
+ }
+
+ @Test
+ public void testGetStatsManagerMXBean() throws Exception {
+ ObjectName objectName =
StatsMXBeanUtil.getStatsManagerObjectName("test");
+ registerStatsManagerMXBean(objectName);
+
+ StatsManagerMXBean mBean = factory.getStatsManagerMXBean("test");
+
+ assertNotNull(mBean);
+ assertEquals("test", mBean.getNamespace());
+ }
@Test
public void testGetKeys() throws Exception {
@@ -72,20 +109,42 @@
Set<StatsKey> keys = factory.getKeys("test");
assertNotNull(keys);
- assertFalse(keys.isEmpty());
assertEquals(1, keys.size());
assertEquals(key, keys.iterator().next());
}
private StatsManager registerStatsManagerMXBean(ObjectName objectName)
throws Exception {
- StatsManager statsManager = new
DefaultStatsManager.Builder().newManager();
+ String namespace =
objectName.getKeyProperty(StatsMXBeanUtil.OBJECT_NAME_ATTR_NAMESPACE);
+ StatsManager statsManager = new
DefaultStatsManager.Builder().withNamespace(namespace).newManager();
StatsManagerMXBean mBean = new
DefaultStatsManagerMXBean(statsManager);
mBean = registerMBean(mBean, objectName, StatsManagerMXBean.class);
return statsManager;
}
- private void registerSessionManagerMXBean(ObjectName objectName,
StatsSessionManager sessionManager) throws Exception {
+ private StatsSessionManager registerSessionManagerMXBean(ObjectName
objectName, StatsSessionManager sessionManager) throws Exception {
+
+ if (sessionManager == null) {
+ EventManager eventManager = new SynchronousEventManager();
+ StatsConfigManager configManager = new
DefaultStatsConfigManager(eventManager, new DefaultStatsKeyFactory());
+ sessionManager = new DefaultSessionManager(configManager,
eventManager);
+ }
+
StatsSessionManagerMXBean mBean = new
DefaultStatsSessionManagerMXBean(sessionManager);
mBean = registerMBean(mBean, objectName,
StatsSessionManagerMXBean.class);
+
+ return sessionManager;
+ }
+
+ private StatsConfigManager registerConfigManagerMXBean(ObjectName
objectName, StatsConfigManager configManager) throws Exception {
+
+ if (configManager == null) {
+ EventManager eventManager = new SynchronousEventManager();
+ configManager = new DefaultStatsConfigManager(eventManager,
new DefaultStatsKeyFactory());
+ }
+
+ StatsConfigManagerMXBean mBean = new
DefaultStatsConfigManagerMXBean(configManager);
+ mBean = registerMBean(mBean, objectName,
StatsConfigManagerMXBean.class);
+
+ return configManager;
}
}
=======================================
---
/stajistics-core/src/test/java/org/stajistics/session/AsynchronousSessionTest.java
Wed Jun 15 16:30:39 2011
+++
/stajistics-core/src/test/java/org/stajistics/session/AsynchronousSessionTest.java
Sun Jun 19 21:26:01 2011
@@ -14,17 +14,17 @@
*/
package org.stajistics.session;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
-
import org.junit.Test;
import org.stajistics.session.recorder.DataRecorder;
import org.stajistics.task.DebugTaskService;
import org.stajistics.task.TaskService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
/**
* @author The Stajistics Project
*/
@@ -110,6 +110,16 @@
public void execute(Class<?> source, Runnable task) {
throw new RuntimeException();
}
+
+
+ @Override
+ public void initialize() {
+ }
+
+ @Override
+ public boolean isRunning() {
+ return false;
+ }
@Override
public void shutdown() {
==============================================================================
Revision: 2f12e45d8925
Author: troy.k...@gmail.com
Date: Sun Jun 19 21:52:08 2011
Log: Created new io package containing filter streams for collecting
io statistics.
http://code.google.com/p/stajistics/source/detail?r=2f12e45d8925
Added:
/stajistics-core/src/main/java/org/stajistics/io/StatsInputStream.java
/stajistics-core/src/main/java/org/stajistics/io/StatsOutputStream.java
/stajistics-core/src/main/java/org/stajistics/io/StatsReader.java
/stajistics-core/src/main/java/org/stajistics/io/StatsWriter.java
=======================================
--- /dev/null
+++ /stajistics-core/src/main/java/org/stajistics/io/StatsInputStream.java
Sun Jun 19 21:52:08 2011
@@ -0,0 +1,98 @@
+package org.stajistics.io;
+
+import org.stajistics.Stats;
+import org.stajistics.StatsKey;
+import org.stajistics.StatsManager;
+import org.stajistics.tracker.manual.ManualTracker;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author The Stajistics Project
+ */
+public class StatsInputStream extends FilterInputStream {
+
+ private final StatsManager statsManager;
+ private final StatsKey key;
+
+ private final ManualTracker tracker;
+
+ protected StatsInputStream(final StatsManager statsManager,
+ final StatsKey key,
+ final InputStream in) {
+ super(in);
+
+ if (statsManager == null) {
+ this.statsManager = Stats.getManager();
+ } else {
+ this.statsManager = statsManager;
+ }
+
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
+
+ this.key = key;
+
+ tracker = statsManager.getTrackerLocator().getManualTracker(key);
+ }
+
+ @Override
+ public int read() throws IOException {
+ final int i = in.read();
+ if (i > -1) {
+ tracker.addValue(1).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ final int i = in.read(b);
+ if (i > -1) {
+ tracker.addValue(i).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws
IOException {
+ final int i = in.read(b, off, len);
+ if (i > -1) {
+ tracker.addValue(i).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ return in.skip(n);
+ }
+
+ @Override
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+
+ @Override
+ public void mark(final int readlimit) {
+ in.mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ in.reset();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+}
=======================================
--- /dev/null
+++ /stajistics-core/src/main/java/org/stajistics/io/StatsOutputStream.java
Sun Jun 19 21:52:08 2011
@@ -0,0 +1,74 @@
+package org.stajistics.io;
+
+import org.stajistics.Stats;
+import org.stajistics.StatsKey;
+import org.stajistics.StatsManager;
+import org.stajistics.tracker.manual.ManualTracker;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author The Stajistics Project
+ */
+public class StatsOutputStream extends FilterOutputStream {
+
+ private final StatsManager statsManager;
+ private final StatsKey key;
+
+ private final ManualTracker tracker;
+
+ public StatsOutputStream(final StatsKey key,
+ final OutputStream out) {
+ this(null, key, out);
+ }
+
+ public StatsOutputStream(final StatsManager statsManager,
+ final StatsKey key,
+ final OutputStream out) {
+ super(out);
+
+ if (statsManager == null) {
+ this.statsManager = Stats.getManager();
+ } else {
+ this.statsManager = statsManager;
+ }
+
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
+
+ this.key = key;
+
+ tracker = statsManager.getTrackerLocator().getManualTracker(key);
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ tracker.addValue(1).commit();
+ out.write(b);
+ }
+
+ @Override
+ public void write(final byte[] b) throws IOException {
+ tracker.addValue(b.length).commit();
+ out.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ tracker.addValue(len).commit();
+ out.write(b, off, len);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ out.close();
+ }
+}
=======================================
--- /dev/null
+++ /stajistics-core/src/main/java/org/stajistics/io/StatsReader.java Sun
Jun 19 21:52:08 2011
@@ -0,0 +1,109 @@
+package org.stajistics.io;
+
+import org.stajistics.Stats;
+import org.stajistics.StatsKey;
+import org.stajistics.StatsManager;
+import org.stajistics.tracker.manual.ManualTracker;
+
+import java.io.FilterReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.CharBuffer;
+
+/**
+ * @author The Stajistics Project
+ */
+public class StatsReader extends FilterReader {
+
+ private final StatsManager statsManager;
+ private final StatsKey key;
+
+ private final ManualTracker tracker;
+
+ public StatsReader(final StatsManager statsManager,
+ final StatsKey key,
+ final Reader in) {
+ super(in);
+
+
+ if (statsManager == null) {
+ this.statsManager = Stats.getManager();
+ } else {
+ this.statsManager = statsManager;
+ }
+
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
+
+ this.key = key;
+
+ tracker = statsManager.getTrackerLocator().getManualTracker(key);
+ }
+
+ @Override
+ public int read() throws IOException {
+ final int i = in.read();
+ if (i > -1) {
+ tracker.addValue(1).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public int read(final char[] cbuf, final int off, final int len)
throws IOException {
+ final int i = in.read(cbuf, off, len);
+ if (i > -1) {
+ tracker.addValue(i).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ return in.skip(n);
+ }
+
+ @Override
+ public boolean ready() throws IOException {
+ return in.ready();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ @Override
+ public void mark(int readAheadLimit) throws IOException {
+ in.mark(readAheadLimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ in.reset();
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+
+ @Override
+ public int read(final CharBuffer target) throws IOException {
+ final int i = in.read(target);
+ if (i > -1) {
+ tracker.addValue(i).commit();
+ }
+ return i;
+ }
+
+ @Override
+ public int read(final char[] cbuf) throws IOException {
+ final int i = in.read(cbuf);
+ if (i > -1) {
+ tracker.addValue(i).commit();
+ }
+ return i;
+ }
+}
=======================================
--- /dev/null
+++ /stajistics-core/src/main/java/org/stajistics/io/StatsWriter.java Sun
Jun 19 21:52:08 2011
@@ -0,0 +1,102 @@
+package org.stajistics.io;
+
+import org.stajistics.Stats;
+import org.stajistics.StatsKey;
+import org.stajistics.StatsManager;
+import org.stajistics.tracker.manual.ManualTracker;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * @author The Stajistics Project
+ */
+public class StatsWriter extends FilterWriter {
+
+ private final StatsManager statsManager;
+ private final StatsKey key;
+
+ private final ManualTracker tracker;
+
+ protected StatsWriter(final StatsManager statsManager,
+ final StatsKey key,
+ final Writer out) {
+ super(out);
+
+ if (statsManager == null) {
+ this.statsManager = Stats.getManager();
+ } else {
+ this.statsManager = statsManager;
+ }
+
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
+
+ this.key = key;
+
+ tracker = statsManager.getTrackerLocator().getManualTracker(key);
+ }
+
+ @Override
+ public void write(final int c) throws IOException {
+ out.write(c);
+ tracker.addValue(1).commit();
+ }
+
+ @Override
+ public void write(final char[] cbuf, final int off, final int len)
throws IOException {
+ out.write(cbuf, off, len);
+ tracker.addValue(len).commit();
+ }
+
+ @Override
+ public void write(final String str, final int off, final int len)
throws IOException {
+ out.write(str, off, len);
+ tracker.addValue(len).commit();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ out.close();
+ }
+
+ @Override
+ public void write(final char[] cbuf) throws IOException {
+ out.write(cbuf);
+ tracker.addValue(cbuf.length).commit();
+ }
+
+ @Override
+ public void write(final String str) throws IOException {
+ out.write(str);
+ tracker.addValue(str.length()).commit();
+ }
+
+ @Override
+ public Writer append(final CharSequence csq) throws IOException {
+ out.append(csq);
+ tracker.addValue(csq.length()).commit();
+ return this;
+ }
+
+ @Override
+ public Writer append(final CharSequence csq, final int start, final
int end) throws IOException {
+ out.append(csq, start, end);
+ tracker.addValue(end - start).commit();
+ return this;
+ }
+
+ @Override
+ public Writer append(final char c) throws IOException {
+ out.append(c);
+ tracker.addValue(1).commit();
+ return this;
+ }
+}