blob: b700c95dbca7c6141e5a74567b94b8313638c1f3 [file] [log] [blame]
yoonseon94672112017-01-31 13:46:21 -08001/*
2 * Copyright 2017-present Open Networking Foundation
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.incubator.store.virtual.impl;
18
19import com.google.common.collect.Collections2;
20import com.google.common.collect.Maps;
yoonseon94672112017-01-31 13:46:21 -080021import org.onosproject.cluster.ClusterService;
22import org.onosproject.cluster.NodeId;
23import org.onosproject.incubator.net.virtual.NetworkId;
24import org.onosproject.incubator.net.virtual.VirtualNetworkMeterStore;
25import org.onosproject.incubator.store.meter.impl.MeterData;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.meter.DefaultMeter;
28import org.onosproject.net.meter.Meter;
29import org.onosproject.net.meter.MeterEvent;
30import org.onosproject.net.meter.MeterFailReason;
31import org.onosproject.net.meter.MeterFeatures;
32import org.onosproject.net.meter.MeterFeaturesKey;
33import org.onosproject.net.meter.MeterKey;
34import org.onosproject.net.meter.MeterOperation;
35import org.onosproject.net.meter.MeterStoreDelegate;
36import org.onosproject.net.meter.MeterStoreResult;
37import org.onosproject.store.service.StorageException;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070038import org.osgi.service.component.annotations.Activate;
39import org.osgi.service.component.annotations.Component;
40import org.osgi.service.component.annotations.Deactivate;
41import org.osgi.service.component.annotations.Reference;
42import org.osgi.service.component.annotations.ReferenceCardinality;
yoonseon94672112017-01-31 13:46:21 -080043import org.slf4j.Logger;
44
45import java.util.Collection;
46import java.util.concurrent.CompletableFuture;
47import java.util.concurrent.ConcurrentHashMap;
48import java.util.concurrent.ConcurrentMap;
49
50import static org.onosproject.net.meter.MeterFailReason.TIMEOUT;
51import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * Implementation of the virtual meter store for a single instance.
55 */
56//TODO: support distributed meter store for virtual networks
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057@Component(immediate = true, service = VirtualNetworkMeterStore.class)
yoonseon94672112017-01-31 13:46:21 -080058public class SimpleVirtualMeterStore
59 extends AbstractVirtualStore<MeterEvent, MeterStoreDelegate>
60 implements VirtualNetworkMeterStore {
61
62 private Logger log = getLogger(getClass());
63
Ray Milkeyd84f89b2018-08-17 14:54:17 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY)
yoonseon94672112017-01-31 13:46:21 -080065 protected ClusterService clusterService;
66
67 private ConcurrentMap<NetworkId, ConcurrentMap<MeterKey, MeterData>> meterMap =
68 Maps.newConcurrentMap();
69
70 private NodeId local;
71
72 private ConcurrentMap<NetworkId, ConcurrentMap<MeterFeaturesKey, MeterFeatures>>
73 meterFeatureMap = Maps.newConcurrentMap();
74
75 private ConcurrentMap<NetworkId,
76 ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>>> futuresMap =
77 Maps.newConcurrentMap();
78
79 @Activate
80 public void activate() {
81 log.info("Started");
82 local = clusterService.getLocalNode().id();
83 }
84
85 @Deactivate
86 public void deactivate() {
87 log.info("Stopped");
88 }
89
90 private ConcurrentMap<MeterKey, MeterData> getMetersByNetwork(NetworkId networkId) {
91 meterMap.computeIfAbsent(networkId, m -> new ConcurrentHashMap<>());
92 return meterMap.get(networkId);
93 }
94
95 private ConcurrentMap<MeterFeaturesKey, MeterFeatures>
96 getMeterFeaturesByNetwork(NetworkId networkId) {
97 meterFeatureMap.computeIfAbsent(networkId, f -> new ConcurrentHashMap<>());
98 return meterFeatureMap.get(networkId);
99 }
100
101 private ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>>
102 getFuturesByNetwork(NetworkId networkId) {
103 futuresMap.computeIfAbsent(networkId, f -> new ConcurrentHashMap<>());
104 return futuresMap.get(networkId);
105 }
106
107 @Override
108 public CompletableFuture<MeterStoreResult> storeMeter(NetworkId networkId, Meter meter) {
109
110 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
111
112 ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>> futures =
113 getFuturesByNetwork(networkId);
114
115 CompletableFuture<MeterStoreResult> future = new CompletableFuture<>();
116 MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
117 futures.put(key, future);
118 MeterData data = new MeterData(meter, null, local);
119
120 try {
121 meters.put(key, data);
122 } catch (StorageException e) {
123 future.completeExceptionally(e);
124 }
125
126 return future;
127 }
128
129 @Override
130 public CompletableFuture<MeterStoreResult> deleteMeter(NetworkId networkId, Meter meter) {
131 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
132
133 ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>> futures =
134 getFuturesByNetwork(networkId);
135
136 CompletableFuture<MeterStoreResult> future = new CompletableFuture<>();
137 MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
138 futures.put(key, future);
139
140 MeterData data = new MeterData(meter, null, local);
141
142 // update the state of the meter. It will be pruned by observing
143 // that it has been removed from the dataplane.
144 try {
145 if (meters.computeIfPresent(key, (k, v) -> data) == null) {
146 future.complete(MeterStoreResult.success());
147 }
148 } catch (StorageException e) {
149 future.completeExceptionally(e);
150 }
151
152 return future;
153 }
154
155 @Override
156 public MeterStoreResult storeMeterFeatures(NetworkId networkId, MeterFeatures meterfeatures) {
157 ConcurrentMap<MeterFeaturesKey, MeterFeatures> meterFeatures
158 = getMeterFeaturesByNetwork(networkId);
159
160 MeterStoreResult result = MeterStoreResult.success();
161 MeterFeaturesKey key = MeterFeaturesKey.key(meterfeatures.deviceId());
162 try {
163 meterFeatures.putIfAbsent(key, meterfeatures);
164 } catch (StorageException e) {
165 result = MeterStoreResult.fail(TIMEOUT);
166 }
167 return result;
168 }
169
170 @Override
171 public MeterStoreResult deleteMeterFeatures(NetworkId networkId, DeviceId deviceId) {
172 ConcurrentMap<MeterFeaturesKey, MeterFeatures> meterFeatures
173 = getMeterFeaturesByNetwork(networkId);
174
175 MeterStoreResult result = MeterStoreResult.success();
176 MeterFeaturesKey key = MeterFeaturesKey.key(deviceId);
177 try {
178 meterFeatures.remove(key);
179 } catch (StorageException e) {
180 result = MeterStoreResult.fail(TIMEOUT);
181 }
182 return result;
183 }
184
185 @Override
186 public CompletableFuture<MeterStoreResult> updateMeter(NetworkId networkId, Meter meter) {
187 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
188 ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>> futures =
189 getFuturesByNetwork(networkId);
190
191 CompletableFuture<MeterStoreResult> future = new CompletableFuture<>();
192 MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
193 futures.put(key, future);
194
195 MeterData data = new MeterData(meter, null, local);
196 try {
197 if (meters.computeIfPresent(key, (k, v) -> data) == null) {
198 future.complete(MeterStoreResult.fail(MeterFailReason.INVALID_METER));
199 }
200 } catch (StorageException e) {
201 future.completeExceptionally(e);
202 }
203 return future;
204 }
205
206 @Override
207 public void updateMeterState(NetworkId networkId, Meter meter) {
208 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
209
210 MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
211 meters.computeIfPresent(key, (k, v) -> {
212 DefaultMeter m = (DefaultMeter) v.meter();
213 m.setState(meter.state());
214 m.setProcessedPackets(meter.packetsSeen());
215 m.setProcessedBytes(meter.bytesSeen());
216 m.setLife(meter.life());
217 // TODO: Prune if drops to zero.
218 m.setReferenceCount(meter.referenceCount());
219 return new MeterData(m, null, v.origin());
220 });
221 }
222
223 @Override
224 public Meter getMeter(NetworkId networkId, MeterKey key) {
225 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
226
227 MeterData data = meters.get(key);
228 return data == null ? null : data.meter();
229 }
230
231 @Override
232 public Collection<Meter> getAllMeters(NetworkId networkId) {
233 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
234
235 return Collections2.transform(meters.values(), MeterData::meter);
236 }
237
238 @Override
239 public void failedMeter(NetworkId networkId, MeterOperation op, MeterFailReason reason) {
240 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
241
242 MeterKey key = MeterKey.key(op.meter().deviceId(), op.meter().id());
243 meters.computeIfPresent(key, (k, v) ->
244 new MeterData(v.meter(), reason, v.origin()));
245 }
246
247 @Override
248 public void deleteMeterNow(NetworkId networkId, Meter m) {
249 ConcurrentMap<MeterKey, MeterData> meters = getMetersByNetwork(networkId);
250 ConcurrentMap<MeterKey, CompletableFuture<MeterStoreResult>> futures =
251 getFuturesByNetwork(networkId);
252
253 MeterKey key = MeterKey.key(m.deviceId(), m.id());
254 futures.remove(key);
255 meters.remove(key);
256 }
257
258 @Override
259 public long getMaxMeters(NetworkId networkId, MeterFeaturesKey key) {
260 ConcurrentMap<MeterFeaturesKey, MeterFeatures> meterFeatures
261 = getMeterFeaturesByNetwork(networkId);
262
263 MeterFeatures features = meterFeatures.get(key);
264 return features == null ? 0L : features.maxMeter();
265 }
266}