blob: de531213840c195fc71d0dc9b3e5b94db891b700 [file] [log] [blame]
Madan Jampani10073672016-01-21 19:13:59 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Madan Jampani10073672016-01-21 19:13:59 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.store.primitives.impl;
18
Ray Milkey6a51cb92018-03-06 09:03:03 -080019import com.google.common.collect.Maps;
20import org.onosproject.store.primitives.MapUpdate;
21import org.onosproject.store.primitives.TransactionId;
22import org.onosproject.store.service.AsyncConsistentMap;
23import org.onosproject.store.service.MapEvent;
24import org.onosproject.store.service.MapEventListener;
25import org.onosproject.store.service.TransactionLog;
26import org.onosproject.store.service.Version;
27import org.onosproject.store.service.Versioned;
28import org.onosproject.utils.MeteringAgent;
29
Madan Jampani10073672016-01-21 19:13:59 -080030import java.util.Collection;
31import java.util.Map;
32import java.util.Map.Entry;
33import java.util.Set;
34import java.util.concurrent.CompletableFuture;
Hyunsun Moon65b38cb2016-05-06 18:27:37 -070035import java.util.concurrent.Executor;
Madan Jampani10073672016-01-21 19:13:59 -080036import java.util.function.BiFunction;
37import java.util.function.Function;
38import java.util.function.Predicate;
39
Madan Jampani10073672016-01-21 19:13:59 -080040/**
41 * {@link AsyncConsistentMap} that meters all its operations.
42 *
43 * @param <K> key type
44 * @param <V> value type
45 */
46public class MeteredAsyncConsistentMap<K, V> extends DelegatingAsyncConsistentMap<K, V> {
47
48 private static final String PRIMITIVE_NAME = "consistentMap";
49 private static final String SIZE = "size";
50 private static final String IS_EMPTY = "isEmpty";
51 private static final String CONTAINS_KEY = "containsKey";
52 private static final String CONTAINS_VALUE = "containsValue";
53 private static final String GET = "get";
Jordan Haltermanb2243072017-05-09 12:04:04 -070054 private static final String GET_OR_DEFAULT = "getOrDefault";
Madan Jampani10073672016-01-21 19:13:59 -080055 private static final String COMPUTE_IF = "computeIf";
56 private static final String PUT = "put";
57 private static final String PUT_AND_GET = "putAndGet";
58 private static final String PUT_IF_ABSENT = "putIfAbsent";
59 private static final String REMOVE = "remove";
60 private static final String CLEAR = "clear";
61 private static final String KEY_SET = "keySet";
62 private static final String VALUES = "values";
63 private static final String ENTRY_SET = "entrySet";
64 private static final String REPLACE = "replace";
65 private static final String COMPUTE_IF_ABSENT = "computeIfAbsent";
Jordan Halterman948d6592017-04-20 17:18:24 -070066 private static final String BEGIN = "begin";
Madan Jampani542d9e22016-04-05 15:39:55 -070067 private static final String PREPARE = "prepare";
68 private static final String COMMIT = "commit";
69 private static final String ROLLBACK = "rollback";
70 private static final String PREPARE_AND_COMMIT = "prepareAndCommit";
Madan Jampani10073672016-01-21 19:13:59 -080071 private static final String ADD_LISTENER = "addListener";
72 private static final String REMOVE_LISTENER = "removeListener";
73 private static final String NOTIFY_LISTENER = "notifyListener";
74
75 private final Map<MapEventListener<K, V>, InternalMeteredMapEventListener> listeners =
76 Maps.newIdentityHashMap();
77 private final MeteringAgent monitor;
78
79 public MeteredAsyncConsistentMap(AsyncConsistentMap<K, V> backingMap) {
80 super(backingMap);
81 this.monitor = new MeteringAgent(PRIMITIVE_NAME, backingMap.name(), true);
82 }
83
84 @Override
85 public CompletableFuture<Integer> size() {
86 final MeteringAgent.Context timer = monitor.startTimer(SIZE);
87 return super.size()
88 .whenComplete((r, e) -> timer.stop(e));
89 }
90
91 @Override
92 public CompletableFuture<Boolean> isEmpty() {
93 final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY);
94 return super.isEmpty()
95 .whenComplete((r, e) -> timer.stop(e));
96 }
97
98 @Override
99 public CompletableFuture<Boolean> containsKey(K key) {
100 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_KEY);
101 return super.containsKey(key)
102 .whenComplete((r, e) -> timer.stop(e));
103 }
104
105 @Override
106 public CompletableFuture<Boolean> containsValue(V value) {
107 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_VALUE);
108 return super.containsValue(value)
109 .whenComplete((r, e) -> timer.stop(e));
110 }
111
112 @Override
113 public CompletableFuture<Versioned<V>> get(K key) {
114 final MeteringAgent.Context timer = monitor.startTimer(GET);
115 return super.get(key)
116 .whenComplete((r, e) -> timer.stop(e));
117 }
118
119 @Override
Jordan Haltermanb2243072017-05-09 12:04:04 -0700120 public CompletableFuture<Versioned<V>> getOrDefault(K key, V defaultValue) {
121 final MeteringAgent.Context timer = monitor.startTimer(GET_OR_DEFAULT);
122 return super.getOrDefault(key, defaultValue)
123 .whenComplete((r, e) -> timer.stop(e));
124 }
125
126 @Override
Madan Jampani10073672016-01-21 19:13:59 -0800127 public CompletableFuture<Versioned<V>> computeIfAbsent(K key,
128 Function<? super K, ? extends V> mappingFunction) {
129 final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF_ABSENT);
130 return super.computeIfAbsent(key, mappingFunction)
131 .whenComplete((r, e) -> timer.stop(e));
132 }
133
134 @Override
135 public CompletableFuture<Versioned<V>> computeIf(K key,
136 Predicate<? super V> condition,
137 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
138 final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF);
139 return super.computeIf(key, condition, remappingFunction)
140 .whenComplete((r, e) -> timer.stop(e));
141 }
142
143 @Override
144 public CompletableFuture<Versioned<V>> put(K key, V value) {
145 final MeteringAgent.Context timer = monitor.startTimer(PUT);
146 return super.put(key, value)
147 .whenComplete((r, e) -> timer.stop(e));
148 }
149
150 @Override
151 public CompletableFuture<Versioned<V>> putAndGet(K key, V value) {
152 final MeteringAgent.Context timer = monitor.startTimer(PUT_AND_GET);
153 return super.putAndGet(key, value)
154 .whenComplete((r, e) -> timer.stop(e));
155 }
156
157 @Override
158 public CompletableFuture<Versioned<V>> remove(K key) {
159 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
160 return super.remove(key)
161 .whenComplete((r, e) -> timer.stop(e));
162 }
163
164 @Override
165 public CompletableFuture<Void> clear() {
166 final MeteringAgent.Context timer = monitor.startTimer(CLEAR);
167 return super.clear()
168 .whenComplete((r, e) -> timer.stop(e));
169 }
170
171 @Override
172 public CompletableFuture<Set<K>> keySet() {
173 final MeteringAgent.Context timer = monitor.startTimer(KEY_SET);
174 return super.keySet()
175 .whenComplete((r, e) -> timer.stop(e));
176 }
177
178 @Override
179 public CompletableFuture<Collection<Versioned<V>>> values() {
180 final MeteringAgent.Context timer = monitor.startTimer(VALUES);
181 return super.values()
182 .whenComplete((r, e) -> timer.stop(e));
183 }
184
185 @Override
186 public CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet() {
187 final MeteringAgent.Context timer = monitor.startTimer(ENTRY_SET);
188 return super.entrySet()
189 .whenComplete((r, e) -> timer.stop(e));
190 }
191
192 @Override
193 public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
194 final MeteringAgent.Context timer = monitor.startTimer(PUT_IF_ABSENT);
195 return super.putIfAbsent(key, value)
196 .whenComplete((r, e) -> timer.stop(e));
197 }
198
199 @Override
200 public CompletableFuture<Boolean> remove(K key, V value) {
201 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
202 return super.remove(key, value)
203 .whenComplete((r, e) -> timer.stop(e));
204
205 }
206
207 @Override
208 public CompletableFuture<Boolean> remove(K key, long version) {
209 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
210 return super.remove(key, version)
211 .whenComplete((r, e) -> timer.stop(e));
212 }
213
214 @Override
215 public CompletableFuture<Versioned<V>> replace(K key, V value) {
216 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
217 return super.replace(key, value)
218 .whenComplete((r, e) -> timer.stop(e));
219 }
220
221 @Override
222 public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
223 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
224 return super.replace(key, oldValue, newValue)
225 .whenComplete((r, e) -> timer.stop(e));
226 }
227
228 @Override
229 public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
230 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
231 return super.replace(key, oldVersion, newValue)
232 .whenComplete((r, e) -> timer.stop(e));
233 }
234
235 @Override
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700236 public CompletableFuture<Void> addListener(MapEventListener<K, V> listener, Executor executor) {
Madan Jampani10073672016-01-21 19:13:59 -0800237 final MeteringAgent.Context timer = monitor.startTimer(ADD_LISTENER);
238 synchronized (listeners) {
239 InternalMeteredMapEventListener meteredListener =
240 listeners.computeIfAbsent(listener, k -> new InternalMeteredMapEventListener(listener));
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700241 return super.addListener(meteredListener, executor)
Madan Jampani10073672016-01-21 19:13:59 -0800242 .whenComplete((r, e) -> timer.stop(e));
243 }
244 }
245
246 @Override
247 public CompletableFuture<Void> removeListener(MapEventListener<K, V> listener) {
248 final MeteringAgent.Context timer = monitor.startTimer(REMOVE_LISTENER);
249 InternalMeteredMapEventListener meteredListener = listeners.remove(listener);
250 if (meteredListener != null) {
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700251 return super.removeListener(meteredListener)
Madan Jampani10073672016-01-21 19:13:59 -0800252 .whenComplete((r, e) -> timer.stop(e));
253 } else {
254 timer.stop(null);
255 return CompletableFuture.completedFuture(null);
256 }
257 }
258
Madan Jampani542d9e22016-04-05 15:39:55 -0700259 @Override
Jordan Halterman948d6592017-04-20 17:18:24 -0700260 public CompletableFuture<Version> begin(TransactionId transactionId) {
261 final MeteringAgent.Context timer = monitor.startTimer(BEGIN);
262 return super.begin(transactionId)
263 .whenComplete((r, e) -> timer.stop(e));
264 }
265
266 @Override
267 public CompletableFuture<Boolean> prepare(TransactionLog<MapUpdate<K, V>> transactionLog) {
Madan Jampani542d9e22016-04-05 15:39:55 -0700268 final MeteringAgent.Context timer = monitor.startTimer(PREPARE);
Jordan Halterman948d6592017-04-20 17:18:24 -0700269 return super.prepare(transactionLog)
270 .whenComplete((r, e) -> timer.stop(e));
Madan Jampani542d9e22016-04-05 15:39:55 -0700271 }
272
273 @Override
274 public CompletableFuture<Void> commit(TransactionId transactionId) {
275 final MeteringAgent.Context timer = monitor.startTimer(COMMIT);
276 return super.commit(transactionId)
277 .whenComplete((r, e) -> timer.stop(e));
278 }
279
280 @Override
281 public CompletableFuture<Void> rollback(TransactionId transactionId) {
282 final MeteringAgent.Context timer = monitor.startTimer(ROLLBACK);
283 return super.rollback(transactionId)
284 .whenComplete((r, e) -> timer.stop(e));
285 }
286
287 @Override
Jordan Halterman948d6592017-04-20 17:18:24 -0700288 public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<MapUpdate<K, V>> transactionLog) {
Madan Jampani542d9e22016-04-05 15:39:55 -0700289 final MeteringAgent.Context timer = monitor.startTimer(PREPARE_AND_COMMIT);
Jordan Halterman948d6592017-04-20 17:18:24 -0700290 return super.prepareAndCommit(transactionLog)
291 .whenComplete((r, e) -> timer.stop(e));
Madan Jampani542d9e22016-04-05 15:39:55 -0700292 }
293
Madan Jampani10073672016-01-21 19:13:59 -0800294 private class InternalMeteredMapEventListener implements MapEventListener<K, V> {
295
296 private final MapEventListener<K, V> listener;
297
298 InternalMeteredMapEventListener(MapEventListener<K, V> listener) {
299 this.listener = listener;
300 }
301
302 @Override
303 public void event(MapEvent<K, V> event) {
304 final MeteringAgent.Context timer = monitor.startTimer(NOTIFY_LISTENER);
305 try {
306 listener.event(event);
307 timer.stop(null);
308 } catch (Exception e) {
309 timer.stop(e);
Ray Milkey6a51cb92018-03-06 09:03:03 -0800310 throw new IllegalStateException(e);
Madan Jampani10073672016-01-21 19:13:59 -0800311 }
312 }
313 }
314}