Flavio Castro
Committed by Gerrit Code Review

ONOS-2456 Added usage metrics to Atomic Counter and Distributed Queue plus refactored the code a bit

Refactored code plus instrumented AtomicValue and DistributedSet

Change-Id: I9c5f7c9f23d530131f15d3c98250ea33238dd2ec
Showing 18 changed files with 469 additions and 114 deletions
...@@ -59,6 +59,14 @@ public interface AtomicCounterBuilder { ...@@ -59,6 +59,14 @@ public interface AtomicCounterBuilder {
59 AtomicCounterBuilder withRetryOnFailure(); 59 AtomicCounterBuilder withRetryOnFailure();
60 60
61 /** 61 /**
62 + * Instantiates Metering service to gather usage and performance metrics.
63 + * By default, usage data will be stored.
64 + *
65 + * @return this AtomicCounterBuilder
66 + */
67 + AtomicCounterBuilder withMeteringDisabled();
68 +
69 + /**
62 * Sets the executor service to use for retrying failed operations. 70 * Sets the executor service to use for retrying failed operations.
63 * <p> 71 * <p>
64 * Note: Must be set when retries are enabled 72 * Note: Must be set when retries are enabled
......
...@@ -60,6 +60,14 @@ public interface AtomicValueBuilder<V> { ...@@ -60,6 +60,14 @@ public interface AtomicValueBuilder<V> {
60 AtomicValueBuilder<V> withPartitionsDisabled(); 60 AtomicValueBuilder<V> withPartitionsDisabled();
61 61
62 /** 62 /**
63 + * Instantiates Metering service to gather usage and performance metrics.
64 + * By default, usage data will be stored.
65 + *
66 + * @return this AtomicValueBuilder for method chaining
67 + */
68 + AtomicValueBuilder<V> withMeteringDisabled();
69 +
70 + /**
63 * Builds a AtomicValue based on the configuration options 71 * Builds a AtomicValue based on the configuration options
64 * supplied to this builder. 72 * supplied to this builder.
65 * 73 *
......
...@@ -105,6 +105,14 @@ public interface ConsistentMapBuilder<K, V> { ...@@ -105,6 +105,14 @@ public interface ConsistentMapBuilder<K, V> {
105 ConsistentMapBuilder<K, V> withPurgeOnUninstall(); 105 ConsistentMapBuilder<K, V> withPurgeOnUninstall();
106 106
107 /** 107 /**
108 + * Instantiates Metering service to gather usage and performance metrics.
109 + * By default, usage data will be stored.
110 + *
111 + * @return this ConsistentMapBuilder
112 + */
113 + ConsistentMapBuilder<K, V> withMeteringDisabled();
114 +
115 + /**
108 * Builds an consistent map based on the configuration options 116 * Builds an consistent map based on the configuration options
109 * supplied to this builder. 117 * supplied to this builder.
110 * 118 *
......
...@@ -51,6 +51,14 @@ public interface DistributedQueueBuilder<E> { ...@@ -51,6 +51,14 @@ public interface DistributedQueueBuilder<E> {
51 DistributedQueueBuilder<E> withSerializer(Serializer serializer); 51 DistributedQueueBuilder<E> withSerializer(Serializer serializer);
52 52
53 /** 53 /**
54 + *
55 + *
56 + * @return this DistributedQueueBuilder for method chaining
57 + */
58 + DistributedQueueBuilder<E> withMeteringDisabled();
59 +
60 +
61 + /**
54 * Disables persistence of queues entries. 62 * Disables persistence of queues entries.
55 * <p> 63 * <p>
56 * When persistence is disabled, a full cluster restart will wipe out all 64 * When persistence is disabled, a full cluster restart will wipe out all
......
...@@ -92,6 +92,13 @@ public interface DistributedSetBuilder<E> { ...@@ -92,6 +92,13 @@ public interface DistributedSetBuilder<E> {
92 DistributedSetBuilder<E> withPartitionsDisabled(); 92 DistributedSetBuilder<E> withPartitionsDisabled();
93 93
94 /** 94 /**
95 + * Instantiate Metrics service to gather usage and performance metrics.
96 + * By default usage information is enabled
97 + * @return this DistributedSetBuilder
98 + */
99 + DistributedSetBuilder<E> withMeteringDisabled();
100 +
101 + /**
95 * Purges set contents when the application owning the set is uninstalled. 102 * Purges set contents when the application owning the set is uninstalled.
96 * <p> 103 * <p>
97 * When this option is enabled, the caller must provide a applicationId via 104 * When this option is enabled, the caller must provide a applicationId via
......
...@@ -247,6 +247,11 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { ...@@ -247,6 +247,11 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
247 } 247 }
248 248
249 @Override 249 @Override
250 + public ConsistentMapBuilder<K, V> withMeteringDisabled() {
251 + return this;
252 + }
253 +
254 + @Override
250 public ConsistentMap<K, V> build() { 255 public ConsistentMap<K, V> build() {
251 return new TestConsistentMap<>(mapName); 256 return new TestConsistentMap<>(mapName);
252 } 257 }
......
...@@ -15,20 +15,15 @@ ...@@ -15,20 +15,15 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 +import org.onosproject.store.service.AsyncAtomicCounter;
19 +import org.slf4j.Logger;
20 +
18 import java.util.concurrent.CompletableFuture; 21 import java.util.concurrent.CompletableFuture;
19 import java.util.concurrent.ScheduledExecutorService; 22 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.TimeUnit; 23 import java.util.concurrent.TimeUnit;
21 import java.util.function.BiFunction; 24 import java.util.function.BiFunction;
22 25
23 -import org.onosproject.store.service.AsyncAtomicCounter; 26 +import static com.google.common.base.Preconditions.checkNotNull;
24 -
25 -
26 -
27 -
28 -
29 -import org.slf4j.Logger;
30 -
31 -import static com.google.common.base.Preconditions.*;
32 import static org.slf4j.LoggerFactory.getLogger; 27 import static org.slf4j.LoggerFactory.getLogger;
33 28
34 /** 29 /**
...@@ -46,66 +41,90 @@ public class DefaultAsyncAtomicCounter implements AsyncAtomicCounter { ...@@ -46,66 +41,90 @@ public class DefaultAsyncAtomicCounter implements AsyncAtomicCounter {
46 // TODO: configure delay via builder 41 // TODO: configure delay via builder
47 private static final int DELAY_BETWEEN_RETRY_SEC = 1; 42 private static final int DELAY_BETWEEN_RETRY_SEC = 1;
48 private final Logger log = getLogger(getClass()); 43 private final Logger log = getLogger(getClass());
44 + private final MeteringAgent monitor;
45 +
46 + private static final String PRIMITIVE_NAME = "atomicCounter";
47 + private static final String INCREMENT_AND_GET = "incrementAndGet";
48 + private static final String GET_AND_INCREMENT = "getAndIncrement";
49 + private static final String GET_AND_ADD = "getAndAdd";
50 + private static final String ADD_AND_GET = "addAndGet";
51 + private static final String GET = "get";
49 52
50 public DefaultAsyncAtomicCounter(String name, 53 public DefaultAsyncAtomicCounter(String name,
51 - Database database, 54 + Database database,
52 - boolean retryOnException, 55 + boolean retryOnException,
53 - ScheduledExecutorService retryExecutor) { 56 + boolean meteringEnabled,
57 + ScheduledExecutorService retryExecutor) {
54 this.name = checkNotNull(name); 58 this.name = checkNotNull(name);
55 this.database = checkNotNull(database); 59 this.database = checkNotNull(database);
56 this.retryOnFailure = retryOnException; 60 this.retryOnFailure = retryOnException;
57 this.retryExecutor = retryExecutor; 61 this.retryExecutor = retryExecutor;
62 + this.monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled);
58 } 63 }
59 64
60 @Override 65 @Override
61 public CompletableFuture<Long> incrementAndGet() { 66 public CompletableFuture<Long> incrementAndGet() {
62 - return addAndGet(1L); 67 + final MeteringAgent.Context timer = monitor.startTimer(INCREMENT_AND_GET);
68 + return addAndGet(1L)
69 + .whenComplete((r, e) -> timer.stop());
63 } 70 }
64 71
65 @Override 72 @Override
66 public CompletableFuture<Long> get() { 73 public CompletableFuture<Long> get() {
67 - return database.counterGet(name); 74 + final MeteringAgent.Context timer = monitor.startTimer(GET);
75 + return database.counterGet(name)
76 + .whenComplete((r, e) -> timer.stop());
68 } 77 }
69 78
70 @Override 79 @Override
71 public CompletableFuture<Long> getAndIncrement() { 80 public CompletableFuture<Long> getAndIncrement() {
72 - return getAndAdd(1L); 81 + final MeteringAgent.Context timer = monitor.startTimer(GET_AND_INCREMENT);
82 + return getAndAdd(1L)
83 + .whenComplete((r, e) -> timer.stop());
73 } 84 }
74 85
75 @Override 86 @Override
76 public CompletableFuture<Long> getAndAdd(long delta) { 87 public CompletableFuture<Long> getAndAdd(long delta) {
88 + final MeteringAgent.Context timer = monitor.startTimer(GET_AND_ADD);
77 CompletableFuture<Long> result = database.counterGetAndAdd(name, delta); 89 CompletableFuture<Long> result = database.counterGetAndAdd(name, delta);
78 if (!retryOnFailure) { 90 if (!retryOnFailure) {
79 - return result; 91 + return result
92 + .whenComplete((r, e) -> timer.stop());
80 } 93 }
81 94
82 CompletableFuture<Long> future = new CompletableFuture<>(); 95 CompletableFuture<Long> future = new CompletableFuture<>();
83 return result.whenComplete((r, e) -> { 96 return result.whenComplete((r, e) -> {
97 + timer.stop();
98 + // TODO : Account for retries
84 if (e != null) { 99 if (e != null) {
85 log.warn("getAndAdd failed due to {}. Will retry", e.getMessage()); 100 log.warn("getAndAdd failed due to {}. Will retry", e.getMessage());
86 retryExecutor.schedule(new RetryTask(database::counterGetAndAdd, delta, future), 101 retryExecutor.schedule(new RetryTask(database::counterGetAndAdd, delta, future),
87 - DELAY_BETWEEN_RETRY_SEC, 102 + DELAY_BETWEEN_RETRY_SEC,
88 - TimeUnit.SECONDS); 103 + TimeUnit.SECONDS);
89 } else { 104 } else {
90 future.complete(r); 105 future.complete(r);
91 } 106 }
92 - }).thenCompose(v -> future); 107 + }).thenCompose(v -> future);
93 } 108 }
94 109
95 @Override 110 @Override
96 public CompletableFuture<Long> addAndGet(long delta) { 111 public CompletableFuture<Long> addAndGet(long delta) {
112 + final MeteringAgent.Context timer = monitor.startTimer(ADD_AND_GET);
97 CompletableFuture<Long> result = database.counterAddAndGet(name, delta); 113 CompletableFuture<Long> result = database.counterAddAndGet(name, delta);
98 if (!retryOnFailure) { 114 if (!retryOnFailure) {
99 - return result; 115 + return result
116 + .whenComplete((r, e) -> timer.stop());
100 } 117 }
101 118
102 CompletableFuture<Long> future = new CompletableFuture<>(); 119 CompletableFuture<Long> future = new CompletableFuture<>();
103 return result.whenComplete((r, e) -> { 120 return result.whenComplete((r, e) -> {
121 + timer.stop();
122 + // TODO : Account for retries
104 if (e != null) { 123 if (e != null) {
105 log.warn("addAndGet failed due to {}. Will retry", e.getMessage()); 124 log.warn("addAndGet failed due to {}. Will retry", e.getMessage());
106 retryExecutor.schedule(new RetryTask(database::counterAddAndGet, delta, future), 125 retryExecutor.schedule(new RetryTask(database::counterAddAndGet, delta, future),
107 - DELAY_BETWEEN_RETRY_SEC, 126 + DELAY_BETWEEN_RETRY_SEC,
108 - TimeUnit.SECONDS); 127 + TimeUnit.SECONDS);
109 } else { 128 } else {
110 future.complete(r); 129 future.complete(r);
111 } 130 }
......
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 +import org.onosproject.store.service.AsyncAtomicCounter;
19 +import org.onosproject.store.service.AtomicCounter;
20 +import org.onosproject.store.service.StorageException;
21 +
18 import java.util.concurrent.CompletableFuture; 22 import java.util.concurrent.CompletableFuture;
19 import java.util.concurrent.ExecutionException; 23 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.ScheduledExecutorService; 24 import java.util.concurrent.ScheduledExecutorService;
21 import java.util.concurrent.TimeUnit; 25 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException; 26 import java.util.concurrent.TimeoutException;
23 27
24 -import org.onosproject.store.service.AsyncAtomicCounter;
25 -import org.onosproject.store.service.AtomicCounter;
26 -import org.onosproject.store.service.StorageException;
27 -
28 /** 28 /**
29 * Default implementation for a distributed AtomicCounter backed by 29 * Default implementation for a distributed AtomicCounter backed by
30 * partitioned Raft DB. 30 * partitioned Raft DB.
...@@ -38,10 +38,11 @@ public class DefaultAtomicCounter implements AtomicCounter { ...@@ -38,10 +38,11 @@ public class DefaultAtomicCounter implements AtomicCounter {
38 private final AsyncAtomicCounter asyncCounter; 38 private final AsyncAtomicCounter asyncCounter;
39 39
40 public DefaultAtomicCounter(String name, 40 public DefaultAtomicCounter(String name,
41 - Database database, 41 + Database database,
42 - boolean retryOnException, 42 + boolean retryOnException,
43 - ScheduledExecutorService retryExecutor) { 43 + boolean meteringEnabled,
44 - asyncCounter = new DefaultAsyncAtomicCounter(name, database, retryOnException, retryExecutor); 44 + ScheduledExecutorService retryExecutor) {
45 + asyncCounter = new DefaultAsyncAtomicCounter(name, database, retryOnException, meteringEnabled, retryExecutor);
45 } 46 }
46 47
47 @Override 48 @Override
......
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import java.util.concurrent.ScheduledExecutorService;
19 -
20 import org.onosproject.store.service.AsyncAtomicCounter; 18 import org.onosproject.store.service.AsyncAtomicCounter;
21 import org.onosproject.store.service.AtomicCounter; 19 import org.onosproject.store.service.AtomicCounter;
22 import org.onosproject.store.service.AtomicCounterBuilder; 20 import org.onosproject.store.service.AtomicCounterBuilder;
23 21
22 +import java.util.concurrent.ScheduledExecutorService;
23 +
24 import static com.google.common.base.Preconditions.checkArgument; 24 import static com.google.common.base.Preconditions.checkArgument;
25 25
26 /** 26 /**
...@@ -33,6 +33,7 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder { ...@@ -33,6 +33,7 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder {
33 private final Database partitionedDatabase; 33 private final Database partitionedDatabase;
34 private final Database inMemoryDatabase; 34 private final Database inMemoryDatabase;
35 private boolean retryOnFailure = false; 35 private boolean retryOnFailure = false;
36 + private boolean metering = true;
36 private ScheduledExecutorService retryExecutor = null; 37 private ScheduledExecutorService retryExecutor = null;
37 38
38 public DefaultAtomicCounterBuilder(Database inMemoryDatabase, Database partitionedDatabase) { 39 public DefaultAtomicCounterBuilder(Database inMemoryDatabase, Database partitionedDatabase) {
...@@ -57,14 +58,14 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder { ...@@ -57,14 +58,14 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder {
57 public AtomicCounter build() { 58 public AtomicCounter build() {
58 validateInputs(); 59 validateInputs();
59 Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase; 60 Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase;
60 - return new DefaultAtomicCounter(name, database, retryOnFailure, retryExecutor); 61 + return new DefaultAtomicCounter(name, database, retryOnFailure, metering, retryExecutor);
61 } 62 }
62 63
63 @Override 64 @Override
64 public AsyncAtomicCounter buildAsyncCounter() { 65 public AsyncAtomicCounter buildAsyncCounter() {
65 validateInputs(); 66 validateInputs();
66 Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase; 67 Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase;
67 - return new DefaultAsyncAtomicCounter(name, database, retryOnFailure, retryExecutor); 68 + return new DefaultAsyncAtomicCounter(name, database, retryOnFailure, metering, retryExecutor);
68 } 69 }
69 70
70 @Override 71 @Override
...@@ -74,6 +75,12 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder { ...@@ -74,6 +75,12 @@ public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder {
74 } 75 }
75 76
76 @Override 77 @Override
78 + public AtomicCounterBuilder withMeteringDisabled() {
79 + metering = false;
80 + return this;
81 + }
82 +
83 + @Override
77 public AtomicCounterBuilder withRetryExecutor(ScheduledExecutorService executor) { 84 public AtomicCounterBuilder withRetryExecutor(ScheduledExecutorService executor) {
78 this.retryExecutor = executor; 85 this.retryExecutor = executor;
79 return this; 86 return this;
......
...@@ -15,9 +15,6 @@ ...@@ -15,9 +15,6 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import java.util.Set;
19 -import java.util.concurrent.CopyOnWriteArraySet;
20 -
21 import org.onosproject.store.service.AtomicValue; 18 import org.onosproject.store.service.AtomicValue;
22 import org.onosproject.store.service.AtomicValueEvent; 19 import org.onosproject.store.service.AtomicValueEvent;
23 import org.onosproject.store.service.AtomicValueEventListener; 20 import org.onosproject.store.service.AtomicValueEventListener;
...@@ -27,6 +24,9 @@ import org.onosproject.store.service.MapEventListener; ...@@ -27,6 +24,9 @@ import org.onosproject.store.service.MapEventListener;
27 import org.onosproject.store.service.Serializer; 24 import org.onosproject.store.service.Serializer;
28 import org.onosproject.store.service.Versioned; 25 import org.onosproject.store.service.Versioned;
29 26
27 +import java.util.Set;
28 +import java.util.concurrent.CopyOnWriteArraySet;
29 +
30 /** 30 /**
31 * Default implementation of AtomicValue. 31 * Default implementation of AtomicValue.
32 * 32 *
...@@ -39,41 +39,64 @@ public class DefaultAtomicValue<V> implements AtomicValue<V> { ...@@ -39,41 +39,64 @@ public class DefaultAtomicValue<V> implements AtomicValue<V> {
39 private final String name; 39 private final String name;
40 private final Serializer serializer; 40 private final Serializer serializer;
41 private final MapEventListener<String, byte[]> mapEventListener = new InternalMapEventListener(); 41 private final MapEventListener<String, byte[]> mapEventListener = new InternalMapEventListener();
42 + private final MeteringAgent monitor;
43 +
44 + private static final String COMPONENT_NAME = "atomicValue";
45 + private static final String GET = "get";
46 + private static final String GET_AND_SET = "getAndSet";
47 + private static final String COMPARE_AND_SET = "compareAndSet";
42 48
43 public DefaultAtomicValue(ConsistentMap<String, byte[]> valueMap, 49 public DefaultAtomicValue(ConsistentMap<String, byte[]> valueMap,
44 - String name, 50 + String name,
45 - Serializer serializer) { 51 + boolean meteringEnabled,
52 + Serializer serializer) {
46 this.valueMap = valueMap; 53 this.valueMap = valueMap;
47 this.name = name; 54 this.name = name;
48 this.serializer = serializer; 55 this.serializer = serializer;
56 + this.monitor = new MeteringAgent(COMPONENT_NAME, name, meteringEnabled);
49 } 57 }
50 58
51 @Override 59 @Override
52 public boolean compareAndSet(V expect, V update) { 60 public boolean compareAndSet(V expect, V update) {
53 - if (expect == null) { 61 + final MeteringAgent.Context newTimer = monitor.startTimer(COMPARE_AND_SET);
54 - if (update == null) { 62 + try {
55 - return true; 63 + if (expect == null) {
56 - } 64 + if (update == null) {
57 - return valueMap.putIfAbsent(name, serializer.encode(update)) == null; 65 + return true;
58 - } else { 66 + }
59 - if (update == null) { 67 + return valueMap.putIfAbsent(name, serializer.encode(update)) == null;
60 - return valueMap.remove(name, serializer.encode(expect)); 68 + } else {
69 + if (update == null) {
70 + return valueMap.remove(name, serializer.encode(expect));
71 + }
72 + return valueMap.replace(name, serializer.encode(expect), serializer.encode(update));
61 } 73 }
62 - return valueMap.replace(name, serializer.encode(expect), serializer.encode(update)); 74 + } finally {
75 + newTimer.stop();
63 } 76 }
64 } 77 }
65 78
66 @Override 79 @Override
67 public V get() { 80 public V get() {
68 - Versioned<byte[]> rawValue = valueMap.get(name); 81 + final MeteringAgent.Context newTimer = monitor.startTimer(GET);
69 - return rawValue == null ? null : serializer.decode(rawValue.value()); 82 + try {
83 + Versioned<byte[]> rawValue = valueMap.get(name);
84 + return rawValue == null ? null : serializer.decode(rawValue.value());
85 + } finally {
86 + newTimer.stop();
87 + }
70 } 88 }
71 89
72 @Override 90 @Override
73 public V getAndSet(V value) { 91 public V getAndSet(V value) {
74 - Versioned<byte[]> previousValue = value == null ? 92 + final MeteringAgent.Context newTimer = monitor.startTimer(GET_AND_SET);
75 - valueMap.remove(name) : valueMap.put(name, serializer.encode(value)); 93 + try {
76 - return previousValue == null ? null : serializer.decode(previousValue.value()); 94 + Versioned<byte[]> previousValue = value == null ?
95 + valueMap.remove(name) : valueMap.put(name, serializer.encode(value));
96 + return previousValue == null ? null : serializer.decode(previousValue.value());
97 + } finally {
98 + newTimer.stop();
99 + }
77 } 100 }
78 101
79 @Override 102 @Override
......
...@@ -31,10 +31,12 @@ public class DefaultAtomicValueBuilder<V> implements AtomicValueBuilder<V> { ...@@ -31,10 +31,12 @@ public class DefaultAtomicValueBuilder<V> implements AtomicValueBuilder<V> {
31 private Serializer serializer; 31 private Serializer serializer;
32 private String name; 32 private String name;
33 private ConsistentMapBuilder<String, byte[]> mapBuilder; 33 private ConsistentMapBuilder<String, byte[]> mapBuilder;
34 + private boolean metering = true;
34 35
35 public DefaultAtomicValueBuilder(DatabaseManager manager) { 36 public DefaultAtomicValueBuilder(DatabaseManager manager) {
36 mapBuilder = manager.<String, byte[]>consistentMapBuilder() 37 mapBuilder = manager.<String, byte[]>consistentMapBuilder()
37 .withName("onos-atomic-values") 38 .withName("onos-atomic-values")
39 + .withMeteringDisabled()
38 .withSerializer(Serializer.using(KryoNamespaces.BASIC)); 40 .withSerializer(Serializer.using(KryoNamespaces.BASIC));
39 } 41 }
40 42
...@@ -57,7 +59,13 @@ public class DefaultAtomicValueBuilder<V> implements AtomicValueBuilder<V> { ...@@ -57,7 +59,13 @@ public class DefaultAtomicValueBuilder<V> implements AtomicValueBuilder<V> {
57 } 59 }
58 60
59 @Override 61 @Override
62 + public AtomicValueBuilder<V> withMeteringDisabled() {
63 + metering = false;
64 + return this;
65 + }
66 +
67 + @Override
60 public AtomicValue<V> build() { 68 public AtomicValue<V> build() {
61 - return new DefaultAtomicValue<>(mapBuilder.build(), name, serializer); 69 + return new DefaultAtomicValue<>(mapBuilder.build(), name, metering, serializer);
62 } 70 }
63 } 71 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -15,15 +15,15 @@ ...@@ -15,15 +15,15 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkArgument;
19 -import static com.google.common.base.Preconditions.checkState;
20 -
21 import org.onosproject.core.ApplicationId; 18 import org.onosproject.core.ApplicationId;
22 import org.onosproject.store.service.AsyncConsistentMap; 19 import org.onosproject.store.service.AsyncConsistentMap;
23 import org.onosproject.store.service.ConsistentMap; 20 import org.onosproject.store.service.ConsistentMap;
24 import org.onosproject.store.service.ConsistentMapBuilder; 21 import org.onosproject.store.service.ConsistentMapBuilder;
25 import org.onosproject.store.service.Serializer; 22 import org.onosproject.store.service.Serializer;
26 23
24 +import static com.google.common.base.Preconditions.checkArgument;
25 +import static com.google.common.base.Preconditions.checkState;
26 +
27 /** 27 /**
28 * Default Consistent Map builder. 28 * Default Consistent Map builder.
29 * 29 *
...@@ -38,6 +38,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K ...@@ -38,6 +38,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
38 private boolean purgeOnUninstall = false; 38 private boolean purgeOnUninstall = false;
39 private boolean partitionsEnabled = true; 39 private boolean partitionsEnabled = true;
40 private boolean readOnly = false; 40 private boolean readOnly = false;
41 + private boolean metering = true;
41 private final DatabaseManager manager; 42 private final DatabaseManager manager;
42 43
43 public DefaultConsistentMapBuilder(DatabaseManager manager) { 44 public DefaultConsistentMapBuilder(DatabaseManager manager) {
...@@ -65,6 +66,12 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K ...@@ -65,6 +66,12 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
65 } 66 }
66 67
67 @Override 68 @Override
69 + public ConsistentMapBuilder<K, V> withMeteringDisabled() {
70 + metering = false;
71 + return this;
72 + }
73 +
74 + @Override
68 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) { 75 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
69 checkArgument(serializer != null); 76 checkArgument(serializer != null);
70 this.serializer = serializer; 77 this.serializer = serializer;
...@@ -109,7 +116,8 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K ...@@ -109,7 +116,8 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
109 partitionsEnabled ? manager.partitionedDatabase : manager.inMemoryDatabase, 116 partitionsEnabled ? manager.partitionedDatabase : manager.inMemoryDatabase,
110 serializer, 117 serializer,
111 readOnly, 118 readOnly,
112 - purgeOnUninstall); 119 + purgeOnUninstall,
120 + metering);
113 return manager.registerMap(asyncMap); 121 return manager.registerMap(asyncMap);
114 } 122 }
115 } 123 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -15,25 +15,24 @@ ...@@ -15,25 +15,24 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkNotNull; 18 +import com.google.common.collect.Sets;
19 +import com.google.common.util.concurrent.Futures;
20 +import org.onosproject.cluster.NodeId;
21 +import org.onosproject.store.service.DistributedQueue;
22 +import org.onosproject.store.service.Serializer;
19 23
20 import java.util.Set; 24 import java.util.Set;
21 import java.util.concurrent.CompletableFuture; 25 import java.util.concurrent.CompletableFuture;
22 import java.util.function.Consumer; 26 import java.util.function.Consumer;
23 27
24 -import org.onosproject.cluster.NodeId; 28 +import static com.google.common.base.Preconditions.checkNotNull;
25 -import org.onosproject.store.service.DistributedQueue;
26 -import org.onosproject.store.service.Serializer;
27 -
28 -import com.google.common.collect.Sets;
29 -import com.google.common.util.concurrent.Futures;
30 29
31 /** 30 /**
32 * DistributedQueue implementation that provides FIFO ordering semantics. 31 * DistributedQueue implementation that provides FIFO ordering semantics.
33 * 32 *
34 * @param <E> queue entry type 33 * @param <E> queue entry type
35 */ 34 */
36 -public class DefaultDistributedQueue<E> implements DistributedQueue<E> { 35 +public class DefaultDistributedQueue<E> implements DistributedQueue<E> {
37 36
38 private final String name; 37 private final String name;
39 private final Database database; 38 private final Database database;
...@@ -42,35 +41,56 @@ public class DefaultDistributedQueue<E> implements DistributedQueue<E> { ...@@ -42,35 +41,56 @@ public class DefaultDistributedQueue<E> implements DistributedQueue<E> {
42 private final Set<CompletableFuture<E>> pendingFutures = Sets.newIdentityHashSet(); 41 private final Set<CompletableFuture<E>> pendingFutures = Sets.newIdentityHashSet();
43 private final Consumer<Set<NodeId>> notifyConsumers; 42 private final Consumer<Set<NodeId>> notifyConsumers;
44 43
44 + private static final String PRIMITIVE_NAME = "distributedQueue";
45 + private static final String SIZE = "size";
46 + private static final String PUSH = "push";
47 + private static final String POP = "pop";
48 + private static final String PEEK = "peek";
49 +
45 private static final String ERROR_NULL_ENTRY = "Null entries are not allowed"; 50 private static final String ERROR_NULL_ENTRY = "Null entries are not allowed";
51 + private final MeteringAgent monitor;
46 52
47 public DefaultDistributedQueue(String name, 53 public DefaultDistributedQueue(String name,
48 - Database database, 54 + Database database,
49 - Serializer serializer, 55 + Serializer serializer,
50 - NodeId localNodeId, 56 + NodeId localNodeId,
51 - Consumer<Set<NodeId>> notifyConsumers) { 57 + boolean meteringEnabled,
58 + Consumer<Set<NodeId>> notifyConsumers) {
52 this.name = checkNotNull(name, "queue name cannot be null"); 59 this.name = checkNotNull(name, "queue name cannot be null");
53 this.database = checkNotNull(database, "database cannot be null"); 60 this.database = checkNotNull(database, "database cannot be null");
54 this.serializer = checkNotNull(serializer, "serializer cannot be null"); 61 this.serializer = checkNotNull(serializer, "serializer cannot be null");
55 this.localNodeId = localNodeId; 62 this.localNodeId = localNodeId;
56 this.notifyConsumers = notifyConsumers; 63 this.notifyConsumers = notifyConsumers;
64 + this.monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled);
65 +
57 } 66 }
58 67
59 @Override 68 @Override
60 public long size() { 69 public long size() {
61 - return Futures.getUnchecked(database.queueSize(name)); 70 + final MeteringAgent.Context timer = monitor.startTimer(SIZE);
71 + try {
72 + return Futures.getUnchecked(database.queueSize(name));
73 + } finally {
74 + timer.stop();
75 + }
62 } 76 }
63 77
64 @Override 78 @Override
65 public void push(E entry) { 79 public void push(E entry) {
66 - checkNotNull(entry, ERROR_NULL_ENTRY); 80 + final MeteringAgent.Context timer = monitor.startTimer(PUSH);
67 - Futures.getUnchecked(database.queuePush(name, serializer.encode(entry)) 81 + try {
68 - .thenAccept(notifyConsumers) 82 + checkNotNull(entry, ERROR_NULL_ENTRY);
69 - .thenApply(v -> null)); 83 + Futures.getUnchecked(database.queuePush(name, serializer.encode(entry))
84 + .thenAccept(notifyConsumers)
85 + .thenApply(v -> null));
86 + } finally {
87 + timer.stop();
88 + }
70 } 89 }
71 90
72 @Override 91 @Override
73 public CompletableFuture<E> pop() { 92 public CompletableFuture<E> pop() {
93 + final MeteringAgent.Context timer = monitor.startTimer(POP);
74 return database.queuePop(name, localNodeId) 94 return database.queuePop(name, localNodeId)
75 .thenCompose(v -> { 95 .thenCompose(v -> {
76 if (v != null) { 96 if (v != null) {
...@@ -80,13 +100,19 @@ public class DefaultDistributedQueue<E> implements DistributedQueue<E> { ...@@ -80,13 +100,19 @@ public class DefaultDistributedQueue<E> implements DistributedQueue<E> {
80 pendingFutures.add(newPendingFuture); 100 pendingFutures.add(newPendingFuture);
81 return newPendingFuture; 101 return newPendingFuture;
82 } 102 }
83 - }); 103 + })
104 + .whenComplete((r, e) -> timer.stop());
84 } 105 }
85 106
86 @Override 107 @Override
87 public E peek() { 108 public E peek() {
88 - return Futures.getUnchecked(database.queuePeek(name) 109 + final MeteringAgent.Context timer = monitor.startTimer(PEEK);
89 - .thenApply(v -> v != null ? serializer.decode(v) : null)); 110 + try {
111 + return Futures.getUnchecked(database.queuePeek(name)
112 + .thenApply(v -> v != null ? serializer.decode(v) : null));
113 + } finally {
114 + timer.stop();
115 + }
90 } 116 }
91 117
92 public String name() { 118 public String name() {
......
...@@ -15,18 +15,17 @@ ...@@ -15,18 +15,17 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkArgument; 18 +import com.google.common.base.Charsets;
19 -import static com.google.common.base.Preconditions.checkState;
20 -
21 -import java.util.Set;
22 -import java.util.function.Consumer;
23 -
24 import org.onosproject.cluster.NodeId; 19 import org.onosproject.cluster.NodeId;
25 import org.onosproject.store.service.DistributedQueue; 20 import org.onosproject.store.service.DistributedQueue;
26 import org.onosproject.store.service.DistributedQueueBuilder; 21 import org.onosproject.store.service.DistributedQueueBuilder;
27 import org.onosproject.store.service.Serializer; 22 import org.onosproject.store.service.Serializer;
28 23
29 -import com.google.common.base.Charsets; 24 +import java.util.Set;
25 +import java.util.function.Consumer;
26 +
27 +import static com.google.common.base.Preconditions.checkArgument;
28 +import static com.google.common.base.Preconditions.checkState;
30 29
31 /** 30 /**
32 * Default implementation of a {@code DistributedQueueBuilder}. 31 * Default implementation of a {@code DistributedQueueBuilder}.
...@@ -39,6 +38,7 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde ...@@ -39,6 +38,7 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde
39 private String name; 38 private String name;
40 private boolean persistenceEnabled = true; 39 private boolean persistenceEnabled = true;
41 private final DatabaseManager databaseManager; 40 private final DatabaseManager databaseManager;
41 + private boolean metering = true;
42 42
43 public DefaultDistributedQueueBuilder( 43 public DefaultDistributedQueueBuilder(
44 DatabaseManager databaseManager) { 44 DatabaseManager databaseManager) {
...@@ -60,6 +60,12 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde ...@@ -60,6 +60,12 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde
60 } 60 }
61 61
62 @Override 62 @Override
63 + public DistributedQueueBuilder<E> withMeteringDisabled() {
64 + metering = false;
65 + return this;
66 + }
67 +
68 + @Override
63 public DistributedQueueBuilder<E> withPersistenceDisabled() { 69 public DistributedQueueBuilder<E> withPersistenceDisabled() {
64 persistenceEnabled = false; 70 persistenceEnabled = false;
65 return this; 71 return this;
...@@ -81,6 +87,7 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde ...@@ -81,6 +87,7 @@ public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilde
81 persistenceEnabled ? databaseManager.partitionedDatabase : databaseManager.inMemoryDatabase, 87 persistenceEnabled ? databaseManager.partitionedDatabase : databaseManager.inMemoryDatabase,
82 serializer, 88 serializer,
83 databaseManager.localNodeId, 89 databaseManager.localNodeId,
90 + metering,
84 notifyOthers); 91 notifyOthers);
85 databaseManager.registerQueue(queue); 92 databaseManager.registerQueue(queue);
86 return queue; 93 return queue;
......
...@@ -15,11 +15,8 @@ ...@@ -15,11 +15,8 @@
15 */ 15 */
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 -import java.util.Collection; 18 +import com.google.common.collect.Maps;
19 -import java.util.Iterator; 19 +import com.google.common.collect.Sets;
20 -import java.util.Map;
21 -import java.util.Set;
22 -
23 import org.onosproject.store.service.ConsistentMap; 20 import org.onosproject.store.service.ConsistentMap;
24 import org.onosproject.store.service.DistributedSet; 21 import org.onosproject.store.service.DistributedSet;
25 import org.onosproject.store.service.MapEvent; 22 import org.onosproject.store.service.MapEvent;
...@@ -27,8 +24,10 @@ import org.onosproject.store.service.MapEventListener; ...@@ -27,8 +24,10 @@ import org.onosproject.store.service.MapEventListener;
27 import org.onosproject.store.service.SetEvent; 24 import org.onosproject.store.service.SetEvent;
28 import org.onosproject.store.service.SetEventListener; 25 import org.onosproject.store.service.SetEventListener;
29 26
30 -import com.google.common.collect.Maps; 27 +import java.util.Collection;
31 -import com.google.common.collect.Sets; 28 +import java.util.Iterator;
29 +import java.util.Map;
30 +import java.util.Set;
32 31
33 /** 32 /**
34 * Implementation of distributed set that is backed by a ConsistentMap. 33 * Implementation of distributed set that is backed by a ConsistentMap.
...@@ -37,96 +36,178 @@ import com.google.common.collect.Sets; ...@@ -37,96 +36,178 @@ import com.google.common.collect.Sets;
37 */ 36 */
38 public class DefaultDistributedSet<E> implements DistributedSet<E> { 37 public class DefaultDistributedSet<E> implements DistributedSet<E> {
39 38
39 + private static final String CONTAINS = "contains";
40 + private static final String PRIMITIVE_NAME = "distributedSet";
41 + private static final String SIZE = "size";
42 + private static final String IS_EMPTY = "isEmpty";
43 + private static final String ITERATOR = "iterator";
44 + private static final String TO_ARRAY = "toArray";
45 + private static final String ADD = "add";
46 + private static final String REMOVE = "remove";
47 + private static final String CONTAINS_ALL = "containsAll";
48 + private static final String ADD_ALL = "addAll";
49 + private static final String RETAIN_ALL = "retainAll";
50 + private static final String REMOVE_ALL = "removeAll";
51 + private static final String CLEAR = "clear";
52 +
40 private final String name; 53 private final String name;
41 private final ConsistentMap<E, Boolean> backingMap; 54 private final ConsistentMap<E, Boolean> backingMap;
42 private final Map<SetEventListener<E>, MapEventListener<E, Boolean>> listenerMapping = Maps.newIdentityHashMap(); 55 private final Map<SetEventListener<E>, MapEventListener<E, Boolean>> listenerMapping = Maps.newIdentityHashMap();
56 + private final MeteringAgent monitor;
43 57
44 - public DefaultDistributedSet(String name, ConsistentMap<E, Boolean> backingMap) { 58 + public DefaultDistributedSet(String name, boolean meteringEnabled, ConsistentMap<E, Boolean> backingMap) {
45 this.name = name; 59 this.name = name;
46 this.backingMap = backingMap; 60 this.backingMap = backingMap;
61 + monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled);
47 } 62 }
48 63
49 @Override 64 @Override
50 public int size() { 65 public int size() {
51 - return backingMap.size(); 66 + final MeteringAgent.Context timer = monitor.startTimer(SIZE);
67 + try {
68 + return backingMap.size();
69 + } finally {
70 + timer.stop();
71 + }
52 } 72 }
53 73
54 @Override 74 @Override
55 public boolean isEmpty() { 75 public boolean isEmpty() {
56 - return backingMap.isEmpty(); 76 + final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY);
77 + try {
78 + return backingMap.isEmpty();
79 + } finally {
80 + timer.stop();
81 + }
57 } 82 }
58 83
59 @SuppressWarnings("unchecked") 84 @SuppressWarnings("unchecked")
60 @Override 85 @Override
61 public boolean contains(Object o) { 86 public boolean contains(Object o) {
62 - return backingMap.containsKey((E) o); 87 + final MeteringAgent.Context timer = monitor.startTimer(CONTAINS);
88 + try {
89 + return backingMap.containsKey((E) o);
90 + } finally {
91 + timer.stop();
92 + }
63 } 93 }
64 94
65 @Override 95 @Override
66 public Iterator<E> iterator() { 96 public Iterator<E> iterator() {
67 - return backingMap.keySet().iterator(); 97 + final MeteringAgent.Context timer = monitor.startTimer(ITERATOR);
98 + //Do we have to measure this guy?
99 + try {
100 + return backingMap.keySet().iterator();
101 + } finally {
102 + timer.stop();
103 + }
68 } 104 }
69 105
70 @Override 106 @Override
71 public Object[] toArray() { 107 public Object[] toArray() {
72 - return backingMap.keySet().stream().toArray(); 108 + final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY);
109 + try {
110 + return backingMap.keySet().stream().toArray();
111 + } finally {
112 + timer.stop();
113 + }
73 } 114 }
74 115
75 @Override 116 @Override
76 public <T> T[] toArray(T[] a) { 117 public <T> T[] toArray(T[] a) {
77 - return backingMap.keySet().stream().toArray(size -> a); 118 + final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY);
119 + try {
120 + return backingMap.keySet().stream().toArray(size -> a);
121 + } finally {
122 + timer.stop();
123 + }
78 } 124 }
79 125
80 @Override 126 @Override
81 public boolean add(E e) { 127 public boolean add(E e) {
82 - return backingMap.putIfAbsent(e, true) == null; 128 + final MeteringAgent.Context timer = monitor.startTimer(ADD);
129 + try {
130 + return backingMap.putIfAbsent(e, true) == null;
131 + } finally {
132 + timer.stop();
133 + }
83 } 134 }
84 135
85 @SuppressWarnings("unchecked") 136 @SuppressWarnings("unchecked")
86 @Override 137 @Override
87 public boolean remove(Object o) { 138 public boolean remove(Object o) {
88 - return backingMap.remove((E) o) != null; 139 + final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
140 + try {
141 + return backingMap.remove((E) o) != null;
142 + } finally {
143 + timer.stop();
144 + }
89 } 145 }
90 146
91 @Override 147 @Override
92 public boolean containsAll(Collection<?> c) { 148 public boolean containsAll(Collection<?> c) {
93 - return c.stream() 149 + final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_ALL);
150 + try {
151 + return c.stream()
94 .allMatch(this::contains); 152 .allMatch(this::contains);
153 + } finally {
154 + timer.stop();
155 + }
95 } 156 }
96 157
97 @Override 158 @Override
98 public boolean addAll(Collection<? extends E> c) { 159 public boolean addAll(Collection<? extends E> c) {
99 - return c.stream() 160 + final MeteringAgent.Context timer = monitor.startTimer(ADD_ALL);
161 + try {
162 + return c.stream()
100 .map(this::add) 163 .map(this::add)
101 .reduce(Boolean::logicalOr) 164 .reduce(Boolean::logicalOr)
102 .orElse(false); 165 .orElse(false);
166 + } finally {
167 + timer.stop();
168 + }
103 } 169 }
104 170
105 @Override 171 @Override
106 public boolean retainAll(Collection<?> c) { 172 public boolean retainAll(Collection<?> c) {
107 - Set<?> retainSet = Sets.newHashSet(c); 173 + final MeteringAgent.Context timer = monitor.startTimer(RETAIN_ALL);
108 - return backingMap.keySet() 174 + try {
175 + Set<?> retainSet = Sets.newHashSet(c);
176 + return backingMap.keySet()
109 .stream() 177 .stream()
110 .filter(k -> !retainSet.contains(k)) 178 .filter(k -> !retainSet.contains(k))
111 .map(this::remove) 179 .map(this::remove)
112 .reduce(Boolean::logicalOr) 180 .reduce(Boolean::logicalOr)
113 .orElse(false); 181 .orElse(false);
182 + } finally {
183 + timer.stop();
184 + }
114 } 185 }
115 186
116 @Override 187 @Override
117 public boolean removeAll(Collection<?> c) { 188 public boolean removeAll(Collection<?> c) {
118 - Set<?> removeSet = Sets.newHashSet(c); 189 + final MeteringAgent.Context timer = monitor.startTimer(REMOVE_ALL);
119 - return backingMap.keySet() 190 + try {
120 - .stream() 191 + Set<?> removeSet = Sets.newHashSet(c);
121 - .filter(removeSet::contains) 192 + return backingMap.keySet()
122 - .map(this::remove) 193 + .stream()
123 - .reduce(Boolean::logicalOr) 194 + .filter(removeSet::contains)
124 - .orElse(false); 195 + .map(this::remove)
196 + .reduce(Boolean::logicalOr)
197 + .orElse(false);
198 + } finally {
199 + timer.stop();
200 + }
125 } 201 }
126 202
127 @Override 203 @Override
128 public void clear() { 204 public void clear() {
129 - backingMap.clear(); 205 + final MeteringAgent.Context timer = monitor.startTimer(CLEAR);
206 + try {
207 + backingMap.clear();
208 + } finally {
209 + timer.stop();
210 + }
130 } 211 }
131 212
132 @Override 213 @Override
......
...@@ -30,9 +30,11 @@ public class DefaultDistributedSetBuilder<E> implements DistributedSetBuilder<E> ...@@ -30,9 +30,11 @@ public class DefaultDistributedSetBuilder<E> implements DistributedSetBuilder<E>
30 30
31 private String name; 31 private String name;
32 private ConsistentMapBuilder<E, Boolean> mapBuilder; 32 private ConsistentMapBuilder<E, Boolean> mapBuilder;
33 + private boolean metering = true;
33 34
34 public DefaultDistributedSetBuilder(DatabaseManager manager) { 35 public DefaultDistributedSetBuilder(DatabaseManager manager) {
35 this.mapBuilder = manager.consistentMapBuilder(); 36 this.mapBuilder = manager.consistentMapBuilder();
37 + mapBuilder.withMeteringDisabled();
36 } 38 }
37 39
38 @Override 40 @Override
...@@ -73,7 +75,13 @@ public class DefaultDistributedSetBuilder<E> implements DistributedSetBuilder<E> ...@@ -73,7 +75,13 @@ public class DefaultDistributedSetBuilder<E> implements DistributedSetBuilder<E>
73 } 75 }
74 76
75 @Override 77 @Override
78 + public DistributedSetBuilder<E> withMeteringDisabled() {
79 + metering = false;
80 + return this;
81 + }
82 +
83 + @Override
76 public DistributedSet<E> build() { 84 public DistributedSet<E> build() {
77 - return new DefaultDistributedSet<E>(name, mapBuilder.build()); 85 + return new DefaultDistributedSet<E>(name, metering, mapBuilder.build());
78 } 86 }
79 } 87 }
......
1 +package org.onosproject.store.consistent.impl;
2 +
3 +/*
4 + * Copyright 2015 Open Networking Laboratory
5 + *
6 + * Licensed under the Apache License, Version 2.0 (the "License");
7 + * you may not use this file except in compliance with the License.
8 + * You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing, software
13 + * distributed under the License is distributed on an "AS IS" BASIS,
14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 + * See the License for the specific language governing permissions and
16 + * limitations under the License.
17 + */
18 +
19 +import com.codahale.metrics.Timer;
20 +import com.google.common.collect.Maps;
21 +import org.onlab.metrics.MetricsComponent;
22 +import org.onlab.metrics.MetricsFeature;
23 +import org.onlab.metrics.MetricsService;
24 +import org.onlab.osgi.DefaultServiceDirectory;
25 +
26 +import java.util.Map;
27 +import java.util.concurrent.TimeUnit;
28 +
29 +import static com.google.common.base.Preconditions.checkNotNull;
30 +
31 +/**
32 + * Agent that implements usage and performance monitoring via the metrics service.
33 + */
34 +public class MeteringAgent {
35 +
36 + private MetricsService metricsService;
37 + private MetricsComponent metricsComponent;
38 + private MetricsFeature metricsFeature;
39 + private final Map<String, Timer> perObjOpTimers = Maps.newConcurrentMap();
40 + private final Map<String, Timer> perOpTimers = Maps.newConcurrentMap();
41 + private Timer perPrimitiveTimer;
42 + private Timer perObjTimer;
43 + private MetricsFeature wildcard;
44 + private final boolean activated;
45 + private Context nullTimer;
46 +
47 + /**
48 + * Constructs a new MeteringAgent for a given distributed primitive.
49 + * Instantiates the metrics service
50 + * Initializes all the general metrics for that object
51 + *
52 + * @param primitiveName Type of primitive to be metered
53 + * @param objName Global name of the primitive
54 + * @param activated
55 + */
56 + public MeteringAgent(String primitiveName, String objName, boolean activated) {
57 + checkNotNull(objName, "Object name cannot be null");
58 + this.activated = activated;
59 + nullTimer = new Context(null, "");
60 + if (this.activated) {
61 + this.metricsService = DefaultServiceDirectory.getService(MetricsService.class);
62 + this.metricsComponent = metricsService.registerComponent(primitiveName);
63 + this.metricsFeature = metricsComponent.registerFeature(objName);
64 + this.wildcard = metricsComponent.registerFeature("*");
65 + this.perObjTimer = metricsService.createTimer(metricsComponent, metricsFeature, "*");
66 + this.perPrimitiveTimer = metricsService.createTimer(metricsComponent, wildcard, "*");
67 + }
68 + }
69 +
70 + /**
71 + * Initializes a specific timer for a given operation.
72 + *
73 + * @param op Specific operation being metered
74 + */
75 + public Context startTimer(String op) {
76 + if (!activated) {
77 + return nullTimer;
78 + }
79 + // Check if timer exists, if it doesn't creates it
80 + final Timer currTimer = perObjOpTimers.computeIfAbsent(op, timer ->
81 + metricsService.createTimer(metricsComponent, metricsFeature, op));
82 + perOpTimers.computeIfAbsent(op, timer -> metricsService.createTimer(metricsComponent, wildcard, op));
83 + // Starts timer
84 + return new Context(currTimer.time(), op);
85 + }
86 +
87 + /**
88 + * Timer.Context with a specific operation.
89 + */
90 + public class Context {
91 + private final Timer.Context context;
92 + private final String operation;
93 +
94 + /**
95 + * Constructs Context.
96 + *
97 + * @param context
98 + * @param operation
99 + */
100 + public Context(Timer.Context context, String operation) {
101 + this.context = context;
102 + this.operation = operation;
103 + }
104 +
105 + /**
106 + * Stops timer given a specific context and updates all related metrics.
107 + */
108 + public void stop() {
109 + if (!activated) {
110 + return;
111 + }
112 + //Stop and updates timer with specific measurements per map, per operation
113 + final long time = context.stop();
114 + //updates timer with aggregated measurements per map
115 + perOpTimers.get(operation).update(time, TimeUnit.NANOSECONDS);
116 + //updates timer with aggregated measurements per map
117 + perObjTimer.update(time, TimeUnit.NANOSECONDS);
118 + //updates timer with aggregated measurements per all Consistent Maps
119 + perPrimitiveTimer.update(time, TimeUnit.NANOSECONDS);
120 + }
121 + }
122 +
123 +}