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