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