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