blob: f8844fb0c6c58394815fa917c903ccc6585d9ac0 [file] [log] [blame]
Madan Jampani10073672016-01-21 19:13:59 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
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
19import java.util.Collection;
20import java.util.Map;
21import java.util.Map.Entry;
22import java.util.Set;
23import java.util.concurrent.CompletableFuture;
Hyunsun Moon65b38cb2016-05-06 18:27:37 -070024import java.util.concurrent.Executor;
Madan Jampani10073672016-01-21 19:13:59 -080025import java.util.function.BiFunction;
26import java.util.function.Function;
27import java.util.function.Predicate;
28
Madan Jampani542d9e22016-04-05 15:39:55 -070029import org.onosproject.store.primitives.TransactionId;
Madan Jampani10073672016-01-21 19:13:59 -080030import org.onosproject.store.service.AsyncConsistentMap;
31import org.onosproject.store.service.MapEvent;
32import org.onosproject.store.service.MapEventListener;
Madan Jampani542d9e22016-04-05 15:39:55 -070033import org.onosproject.store.service.MapTransaction;
Madan Jampani10073672016-01-21 19:13:59 -080034import org.onosproject.store.service.Versioned;
35
36import com.google.common.base.Throwables;
37import com.google.common.collect.Maps;
Madan Jampani542d9e22016-04-05 15:39:55 -070038
Aaron Kruglikov1110b2c2016-02-02 16:24:37 -080039import org.onosproject.utils.MeteringAgent;
Madan Jampani10073672016-01-21 19:13:59 -080040
41/**
42 * {@link AsyncConsistentMap} that meters all its operations.
43 *
44 * @param <K> key type
45 * @param <V> value type
46 */
47public class MeteredAsyncConsistentMap<K, V> extends DelegatingAsyncConsistentMap<K, V> {
48
49 private static final String PRIMITIVE_NAME = "consistentMap";
50 private static final String SIZE = "size";
51 private static final String IS_EMPTY = "isEmpty";
52 private static final String CONTAINS_KEY = "containsKey";
53 private static final String CONTAINS_VALUE = "containsValue";
54 private static final String GET = "get";
55 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";
Madan Jampani542d9e22016-04-05 15:39:55 -070066 private static final String PREPARE = "prepare";
67 private static final String COMMIT = "commit";
68 private static final String ROLLBACK = "rollback";
69 private static final String PREPARE_AND_COMMIT = "prepareAndCommit";
Madan Jampani10073672016-01-21 19:13:59 -080070 private static final String ADD_LISTENER = "addListener";
71 private static final String REMOVE_LISTENER = "removeListener";
72 private static final String NOTIFY_LISTENER = "notifyListener";
73
74 private final Map<MapEventListener<K, V>, InternalMeteredMapEventListener> listeners =
75 Maps.newIdentityHashMap();
76 private final MeteringAgent monitor;
77
78 public MeteredAsyncConsistentMap(AsyncConsistentMap<K, V> backingMap) {
79 super(backingMap);
80 this.monitor = new MeteringAgent(PRIMITIVE_NAME, backingMap.name(), true);
81 }
82
83 @Override
84 public CompletableFuture<Integer> size() {
85 final MeteringAgent.Context timer = monitor.startTimer(SIZE);
86 return super.size()
87 .whenComplete((r, e) -> timer.stop(e));
88 }
89
90 @Override
91 public CompletableFuture<Boolean> isEmpty() {
92 final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY);
93 return super.isEmpty()
94 .whenComplete((r, e) -> timer.stop(e));
95 }
96
97 @Override
98 public CompletableFuture<Boolean> containsKey(K key) {
99 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_KEY);
100 return super.containsKey(key)
101 .whenComplete((r, e) -> timer.stop(e));
102 }
103
104 @Override
105 public CompletableFuture<Boolean> containsValue(V value) {
106 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_VALUE);
107 return super.containsValue(value)
108 .whenComplete((r, e) -> timer.stop(e));
109 }
110
111 @Override
112 public CompletableFuture<Versioned<V>> get(K key) {
113 final MeteringAgent.Context timer = monitor.startTimer(GET);
114 return super.get(key)
115 .whenComplete((r, e) -> timer.stop(e));
116 }
117
118 @Override
119 public CompletableFuture<Versioned<V>> computeIfAbsent(K key,
120 Function<? super K, ? extends V> mappingFunction) {
121 final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF_ABSENT);
122 return super.computeIfAbsent(key, mappingFunction)
123 .whenComplete((r, e) -> timer.stop(e));
124 }
125
126 @Override
127 public CompletableFuture<Versioned<V>> computeIf(K key,
128 Predicate<? super V> condition,
129 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
130 final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF);
131 return super.computeIf(key, condition, remappingFunction)
132 .whenComplete((r, e) -> timer.stop(e));
133 }
134
135 @Override
136 public CompletableFuture<Versioned<V>> put(K key, V value) {
137 final MeteringAgent.Context timer = monitor.startTimer(PUT);
138 return super.put(key, value)
139 .whenComplete((r, e) -> timer.stop(e));
140 }
141
142 @Override
143 public CompletableFuture<Versioned<V>> putAndGet(K key, V value) {
144 final MeteringAgent.Context timer = monitor.startTimer(PUT_AND_GET);
145 return super.putAndGet(key, value)
146 .whenComplete((r, e) -> timer.stop(e));
147 }
148
149 @Override
150 public CompletableFuture<Versioned<V>> remove(K key) {
151 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
152 return super.remove(key)
153 .whenComplete((r, e) -> timer.stop(e));
154 }
155
156 @Override
157 public CompletableFuture<Void> clear() {
158 final MeteringAgent.Context timer = monitor.startTimer(CLEAR);
159 return super.clear()
160 .whenComplete((r, e) -> timer.stop(e));
161 }
162
163 @Override
164 public CompletableFuture<Set<K>> keySet() {
165 final MeteringAgent.Context timer = monitor.startTimer(KEY_SET);
166 return super.keySet()
167 .whenComplete((r, e) -> timer.stop(e));
168 }
169
170 @Override
171 public CompletableFuture<Collection<Versioned<V>>> values() {
172 final MeteringAgent.Context timer = monitor.startTimer(VALUES);
173 return super.values()
174 .whenComplete((r, e) -> timer.stop(e));
175 }
176
177 @Override
178 public CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet() {
179 final MeteringAgent.Context timer = monitor.startTimer(ENTRY_SET);
180 return super.entrySet()
181 .whenComplete((r, e) -> timer.stop(e));
182 }
183
184 @Override
185 public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
186 final MeteringAgent.Context timer = monitor.startTimer(PUT_IF_ABSENT);
187 return super.putIfAbsent(key, value)
188 .whenComplete((r, e) -> timer.stop(e));
189 }
190
191 @Override
192 public CompletableFuture<Boolean> remove(K key, V value) {
193 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
194 return super.remove(key, value)
195 .whenComplete((r, e) -> timer.stop(e));
196
197 }
198
199 @Override
200 public CompletableFuture<Boolean> remove(K key, long version) {
201 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
202 return super.remove(key, version)
203 .whenComplete((r, e) -> timer.stop(e));
204 }
205
206 @Override
207 public CompletableFuture<Versioned<V>> replace(K key, V value) {
208 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
209 return super.replace(key, value)
210 .whenComplete((r, e) -> timer.stop(e));
211 }
212
213 @Override
214 public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
215 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
216 return super.replace(key, oldValue, newValue)
217 .whenComplete((r, e) -> timer.stop(e));
218 }
219
220 @Override
221 public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
222 final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
223 return super.replace(key, oldVersion, newValue)
224 .whenComplete((r, e) -> timer.stop(e));
225 }
226
227 @Override
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700228 public CompletableFuture<Void> addListener(MapEventListener<K, V> listener, Executor executor) {
Madan Jampani10073672016-01-21 19:13:59 -0800229 final MeteringAgent.Context timer = monitor.startTimer(ADD_LISTENER);
230 synchronized (listeners) {
231 InternalMeteredMapEventListener meteredListener =
232 listeners.computeIfAbsent(listener, k -> new InternalMeteredMapEventListener(listener));
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700233 return super.addListener(meteredListener, executor)
Madan Jampani10073672016-01-21 19:13:59 -0800234 .whenComplete((r, e) -> timer.stop(e));
235 }
236 }
237
238 @Override
239 public CompletableFuture<Void> removeListener(MapEventListener<K, V> listener) {
240 final MeteringAgent.Context timer = monitor.startTimer(REMOVE_LISTENER);
241 InternalMeteredMapEventListener meteredListener = listeners.remove(listener);
242 if (meteredListener != null) {
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700243 return super.removeListener(meteredListener)
Madan Jampani10073672016-01-21 19:13:59 -0800244 .whenComplete((r, e) -> timer.stop(e));
245 } else {
246 timer.stop(null);
247 return CompletableFuture.completedFuture(null);
248 }
249 }
250
Madan Jampani542d9e22016-04-05 15:39:55 -0700251 @Override
252 public CompletableFuture<Boolean> prepare(MapTransaction<K, V> transaction) {
253 final MeteringAgent.Context timer = monitor.startTimer(PREPARE);
254 return super.prepare(transaction)
255 .whenComplete((r, e) -> timer.stop(e));
256 }
257
258 @Override
259 public CompletableFuture<Void> commit(TransactionId transactionId) {
260 final MeteringAgent.Context timer = monitor.startTimer(COMMIT);
261 return super.commit(transactionId)
262 .whenComplete((r, e) -> timer.stop(e));
263 }
264
265 @Override
266 public CompletableFuture<Void> rollback(TransactionId transactionId) {
267 final MeteringAgent.Context timer = monitor.startTimer(ROLLBACK);
268 return super.rollback(transactionId)
269 .whenComplete((r, e) -> timer.stop(e));
270 }
271
272 @Override
273 public CompletableFuture<Boolean> prepareAndCommit(MapTransaction<K, V> transaction) {
274 final MeteringAgent.Context timer = monitor.startTimer(PREPARE_AND_COMMIT);
275 return super.prepareAndCommit(transaction)
276 .whenComplete((r, e) -> timer.stop(e));
277 }
278
Madan Jampani10073672016-01-21 19:13:59 -0800279 private class InternalMeteredMapEventListener implements MapEventListener<K, V> {
280
281 private final MapEventListener<K, V> listener;
282
283 InternalMeteredMapEventListener(MapEventListener<K, V> listener) {
284 this.listener = listener;
285 }
286
287 @Override
288 public void event(MapEvent<K, V> event) {
289 final MeteringAgent.Context timer = monitor.startTimer(NOTIFY_LISTENER);
290 try {
291 listener.event(event);
292 timer.stop(null);
293 } catch (Exception e) {
294 timer.stop(e);
295 Throwables.propagate(e);
296 }
297 }
298 }
299}