[VOL-3260] Purging all meter state on OLT delete
Change-Id: I6323779d584b341d33cc91231197504b80a91fc4
diff --git a/app/src/main/java/org/opencord/olt/impl/OltMeterService.java b/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
index 3cbdbd7..fc56066 100644
--- a/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
+++ b/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
@@ -42,7 +42,6 @@
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.opencord.olt.internalapi.AccessDeviceMeterService;
-import org.opencord.olt.internalapi.DeviceBandwidthProfile;
import org.opencord.sadis.BandwidthProfileInformation;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
@@ -56,13 +55,14 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -100,8 +100,6 @@
protected boolean deleteMeters = true;
- ConsistentMultimap<String, MeterKey> bpInfoToMeter;
-
private ApplicationId appId;
private static final String APP_NAME = "org.opencord.olt";
@@ -111,7 +109,9 @@
protected ExecutorService eventExecutor;
- private Set<DeviceBandwidthProfile> pendingMeters;
+ private Map<DeviceId, Set<BandwidthProfileInformation>> pendingMeters;
+ private Map<DeviceId, Map<MeterKey, AtomicInteger>> pendingRemoveMeters;
+ ConsistentMultimap<String, MeterKey> bpInfoToMeter;
@Activate
public void activate(ComponentContext context) {
@@ -133,7 +133,8 @@
meterService.addListener(meterListener);
componentConfigService.registerProperties(getClass());
- pendingMeters = ConcurrentHashMap.newKeySet();
+ pendingMeters = Maps.newConcurrentMap();
+ pendingRemoveMeters = Maps.newConcurrentMap();
log.info("Olt Meter service started");
}
@@ -250,26 +251,54 @@
}
@Override
- public void addToPendingMeters(DeviceBandwidthProfile deviceBandwidthProfile) {
- pendingMeters.add(deviceBandwidthProfile);
+ public void addToPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
+ if (deviceId == null) {
+ return;
+ }
+ pendingMeters.compute(deviceId, (id, bwps) -> {
+ if (bwps == null) {
+ bwps = new HashSet<>();
+ }
+ bwps.add(bwpInfo);
+ return bwps;
+ });
}
@Override
- public void removeFromPendingMeters(DeviceBandwidthProfile deviceBandwidthProfile) {
- pendingMeters.remove(deviceBandwidthProfile);
+ public void removeFromPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
+ if (deviceId == null) {
+ return;
+ }
+ pendingMeters.computeIfPresent(deviceId, (id, bwps) -> {
+ bwps.remove(bwpInfo);
+ return bwps;
+ });
}
@Override
- public boolean isMeterPending(DeviceBandwidthProfile deviceBandwidthProfile) {
- return pendingMeters.contains(deviceBandwidthProfile);
+ public boolean isMeterPending(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
+ if (!pendingMeters.containsKey(deviceId)) {
+ return false;
+ }
+ return pendingMeters.get(deviceId).contains(bwpInfo);
}
@Override
public void clearMeters(DeviceId deviceId) {
log.debug("Removing all meters for device {}", deviceId);
+ clearDeviceState(deviceId);
meterService.purgeMeters(deviceId);
}
+ @Override
+ public void clearDeviceState(DeviceId deviceId) {
+ log.info("Clearing local device state for {}", deviceId);
+ pendingRemoveMeters.remove(deviceId);
+ removeMetersFromBpMapping(deviceId);
+ //Following call handles cornercase of OLT delete during meter provisioning
+ pendingMeters.remove(deviceId);
+ }
+
private List<Band> createMeterBands(BandwidthProfileInformation bpInfo) {
List<Band> meterBands = new ArrayList<>();
@@ -288,9 +317,23 @@
.build();
}
- private class InternalMeterListener implements MeterListener {
+ private void removeMeterFromBpMapping(MeterKey meterKey) {
+ List<Map.Entry<String, MeterKey>> meters = bpInfoToMeter.stream()
+ .filter(e -> e.getValue().equals(meterKey))
+ .collect(Collectors.toList());
- Map<MeterKey, AtomicInteger> pendingRemoveMeters = Maps.newConcurrentMap();
+ meters.forEach(e -> bpInfoToMeter.remove(e.getKey(), e.getValue()));
+ }
+
+ private void removeMetersFromBpMapping(DeviceId deviceId) {
+ List<Map.Entry<String, MeterKey>> meters = bpInfoToMeter.stream()
+ .filter(e -> e.getValue().deviceId().equals(deviceId))
+ .collect(Collectors.toList());
+
+ meters.forEach(e -> bpInfoToMeter.remove(e.getKey(), e.getValue()));
+ }
+
+ private class InternalMeterListener implements MeterListener {
@Override
public void event(MeterEvent meterEvent) {
@@ -302,33 +345,50 @@
}
MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
if (deleteMeters && MeterEvent.Type.METER_REFERENCE_COUNT_ZERO.equals(meterEvent.type())) {
- log.info("Zero Count Meter Event is received. Meter is {}", meter.id());
- incrementMeterCount(key);
+ log.info("Zero Count Meter Event is received. Meter is {} on {}",
+ meter.id(), meter.deviceId());
+ incrementMeterCount(meter.deviceId(), key);
- if (appId.equals(meter.appId()) && pendingRemoveMeters.get(key).get() == 3) {
- log.info("Deleting unreferenced, no longer programmed Meter {}", meter.id());
+ if (appId.equals(meter.appId()) && pendingRemoveMeters.get(meter.deviceId())
+ .get(key).get() == 3) {
+ log.info("Deleting unreferenced, no longer programmed Meter {} on {}",
+ meter.id(), meter.deviceId());
deleteMeter(meter.deviceId(), meter.id());
}
}
if (MeterEvent.Type.METER_REMOVED.equals(meterEvent.type())) {
- log.info("Meter Removed Event is received for {}", meter.id());
- pendingRemoveMeters.remove(key);
+ log.info("Meter Removed Event is received for {} on {}",
+ meter.id(), meter.deviceId());
+ pendingRemoveMeters.computeIfPresent(meter.deviceId(),
+ (id, meters) -> {
+ if (meters.get(key) == null) {
+ log.info("Meters is not pending " +
+ "{} on {}", key, id);
+ return meters;
+ }
+ meters.remove(key);
+ return meters;
+ });
removeMeterFromBpMapping(key);
}
});
}
- private void incrementMeterCount(MeterKey key) {
+ private void incrementMeterCount(DeviceId deviceId, MeterKey key) {
if (key == null) {
return;
}
- pendingRemoveMeters.compute(key,
- (k, v) -> {
- if (v == null) {
- return new AtomicInteger(1);
+ pendingRemoveMeters.compute(deviceId,
+ (id, meters) -> {
+ if (meters == null) {
+ meters = new HashMap<>();
+
}
- v.addAndGet(1);
- return v;
+ if (meters.get(key) == null) {
+ meters.put(key, new AtomicInteger(1));
+ }
+ meters.get(key).addAndGet(1);
+ return meters;
});
}
@@ -346,13 +406,5 @@
meterService.withdraw(meterRequest, meterId);
}
}
-
- private void removeMeterFromBpMapping(MeterKey meterKey) {
- List<Map.Entry<String, MeterKey>> meters = bpInfoToMeter.stream()
- .filter(e -> e.getValue().equals(meterKey))
- .collect(Collectors.toList());
-
- meters.forEach(e -> bpInfoToMeter.remove(e.getKey(), e.getValue()));
- }
}
}