[ONOS-5599] Store meter features into MeterStore

Change-Id: I22f7366b87cad6fc706b6ff7b0ccff1a0e85ad6a
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
index be7de21..b681c27 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
@@ -26,18 +26,22 @@
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.meter.Band;
 import org.onosproject.net.meter.DefaultBand;
 import org.onosproject.net.meter.DefaultMeter;
 import org.onosproject.net.meter.Meter;
 import org.onosproject.net.meter.MeterEvent;
 import org.onosproject.net.meter.MeterFailReason;
+import org.onosproject.net.meter.MeterFeatures;
+import org.onosproject.net.meter.MeterFeaturesKey;
 import org.onosproject.net.meter.MeterKey;
 import org.onosproject.net.meter.MeterOperation;
 import org.onosproject.net.meter.MeterState;
 import org.onosproject.net.meter.MeterStore;
 import org.onosproject.net.meter.MeterStoreDelegate;
 import org.onosproject.net.meter.MeterStoreResult;
+import org.onosproject.net.meter.DefaultMeterFeatures;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.ConsistentMap;
@@ -54,6 +58,7 @@
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 
+import static org.onosproject.net.meter.MeterFailReason.TIMEOUT;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -68,6 +73,7 @@
     private Logger log = getLogger(getClass());
 
     private static final String METERSTORE = "onos-meter-store";
+    private static final String METERFEATURESSTORE = "onos-meter-features-store";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private StorageService storageService;
@@ -81,6 +87,8 @@
     private ConsistentMap<MeterKey, MeterData> meters;
     private NodeId local;
 
+    private ConsistentMap<MeterFeaturesKey, MeterFeatures> meterFeatures;
+
     private MapEventListener<MeterKey, MeterData> mapListener = new InternalMapEventListener();
 
     private Map<MeterKey, CompletableFuture<MeterStoreResult>> futures =
@@ -106,6 +114,16 @@
 
         meters.addListener(mapListener);
 
+        meterFeatures = storageService.<MeterFeaturesKey, MeterFeatures>consistentMapBuilder()
+                .withName(METERFEATURESSTORE)
+                .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API),
+                        MeterFeaturesKey.class,
+                        MeterFeatures.class,
+                        DefaultMeterFeatures.class,
+                        Band.Type.class,
+                        Meter.Unit.class,
+                        MeterFailReason.class)).build();
+
         log.info("Started");
     }
 
@@ -157,6 +175,30 @@
     }
 
     @Override
+    public MeterStoreResult storeMeterFeatures(MeterFeatures meterfeatures) {
+        MeterStoreResult result = MeterStoreResult.success();
+        MeterFeaturesKey key = MeterFeaturesKey.key(meterfeatures.deviceId());
+        try {
+            meterFeatures.putIfAbsent(key, meterfeatures);
+        } catch (StorageException e) {
+            result = MeterStoreResult.fail(TIMEOUT);
+        }
+        return result;
+    }
+
+    @Override
+    public MeterStoreResult deleteMeterFeatures(DeviceId deviceId) {
+        MeterStoreResult result = MeterStoreResult.success();
+        MeterFeaturesKey key = MeterFeaturesKey.key(deviceId);
+        try {
+            meterFeatures.remove(key);
+        } catch (StorageException e) {
+            result = MeterStoreResult.fail(TIMEOUT);
+        }
+        return result;
+    }
+
+    @Override
     public CompletableFuture<MeterStoreResult> updateMeter(Meter meter) {
         CompletableFuture<MeterStoreResult> future = new CompletableFuture<>();
         MeterKey key = MeterKey.key(meter.deviceId(), meter.id());
@@ -214,6 +256,12 @@
         meters.remove(key);
     }
 
+    @Override
+    public long getMaxMeters(MeterFeaturesKey key) {
+        MeterFeatures features = Versioned.valueOrElse(meterFeatures.get(key), null);
+        return features == null ? 0L : features.maxMeter();
+    }
+
     private class InternalMapEventListener implements MapEventListener<MeterKey, MeterData> {
         @Override
         public void event(MapEvent<MeterKey, MeterData> event) {