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 | } | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -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 | ... | ... |
core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounterBuilder.java
... | @@ -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 | ... | ... |
core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMapBuilder.java
... | @@ -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 | +} |
-
Please register or login to post a comment