You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sirona.apache.org by rm...@apache.org on 2013/11/08 10:34:56 UTC

svn commit: r1539961 - in /incubator/sirona/trunk: agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/ agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/ agent/store/cassandra/src/main/java/org/apache/sirona/cassand...

Author: rmannibucau
Date: Fri Nov  8 09:34:55 2013
New Revision: 1539961

URL: http://svn.apache.org/r1539961
Log:
cassandra collector counter should be almost working

Added:
    incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/
    incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/
    incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/AgentCounterTest.java
      - copied, changed from r1539712, incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/AgentCounterTest.java
Removed:
    incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CounterDao.java
    incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/AgentCounterTest.java
Modified:
    incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/CassandraBuilder.java
    incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/CassandraSirona.java
    incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraCollectorCounterDataStore.java
    incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraLeafCounter.java
    incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/framework/CassandraRunner.java
    incubator/sirona/trunk/core/src/main/java/org/apache/sirona/counters/Counter.java
    incubator/sirona/trunk/core/src/main/java/org/apache/sirona/store/counter/InMemoryCounterDataStore.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/AggregatedCollectorCounter.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java

Modified: incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/CassandraBuilder.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/CassandraBuilder.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/CassandraBuilder.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/CassandraBuilder.java Fri Nov  8 09:34:55 2013
@@ -26,7 +26,7 @@ public class CassandraBuilder {
     private String counterColumnFamily = "counters";
     private String gaugeColumnFamily = "gauges";
     private String statusColumnFamily = "statuses";
-    private String markersColumnFamily = "markers";
+    private String markerCountersColumFamily = "markers_counters";
     private int replicationFactor = 1;
 
     public String getHosts() {
@@ -57,7 +57,7 @@ public class CassandraBuilder {
         return replicationFactor;
     }
 
-    public String getMarkersColumnFamily() {
-        return markersColumnFamily;
+    public String getMarkerCountersColumFamily() {
+        return markerCountersColumFamily;
     }
 }

Modified: incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/CassandraSirona.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/CassandraSirona.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/CassandraSirona.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/CassandraSirona.java Fri Nov  8 09:34:55 2013
@@ -51,14 +51,14 @@ public class CassandraSirona {
         final ColumnFamilyDefinition counters = HFactory.createColumnFamilyDefinition(keyspaceName, builder.getCounterColumnFamily(), ComparatorType.UTF8TYPE);
         final ColumnFamilyDefinition gauges = HFactory.createColumnFamilyDefinition(keyspaceName, builder.getGaugeColumnFamily(), ComparatorType.UTF8TYPE);
         final ColumnFamilyDefinition statuses = HFactory.createColumnFamilyDefinition(keyspaceName, builder.getStatusColumnFamily(), ComparatorType.UTF8TYPE);
-        final ColumnFamilyDefinition markers = HFactory.createColumnFamilyDefinition(keyspaceName, builder.getMarkersColumnFamily(), ComparatorType.UTF8TYPE);
+        final ColumnFamilyDefinition markersCounters = HFactory.createColumnFamilyDefinition(keyspaceName, builder.getMarkerCountersColumFamily(), ComparatorType.UTF8TYPE);
 
         { // ensure keyspace exists, here if the keyspace doesn't exist we suppose nothing exist
             if (cluster.describeKeyspace(keyspaceName) == null) {
                 LOGGER.info("Creating Cassandra '" + keyspaceName + "' keyspace.");
                 cluster.addKeyspace(
                     HFactory.createKeyspaceDefinition(keyspaceName, ThriftKsDef.DEF_STRATEGY_CLASS, builder.getReplicationFactor(),
-                        asList(counters, gauges, statuses, markers)));
+                        asList(counters, gauges, statuses, markersCounters)));
             }
         }
     }
@@ -85,11 +85,15 @@ public class CassandraSirona {
         return builder.getCounterColumnFamily();
     }
 
-    public String getMarkersColumFamily() {
-        return builder.getMarkersColumnFamily();
-    }
-
     public Keyspace getKeyspace() {
         return keyspace;
     }
+
+    public String getMarkerCountersColumFamily() {
+        return builder.getMarkerCountersColumFamily();
+    }
+
+    public String keySeparator() {
+        return SEPARATOR;
+    }
 }

Modified: incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraCollectorCounterDataStore.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraCollectorCounterDataStore.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraCollectorCounterDataStore.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraCollectorCounterDataStore.java Fri Nov  8 09:34:55 2013
@@ -16,40 +16,227 @@
  */
 package org.apache.sirona.cassandra.collector.counter;
 
+import me.prettyprint.cassandra.serializers.DoubleSerializer;
+import me.prettyprint.cassandra.serializers.IntegerSerializer;
+import me.prettyprint.cassandra.serializers.LongSerializer;
+import me.prettyprint.cassandra.serializers.SerializerTypeInferer;
+import me.prettyprint.cassandra.serializers.StringSerializer;
+import me.prettyprint.cassandra.service.KeyIterator;
+import me.prettyprint.hector.api.Keyspace;
+import me.prettyprint.hector.api.Serializer;
+import me.prettyprint.hector.api.beans.ColumnSlice;
+import me.prettyprint.hector.api.beans.HColumn;
+import me.prettyprint.hector.api.factory.HFactory;
+import me.prettyprint.hector.api.query.QueryResult;
+import me.prettyprint.hector.api.query.SliceQuery;
+import org.apache.sirona.Role;
+import org.apache.sirona.cassandra.DynamicDelegatedSerializer;
+import org.apache.sirona.cassandra.collector.CassandraSirona;
+import org.apache.sirona.collector.server.store.counter.AggregatedCollectorCounter;
 import org.apache.sirona.collector.server.store.counter.InMemoryCollectorCounterStore;
 import org.apache.sirona.collector.server.store.counter.LeafCollectorCounter;
+import org.apache.sirona.configuration.Configuration;
 import org.apache.sirona.counters.Counter;
+import org.apache.sirona.counters.Unit;
+import org.apache.sirona.math.M2AwareStatisticalSummary;
 
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
 
 public class CassandraCollectorCounterDataStore extends InMemoryCollectorCounterStore {
-    private final CounterDao dao;
+    private static final String[] FIND_BY_KEYS_COLUMNS = new String[] { "maxConcurrency", "variance", "n", "max", "min", "sum", "m2", "mean" };
+    private static final String EMPTY_VALUE = "";
+
+    private final Keyspace keyspace;
+    private final String family;
+    private final String markerCounterFamily;
+    private final CassandraSirona cassandra;
 
     public CassandraCollectorCounterDataStore() {
-        dao = new CounterDao();
+        this.cassandra = Configuration.findOrCreateInstance(CassandraSirona.class);
+        this.keyspace = cassandra.getKeyspace();
+        this.family = cassandra.getCounterColumnFamily();
+        this.markerCounterFamily = cassandra.getMarkerCountersColumFamily();
     }
 
     @Override
     public LeafCollectorCounter getOrCreateCounter(final Counter.Key key, final String marker) {
-        final CassandraLeafCounter byKey = dao.findByKey(key, marker);
+        final CassandraLeafCounter byKey = findByKey(key, marker);
         if (byKey != null) {
             return byKey;
         }
-        return dao.save(new CassandraLeafCounter(key), marker);
+        return save(new CassandraLeafCounter(key, this, marker), marker);
     }
 
     @Override
-    public Collection<String> markers() {
-        return dao.markers();
+    public Collection<? extends LeafCollectorCounter> getCounters(final String marker) {
+        final SliceQuery<String, String, String> q = HFactory.createSliceQuery(keyspace,
+            StringSerializer.get(), StringSerializer.get(), StringSerializer.get());
+
+        final QueryResult<ColumnSlice<String, String>> result = q.setKey(marker)
+            .setColumnFamily(markerCounterFamily)
+            .setRange(null, null, false, Integer.MAX_VALUE)
+            .execute();
+
+        final ColumnSlice<String, String> map = result.get();
+        if (map.getColumns().isEmpty()) {
+            return null;
+        }
+
+        final Collection<CassandraLeafCounter> counters = new LinkedList<CassandraLeafCounter>();
+        for (final HColumn<String, String> c : map.getColumns()) {
+            final String key = c.getName();
+            final String[] segments = key.split(cassandra.keySeparator());
+            final Counter.Key ckey = new Counter.Key(new Role(segments[0], Unit.get(segments[1])), segments[2]);
+
+            final DynamicDelegatedSerializer<Number> dynamicSerializer = new DynamicDelegatedSerializer<Number>();
+            final SliceQuery<String, String, Number> slice = HFactory.createSliceQuery(keyspace,
+                StringSerializer.get(), StringSerializer.get(), dynamicSerializer);
+
+            final QueryResult<ColumnSlice<String, Number>> counterResult = slice.setKey(key)
+                .setColumnNames(FIND_BY_KEYS_COLUMNS)
+                .setColumnFamily(family)
+                .execute();
+
+            final ColumnSlice<String, Number> counterColumn = counterResult.get();
+            if (counterColumn.getColumns().isEmpty()) {
+                return null;
+            }
+
+            counters.add(counter(ckey, dynamicSerializer, counterColumn, marker));
+        }
+        return counters;
     }
 
     @Override
-    public Collection<? extends Counter> getCounters(final String marker) {
-        throw new UnsupportedOperationException();
+    public Collection<String> markers() {
+        final Collection<String> set = new HashSet<String>();
+        for (final String item : new KeyIterator.Builder<String>(cassandra.getKeyspace(), cassandra.getMarkerCountersColumFamily(), StringSerializer.get()).build()) {
+            set.add(item);
+        }
+        return set;
+    }
+
+    @Override // TODO: see if we shouldn't store it or if aggregation can be done on java side
+    public AggregatedCollectorCounter getOrCreateCounter(final Counter.Key key) {
+        final Map<String, LeafCollectorCounter> counters = new HashMap<String, LeafCollectorCounter>();
+        for (final String marker : markers()) {
+            final LeafCollectorCounter c = getOrCreateCounter(key, marker);
+            counters.put(marker, c);
+        }
+        return new AggregatedCollectorCounter(key, counters);
+    }
+
+    @Override // TODO: see if we shouldn't store it or if aggregation can be done on java side
+    public Collection<Counter> getCounters() {
+        final Map<Counter.Key, Map<String, LeafCollectorCounter>> counters = new HashMap<Counter.Key, Map<String, LeafCollectorCounter>>();
+        for (final String marker : markers()) {
+            for (final LeafCollectorCounter c : getCounters(marker)) {
+                Map<String, LeafCollectorCounter> values = counters.get(c.getKey());
+                if (values == null) {
+                    values = new HashMap<String, LeafCollectorCounter>();
+                    counters.put(c.getKey(), values);
+                }
+                values.put(marker, c);
+            }
+        }
+
+        final Collection<Counter> c = new LinkedList<Counter>();
+        for (final Map.Entry<Counter.Key, Map<String, LeafCollectorCounter>> entry : counters.entrySet()) {
+            c.add(new AggregatedCollectorCounter(entry.getKey(), entry.getValue()));
+        }
+
+        return c;
     }
 
     @Override
+    public void update(final Counter.Key key, final String marker, final M2AwareStatisticalSummary stats, final int concurrency) {
+        save(new CassandraLeafCounter(key, this, marker).sync(stats, concurrency), marker);
+    }
+
+    @Override // TODO: should we really clear counters or use a timestamp or a flag?
     public void clearCounters() {
-        throw new UnsupportedOperationException();
+        // no-op
+    }
+
+    protected CassandraLeafCounter findByKey(final Counter.Key ckey, final String marker) {
+        final String key = id(ckey, marker);
+
+        final DynamicDelegatedSerializer<Number> serializer = new DynamicDelegatedSerializer<Number>();
+        final SliceQuery<String, String, Number> q = HFactory.createSliceQuery(keyspace,
+            StringSerializer.get(), StringSerializer.get(), serializer);
+
+        final QueryResult<ColumnSlice<String, Number>> result = q.setKey(key)
+            .setColumnNames(FIND_BY_KEYS_COLUMNS)
+            .setColumnFamily(family)
+            .execute();
+
+        final ColumnSlice<String, Number> map = result.get();
+        if (map.getColumns().isEmpty()) {
+            return null;
+        }
+
+        return counter(ckey, serializer, map, marker);
+    }
+
+    protected CassandraLeafCounter counter(final Counter.Key ckey,
+                                         final DynamicDelegatedSerializer<Number> serializer,
+                                         final ColumnSlice<String, Number> map,
+                                         final String marker) {
+        return new CassandraLeafCounter(ckey, this, marker)
+            .sync(new M2AwareStatisticalSummary(
+                getOrZero(serializer, map.getColumnByName("mean"), DoubleSerializer.get()).doubleValue(),
+                getOrZero(serializer, map.getColumnByName("variance"), DoubleSerializer.get()).doubleValue(),
+                getOrZero(serializer, map.getColumnByName("n"), LongSerializer.get()).longValue(),
+                getOrZero(serializer, map.getColumnByName("max"), DoubleSerializer.get()).doubleValue(),
+                getOrZero(serializer, map.getColumnByName("min"), DoubleSerializer.get()).doubleValue(),
+                getOrZero(serializer, map.getColumnByName("sum"), DoubleSerializer.get()).doubleValue(),
+                getOrZero(serializer, map.getColumnByName("m2"), DoubleSerializer.get()).doubleValue()),
+                getOrZero(serializer, map.getColumnByName("maxConcurrency"), IntegerSerializer.get()).intValue());
+    }
+
+    protected CassandraLeafCounter save(final CassandraLeafCounter counter, final String marker) {
+        final Counter.Key key = counter.getKey();
+        final String id = id(key, marker);
+
+        // counter itself
+        HFactory.createMutator(keyspace, StringSerializer.get())
+            .addInsertion(id, family, column("role", key.getRole().getName()))
+            .addInsertion(id, family, column("key", key.getName()))
+            .addInsertion(id, family, column("maxConcurrency", counter.getMaxConcurrency()))
+            .addInsertion(id, family, column("variance", counter.getVariance()))
+            .addInsertion(id, family, column("n", counter.getHits()))
+            .addInsertion(id, family, column("max", counter.getMax()))
+            .addInsertion(id, family, column("min", counter.getMin()))
+            .addInsertion(id, family, column("sum", counter.getSum()))
+            .addInsertion(id, family, column("m2", counter.getSecondMoment()))
+            .addInsertion(id, family, column("mean", counter.getMean()))
+            .execute();
+
+        // marker-counter
+        HFactory.createMutator(keyspace, StringSerializer.get())
+            .addInsertion(marker, markerCounterFamily, column(id, EMPTY_VALUE))
+            .execute();
+
+        return counter;
+    }
+
+    protected String id(final Counter.Key key, final String marker) {
+        return cassandra.generateKey(key.getRole().getName(), key.getRole().getUnit().getName(), key.getName(), marker);
+    }
+
+    protected static Number getOrZero(final DynamicDelegatedSerializer<Number> delegatedSerializer, final HColumn<String, Number> col, final Serializer<? extends Number> serializer) {
+        delegatedSerializer.setDelegate(serializer);
+        if (col == null || col.getValue() == null) {
+            return 0;
+        }
+        return col.getValue();
+    }
+
+    protected static <B> HColumn<String, B> column(final String name, final B value) {
+        return HFactory.createColumn(name, value, StringSerializer.get(), (Serializer<B>) SerializerTypeInferer.getSerializer(value));
     }
 }

Modified: incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraLeafCounter.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraLeafCounter.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraLeafCounter.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/main/java/org/apache/sirona/cassandra/collector/counter/CassandraLeafCounter.java Fri Nov  8 09:34:55 2013
@@ -20,16 +20,27 @@ import org.apache.sirona.collector.serve
 import org.apache.sirona.math.M2AwareStatisticalSummary;
 
 public class CassandraLeafCounter extends LeafCollectorCounter {
-    public CassandraLeafCounter(final Key key) {
+    private final CassandraCollectorCounterDataStore store;
+    private final String marker;
+
+    public CassandraLeafCounter(final Key key, final CassandraCollectorCounterDataStore store, final String marker) {
         super(key);
+        this.store = store;
+        this.marker = marker;
     }
 
-    public void sync(final M2AwareStatisticalSummary newStats, final int newConcurrency) {
+    public CassandraLeafCounter sync(final M2AwareStatisticalSummary newStats, final int newConcurrency) {
         super.update(newStats, newConcurrency);
+        return this;
     }
 
     @Override
     public void update(final M2AwareStatisticalSummary newStats, final int newConcurrency) {
-        throw new UnsupportedOperationException();
+        super.update(newStats, newConcurrency);
+        store.save(this, marker);
+    }
+
+    public M2AwareStatisticalSummary getStatistics() {
+        return statistics;
     }
 }

Copied: incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/AgentCounterTest.java (from r1539712, incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/AgentCounterTest.java)
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/AgentCounterTest.java?p2=incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/AgentCounterTest.java&p1=incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/AgentCounterTest.java&r1=1539712&r2=1539961&rev=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/AgentCounterTest.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/collector/counter/AgentCounterTest.java Fri Nov  8 09:34:55 2013
@@ -14,18 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sirona.cassandra;
+package org.apache.sirona.cassandra.collector.counter;
 
 import me.prettyprint.hector.api.Cluster;
 import me.prettyprint.hector.api.Keyspace;
 import org.apache.sirona.Role;
-import org.apache.sirona.cassandra.collector.counter.CassandraCollectorCounterDataStore;
-import org.apache.sirona.cassandra.collector.counter.CounterDao;
 import org.apache.sirona.cassandra.framework.CassandraRunner;
 import org.apache.sirona.cassandra.framework.CassandraTestInject;
+import org.apache.sirona.collector.server.store.counter.AggregatedCollectorCounter;
 import org.apache.sirona.collector.server.store.counter.LeafCollectorCounter;
 import org.apache.sirona.counters.Counter;
 import org.apache.sirona.counters.Unit;
+import org.apache.sirona.math.M2AwareStatisticalSummary;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -34,7 +34,6 @@ import java.util.Collection;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 @RunWith(CassandraRunner.class)
@@ -60,9 +59,9 @@ public class AgentCounterTest {
         final Counter.Key key = new Counter.Key(new Role("K100Drap", Unit.UNARY), "K100Drap#1");
         final String marker = "node1";
 
-        assertNull(new CounterDao().findByKey(key, marker));
+        assertNull(new CassandraCollectorCounterDataStore().findByKey(key, marker));
         new CassandraCollectorCounterDataStore().getOrCreateCounter(key, marker);
-        assertNotNull(new CounterDao().findByKey(key, marker));
+        assertNotNull(new CassandraCollectorCounterDataStore().findByKey(key, marker));
 
         final LeafCollectorCounter counter = new CassandraCollectorCounterDataStore().getOrCreateCounter(key, marker);
         assertEquals("K100Drap#1", counter.getKey().getName());
@@ -74,12 +73,73 @@ public class AgentCounterTest {
         final Counter.Key key = new Counter.Key(new Role("K100Drap", Unit.UNARY), "K100Drap#1");
         final String marker = "node1";
 
-        assertNull(new CounterDao().findByKey(key, marker));
+        assertNull(new CassandraCollectorCounterDataStore().findByKey(key, marker));
         new CassandraCollectorCounterDataStore().getOrCreateCounter(key, marker);
-        assertNotNull(new CounterDao().findByKey(key, marker));
+        assertNotNull(new CassandraCollectorCounterDataStore().findByKey(key, marker));
 
         final Collection<String> markers = new CassandraCollectorCounterDataStore().markers();
         assertEquals(1, markers.size());
         assertTrue(markers.contains("node1"));
     }
+
+    @Test
+    public void getAggregatedCountersByKey() {
+        final Counter.Key key = new Counter.Key(new Role("cassandra", Unit.MEGA), "k");
+        final CassandraCollectorCounterDataStore store = new CassandraCollectorCounterDataStore();
+        final CassandraLeafCounter counter1 = new CassandraLeafCounter(key, store, "node1").sync(new M2AwareStatisticalSummary(1, 1, 1, 1, 1, 1, 1), 1);
+        final CassandraLeafCounter counter2 = new CassandraLeafCounter(key, store, "node2").sync(new M2AwareStatisticalSummary(3, 4, 4, 4, 4, 4, 4), 2);
+
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key, "node1").update(counter1.getStatistics(), counter1.getMaxConcurrency());
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key, "node2").update(counter2.getStatistics(), counter2.getMaxConcurrency());
+
+        final AggregatedCollectorCounter aggregation = new CassandraCollectorCounterDataStore().getOrCreateCounter(key);
+        assertEquals(3, aggregation.getMaxConcurrency());
+        assertEquals(1., aggregation.getMean(), 0.);
+        assertEquals(1., aggregation.getMin(), 0.);
+        assertEquals(5., aggregation.getHits(), 0.);
+        assertEquals(2.05, aggregation.getVariance(), 0.);
+        assertEquals(4., aggregation.getMax(), 0.);
+        assertEquals(5., aggregation.getSum(), 0.);
+        assertEquals(8.2, aggregation.getSecondMoment(), 0.);
+    }
+
+    @Test
+    public void getAggregatedCounters() {
+        final Counter.Key key1 = new Counter.Key(new Role("cassandra", Unit.MEGA), "k1");
+        final Counter.Key key2 = new Counter.Key(new Role("cassandra", Unit.MEGA), "k2");
+
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key1, "node1").update(new M2AwareStatisticalSummary(1, 1, 1, 1, 1, 1, 1), 1);
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key1, "node2").update(new M2AwareStatisticalSummary(3, 4, 4, 4, 4, 4, 4), 2);
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key2, "node1").update(new M2AwareStatisticalSummary(1, 1, 1, 1, 1, 1, 1), 1);
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key2, "node2").update(new M2AwareStatisticalSummary(3, 4, 4, 4, 4, 4, 4), 2);
+
+        final Collection<Counter> aggregations = new CassandraCollectorCounterDataStore().getCounters();
+        assertEquals(2, aggregations.size());
+
+        for (final Counter aggregation : aggregations) {
+            assertEquals(3, aggregation.getMaxConcurrency());
+            assertEquals(1., aggregation.getMean(), 0.);
+            assertEquals(1., aggregation.getMin(), 0.);
+            assertEquals(5., aggregation.getHits(), 0.);
+            assertEquals(2.05, aggregation.getVariance(), 0.);
+            assertEquals(4., aggregation.getMax(), 0.);
+            assertEquals(5., aggregation.getSum(), 0.);
+            assertEquals(8.2, aggregation.getSecondMoment(), 0.);
+        }
+    }
+
+    @Test
+    public void update() {
+        final Counter.Key key = new Counter.Key(new Role("K100Drap", Unit.UNARY), "K100Drap#1");
+
+        new CassandraCollectorCounterDataStore().getOrCreateCounter(key, "node1");
+        assertNotNull(new CassandraCollectorCounterDataStore().findByKey(key, "node1"));
+        new CassandraCollectorCounterDataStore().update(key, "node1", new M2AwareStatisticalSummary(3, 4, 4, 4, 4, 4, 4), 2);
+
+        final LeafCollectorCounter counter = new CassandraCollectorCounterDataStore().getOrCreateCounter(key, "node1");
+        assertEquals("K100Drap#1", counter.getKey().getName());
+        assertEquals("K100Drap", counter.getKey().getRole().getName());
+        assertEquals(4, counter.getMax(), 0.);
+        assertEquals(2, counter.getMaxConcurrency(), 0.);
+    }
 }

Modified: incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/framework/CassandraRunner.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/framework/CassandraRunner.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/framework/CassandraRunner.java (original)
+++ incubator/sirona/trunk/agent/store/cassandra/src/test/java/org/apache/sirona/cassandra/framework/CassandraRunner.java Fri Nov  8 09:34:55 2013
@@ -40,7 +40,7 @@ public class CassandraRunner extends Blo
     }
 
     @Override
-    protected List<MethodRule> rules(Object test) {
+    protected List<MethodRule> rules(final Object test) {
         final List<MethodRule> rules = super.rules(test);
         rules.add(new MethodRule(){
             public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {

Modified: incubator/sirona/trunk/core/src/main/java/org/apache/sirona/counters/Counter.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/core/src/main/java/org/apache/sirona/counters/Counter.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/core/src/main/java/org/apache/sirona/counters/Counter.java (original)
+++ incubator/sirona/trunk/core/src/main/java/org/apache/sirona/counters/Counter.java Fri Nov  8 09:34:55 2013
@@ -63,6 +63,7 @@ public interface Counter {
     public static class Key implements Serializable {
         private final String name;
         private final Role role;
+        private int hash = Integer.MIN_VALUE;
 
         public Key(final Role role, final String name) {
             this.role = role;
@@ -86,9 +87,11 @@ public interface Counter {
 
         @Override
         public int hashCode() {
-            int result = name.hashCode();
-            result = 31 * result + role.hashCode();
-            return result;
+            if (hash == Integer.MIN_VALUE) {
+                hash = name.hashCode();
+                hash = 31 * hash + role.hashCode();
+            }
+            return hash;
         }
 
         public String getName() {

Modified: incubator/sirona/trunk/core/src/main/java/org/apache/sirona/store/counter/InMemoryCounterDataStore.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/core/src/main/java/org/apache/sirona/store/counter/InMemoryCounterDataStore.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/core/src/main/java/org/apache/sirona/store/counter/InMemoryCounterDataStore.java (original)
+++ incubator/sirona/trunk/core/src/main/java/org/apache/sirona/store/counter/InMemoryCounterDataStore.java Fri Nov  8 09:34:55 2013
@@ -18,7 +18,6 @@ package org.apache.sirona.store.counter;
 
 import org.apache.sirona.counters.Counter;
 import org.apache.sirona.counters.DefaultCounter;
-import org.apache.sirona.store.counter.CounterDataStore;
 
 import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;

Modified: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/AggregatedCollectorCounter.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/AggregatedCollectorCounter.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/AggregatedCollectorCounter.java (original)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/AggregatedCollectorCounter.java Fri Nov  8 09:34:55 2013
@@ -33,6 +33,12 @@ public class AggregatedCollectorCounter 
         super(key);
     }
 
+    public AggregatedCollectorCounter(final Key key, final Map<String, LeafCollectorCounter> counters) {
+        super(key);
+        aggregation.putAll(counters);
+        update();
+    }
+
     public void update() {
         final Lock workLock = lock.writeLock();
         workLock.lock();

Modified: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java?rev=1539961&r1=1539960&r2=1539961&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java (original)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java Fri Nov  8 09:34:55 2013
@@ -41,7 +41,7 @@ public class InMemoryCollectorCounterSto
     }
 
     @Override
-    public Collection<? extends Counter> getCounters(final String marker) {
+    public Collection<? extends LeafCollectorCounter> getCounters(final String marker) {
         return countersByMarker.get(marker).values();
     }