HC2VPP-205 / HC2VPP-25 - Sub interface caching improvement 77/7877/16
authorJan Srnicek <[email protected]>
Tue, 15 Aug 2017 08:15:06 +0000 (10:15 +0200)
committerMarek Gradzki <[email protected]>
Wed, 16 Aug 2017 05:37:09 +0000 (05:37 +0000)
Improves dumping mechanism for sub interfaces in a way
that if full dump was already performed,
it will be used from cache instead of new dump call.
Also prevents creating dump dto's if not necessary

Change-Id: I46a305ec1b325c2d949bff9e2b151752ccd508b6
Signed-off-by: Jan Srnicek <[email protected]>
32 files changed:
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/V3poModule.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterconnectionReadUtils.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/L2Customizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2Customizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java [new file with mode: 0644]

index fb89110..b128939 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.hc2vpp.v3po;
 
 import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
@@ -26,6 +27,8 @@ import io.fd.hc2vpp.v3po.factory.L2HoneycombWriterFactory;
 import io.fd.hc2vpp.v3po.factory.L2StateHoneycombReaderFactory;
 import io.fd.hc2vpp.v3po.factory.SubinterfaceAugmentationWriterFactory;
 import io.fd.hc2vpp.v3po.factory.SubinterfaceStateAugmentationReaderFactory;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManagerProvider;
 import io.fd.hc2vpp.v3po.notification.InterfaceChangeNotificationProducerProvider;
 import io.fd.honeycomb.notification.ManagedNotificationProducer;
 import io.fd.honeycomb.translate.read.ReaderFactory;
@@ -50,6 +53,8 @@ public class V3poModule extends AbstractModule {
                 .annotatedWith(Names.named("bridge-domain-context"))
                 .toInstance(new NamingContext("bridge-domain-", "bridge-domain-context"));
 
+        bind(InterfaceCacheDumpManager.class).toProvider(InterfaceCacheDumpManagerProvider.class).in(Singleton.class);
+
         // Context utility for deleted interfaces
         bind(DisabledInterfacesManager.class).toInstance(new DisabledInterfacesManager());
 
index 44390b4..eaacb13 100644 (file)
@@ -30,6 +30,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.TapCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VhostUserCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanGpeCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.hc2vpp.v3po.interfacesstate.pbb.PbbRewriteStateCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.span.InterfaceMirroredInterfacesCustomizer;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
@@ -65,6 +66,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
     private final NamingContext ifcNamingCtx;
     private final NamingContext bdNamingCtx;
     private final DisabledInterfacesManager ifcDisableContext;
+    private final InterfaceCacheDumpManager ifaceDumpManager;
     private final FutureJVppCore jvpp;
 
     static final InstanceIdentifier<InterfacesState> IFC_STATE_ID =
@@ -75,11 +77,13 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
     public InterfacesStateReaderFactory(final FutureJVppCore jvpp,
                                         @Named("interface-context") final NamingContext ifcNamingCtx,
                                         @Named("bridge-domain-context") final NamingContext bdNamingCtx,
-                                        final DisabledInterfacesManager ifcDisableContext) {
+                                        final DisabledInterfacesManager ifcDisableContext,
+                                        final InterfaceCacheDumpManager ifaceDumpManager) {
         this.jvpp = jvpp;
         this.ifcNamingCtx = ifcNamingCtx;
         this.bdNamingCtx = bdNamingCtx;
         this.ifcDisableContext = ifcDisableContext;
+        this.ifaceDumpManager = ifaceDumpManager;
     }
 
     @Override
@@ -87,7 +91,8 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         // InterfacesState(Structural)
         registry.addStructuralReader(IFC_STATE_ID, InterfacesStateBuilder.class);
         //  Interface
-        registry.add(new GenericInitListReader<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingCtx, ifcDisableContext)));
+        registry.add(new GenericInitListReader<>(IFC_ID,
+                new InterfaceCustomizer(ifcNamingCtx, ifcDisableContext, ifaceDumpManager)));
 
         // v3po.yang
         initVppIfcAugmentationReaders(registry, IFC_ID);
@@ -104,25 +109,28 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         registry.addStructuralReader(vppIfcAugId, VppInterfaceStateAugmentationBuilder.class);
         //    Ethernet
         registry.add(new GenericInitReader<>(vppIfcAugId.child(Ethernet.class),
-            new EthernetCustomizer(jvpp, ifcNamingCtx)));
+                new EthernetCustomizer(ifaceDumpManager)));
         //    Routing
         registry.add(new GenericInitReader<>(vppIfcAugId.child(Routing.class),
-            new InterfaceRoutingCustomizer(jvpp, ifcNamingCtx)));
+                new InterfaceRoutingCustomizer(jvpp, ifcNamingCtx)));
         //    Tap
-        registry.add(new GenericInitReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcNamingCtx)));
+        registry.add(new GenericInitReader<>(vppIfcAugId.child(Tap.class),
+                new TapCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    VhostUser
         registry.add(new GenericInitReader<>(vppIfcAugId.child(VhostUser.class),
-                        new VhostUserCustomizer(jvpp, ifcNamingCtx)));
+                new VhostUserCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    Vxlan
-        registry.add(new GenericInitReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcNamingCtx)));
+        registry.add(new GenericInitReader<>(vppIfcAugId.child(Vxlan.class),
+                new VxlanCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    VxlanGpe
         registry.add(new GenericInitReader<>(vppIfcAugId.child(VxlanGpe.class),
-                        new VxlanGpeCustomizer(jvpp, ifcNamingCtx)));
+                new VxlanGpeCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    Gre
-        registry.add(new GenericInitReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcNamingCtx)));
+        registry.add(new GenericInitReader<>(vppIfcAugId.child(Gre.class),
+                new GreCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    L2
         registry.add(new GenericInitReader<>(vppIfcAugId.child(L2.class),
-                        new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx)));
+                new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx, ifaceDumpManager)));
         // Span
         final InstanceIdentifier<Span> spanId = vppIfcAugId.child(Span.class);
         registry.addStructuralReader(spanId, SpanBuilder.class);
@@ -141,5 +149,4 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         registry.add(new GenericReader<>(ifcId.augmentation(PbbRewriteStateInterfaceAugmentation.class).child(
                 PbbRewriteState.class), new PbbRewriteStateCustomizer(jvpp)));
     }
-
 }
index de91a06..a041bc8 100644 (file)
@@ -24,6 +24,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.RewriteCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceL2Customizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceRoutingCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.hc2vpp.v3po.interfacesstate.span.SubInterfaceMirroredInterfacesCustomizer;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
 import io.fd.honeycomb.translate.impl.read.GenericInitReader;
@@ -36,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinter
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.VppSubinterfaceSpanStateAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.interfaces.state._interface.sub.interfaces.sub._interface.SpanState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.interfaces.state._interface.sub.interfaces.sub._interface.SpanStateBuilder;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.span.state.attributes.MirroredInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.SubinterfaceStateAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.SubinterfaceStateAugmentationBuilder;
@@ -45,12 +45,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.match.attributes.match.type.vlan.tagged.VlanTagged;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Tags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.tags.Tag;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.routing.attributes.Routing;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -59,21 +58,24 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF
     private final FutureJVppCore jvpp;
     private final NamingContext ifcCtx;
     private final NamingContext bdCtx;
+    private final InterfaceCacheDumpManager ifaceDumpManager;
 
     @Inject
     public SubinterfaceStateAugmentationReaderFactory(final FutureJVppCore jvpp,
                                                       @Named("interface-context") final NamingContext ifcCtx,
-                                                      @Named("bridge-domain-context") final NamingContext bdCtx) {
+                                                      @Named("bridge-domain-context") final NamingContext bdCtx,
+                                                      final InterfaceCacheDumpManager ifaceDumpManager) {
         this.jvpp = jvpp;
         this.ifcCtx = ifcCtx;
         this.bdCtx = bdCtx;
+        this.ifaceDumpManager = ifaceDumpManager;
     }
 
     @Override
     public void init(final ModifiableReaderRegistryBuilder registry) {
         // SubinterfaceStateAugmentation(Structural)
         final InstanceIdentifier<SubinterfaceStateAugmentation> subIfcAugId =
-            InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class);
+                InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class);
         registry.addStructuralReader(subIfcAugId, SubinterfaceStateAugmentationBuilder.class);
         //  SubInterfaces(Structural)
         final InstanceIdentifier<SubInterfaces> subIfcsId = subIfcAugId.child(SubInterfaces.class);
@@ -81,26 +83,30 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF
         //   SubInterface(Subtree)
         final InstanceIdentifier<SubInterface> subIfcId = subIfcsId.child(SubInterface.class);
         registry.subtreeAdd(Sets.newHashSet(
-            InstanceIdentifier.create(SubInterface.class).child(Tags.class),
-            InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class),
-            InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class),
-            InstanceIdentifier.create(SubInterface.class).child(Match.class),
-            InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)),
-            new GenericInitListReader<>(subIfcId, new SubInterfaceCustomizer(jvpp, ifcCtx)));
+                InstanceIdentifier.create(SubInterface.class).child(Tags.class),
+                InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class),
+                InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class),
+                InstanceIdentifier.create(SubInterface.class).child(Match.class),
+                InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)),
+                new GenericInitListReader<>(subIfcId,
+                        new SubInterfaceCustomizer(jvpp, ifcCtx, ifaceDumpManager)));
         //    L2
         final InstanceIdentifier<L2> l2Id = subIfcId.child(L2.class);
-        registry.add(new GenericInitReader<>(l2Id, new SubInterfaceL2Customizer(jvpp, ifcCtx, bdCtx)));
+        registry.add(new GenericInitReader<>(l2Id,
+                new SubInterfaceL2Customizer(jvpp, ifcCtx, bdCtx, ifaceDumpManager)));
         //     Rewrite(Subtree)
         registry.subtreeAdd(Sets.newHashSet(
-            InstanceIdentifier.create(Rewrite.class).child(PushTags.class),
-            InstanceIdentifier.create(Rewrite.class).child(PushTags.class)
-                .child(
-                    org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)),
-            new GenericReader<>(l2Id.child(Rewrite.class), new RewriteCustomizer(jvpp, ifcCtx)));
+                InstanceIdentifier.create(Rewrite.class).child(PushTags.class),
+                InstanceIdentifier.create(Rewrite.class).child(PushTags.class)
+                        .child(
+                                org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)),
+                new GenericReader<>(l2Id.child(Rewrite.class),
+                        new RewriteCustomizer(ifaceDumpManager)));
         final InstanceIdentifier<Routing> routingId = subIfcId.child(Routing.class);
         registry.add(new GenericReader<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcCtx)));
 
-        final InstanceIdentifier<VppSubinterfaceSpanStateAugmentation> spanStateAugId = subIfcId.augmentation(VppSubinterfaceSpanStateAugmentation.class);
+        final InstanceIdentifier<VppSubinterfaceSpanStateAugmentation> spanStateAugId =
+                subIfcId.augmentation(VppSubinterfaceSpanStateAugmentation.class);
         registry.addStructuralReader(spanStateAugId, VppSubinterfaceSpanStateAugmentationBuilder.class);
 
         final InstanceIdentifier<SpanState> spanStateId = spanStateAugId
@@ -108,6 +114,7 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF
         registry.addStructuralReader(spanStateId, SpanStateBuilder.class);
 
         final InstanceIdentifier<MirroredInterfaces> mirroredInterfacesId = spanStateId.child(MirroredInterfaces.class);
-        registry.add(new GenericInitReader<>(mirroredInterfacesId, new SubInterfaceMirroredInterfacesCustomizer(jvpp, ifcCtx)));
+        registry.add(new GenericInitReader<>(mirroredInterfacesId,
+                new SubInterfaceMirroredInterfacesCustomizer(jvpp, ifcCtx)));
     }
 }
index 1afdbcd..8bb01a9 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -35,20 +33,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
-public class EthernetCustomizer extends FutureJVppCustomizer
+public class EthernetCustomizer
         implements InitializingReaderCustomizer<Ethernet, EthernetBuilder>, InterfaceDataTranslator {
 
-    private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class);
-    private NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public EthernetCustomizer(@Nonnull final FutureJVppCore jvpp,
-                              @Nonnull final NamingContext interfaceContext) {
-        super(jvpp);
-        this.interfaceContext = interfaceContext;
+    public EthernetCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) {
+        this.dumpManager = dumpManager;
     }
 
     @Override
@@ -69,8 +62,7 @@ public class EthernetCustomizer extends FutureJVppCustomizer
                                       @Nonnull final ReadContext ctx) throws ReadFailedException {
 
         final InterfaceKey key = id.firstKeyOf(Interface.class);
-        final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(),
-                interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG);
+        final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, key.getName());
 
         if (iface.linkMtu != 0) {
             builder.setMtu((int) iface.linkMtu);
index 3d1782a..ee54a11 100644 (file)
@@ -18,13 +18,14 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.vpp.jvpp.core.dto.GreTunnelDetails;
 import io.fd.vpp.jvpp.core.dto.GreTunnelDetailsReplyDump;
 import io.fd.vpp.jvpp.core.dto.GreTunnelDump;
@@ -54,11 +55,15 @@ public class GreCustomizer extends FutureJVppCustomizer
         implements InitializingReaderCustomizer<Gre, GreBuilder>, InterfaceDataTranslator {
 
     private static final Logger LOG = LoggerFactory.getLogger(GreCustomizer.class);
-    private NamingContext interfaceContext;
+    private final NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public GreCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+    public GreCustomizer(@Nonnull final FutureJVppCore jvpp,
+                         @Nonnull final NamingContext interfaceContext,
+                         @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
     }
 
     @Override
@@ -79,7 +84,7 @@ public class GreCustomizer extends FutureJVppCustomizer
                                       @Nonnull final ReadContext ctx) throws ReadFailedException {
         final InterfaceKey key = id.firstKeyOf(Interface.class);
         final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, GreTunnel.class, LOG)) {
+        if (!isInterfaceOfType(dumpManager, id, ctx, GreTunnel.class)) {
             return;
         }
 
index 5c3072e..a255313 100644 (file)
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails;
@@ -49,13 +50,16 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator {
     private final FutureJVppCore futureJVppCore;
     private final NamingContext interfaceContext;
     private final NamingContext bridgeDomainContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
     InterconnectionReadUtils(@Nonnull final FutureJVppCore futureJVppCore,
                              @Nonnull final NamingContext interfaceContext,
-                             @Nonnull final NamingContext bridgeDomainContext) {
+                             @Nonnull final NamingContext bridgeDomainContext,
+                             @Nonnull final InterfaceCacheDumpManager dumpManager) {
         this.futureJVppCore = requireNonNull(futureJVppCore, "futureJVppCore should not be null");
         this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null");
         this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+        this.dumpManager = requireNonNull(dumpManager, "dumpManager should not be null");
     }
 
     @Nullable
@@ -64,8 +68,7 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator {
             throws ReadFailedException {
         final int ifaceId = interfaceContext.getIndex(ifaceName, ctx.getMappingContext());
 
-        final SwInterfaceDetails iface = getVppInterfaceDetails(futureJVppCore, id, ifaceName,
-                ifaceId, ctx.getModificationCache(), LOG);
+        final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName);
         LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface);
 
         final BridgeDomainDetailsReplyDump dumpReply = getDumpReply(id);
@@ -78,7 +81,7 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator {
 
                 // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index
                 final Optional<BridgeDomainDetails> bridgeDomainForInterface =
-                    getBridgeDomainForInterface(dumpReply, bd.bdId);
+                        getBridgeDomainForInterface(dumpReply, bd.bdId);
                 // Since we already found an interface assigned to a bridge domain, the details for BD must be present
                 checkState(bridgeDomainForInterface.isPresent());
                 if (bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) {
index fe04e5d..5ec0082 100644 (file)
 package io.fd.hc2vpp.v3po.interfacesstate;
 
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.MappingContext;
-import io.fd.honeycomb.translate.ModificationCache;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
@@ -54,36 +46,21 @@ import org.slf4j.LoggerFactory;
 /**
  * Customizer for reading ietf-interfaces:interfaces-state/interface.
  */
-public class InterfaceCustomizer extends FutureJVppCustomizer
+public class InterfaceCustomizer
         implements InitializingListReaderCustomizer<Interface, InterfaceKey, InterfaceBuilder>, ByteDataTranslator,
         InterfaceDataTranslator {
 
-    public static final String DUMPED_IFCS_CONTEXT_KEY =
-            InterfaceCustomizer.class.getName() + "dumpedInterfacesDuringGetAllIds";
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class);
     private final NamingContext interfaceNamingContext;
     private final DisabledInterfacesManager interfaceDisableContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public InterfaceCustomizer(@Nonnull final FutureJVppCore jvpp,
-                               @Nonnull final NamingContext interfaceNamingContext,
-                               @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
-        super(jvpp);
+    public InterfaceCustomizer(@Nonnull final NamingContext interfaceNamingContext,
+                               @Nonnull final DisabledInterfacesManager interfaceDisableContext,
+                               @Nonnull final InterfaceCacheDumpManager dumpManager) {
         this.interfaceNamingContext = interfaceNamingContext;
         this.interfaceDisableContext = interfaceDisableContext;
-    }
-
-    public static void cacheInterfaceDump(final @Nonnull ReadContext context, final SwInterfaceDetailsReplyDump ifaces) {
-        context.getModificationCache().put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream()
-                .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)));
-    }
-
-    @Nonnull
-    @SuppressWarnings("unchecked")
-    public static Map<Integer, SwInterfaceDetails> getCachedInterfaceDump(@Nonnull final ModificationCache ctx) {
-        return ctx.get(DUMPED_IFCS_CONTEXT_KEY) == null
-                ? new HashMap<>()
-                // allow customizers to update the cache
-                : (Map<Integer, SwInterfaceDetails>) ctx.get(DUMPED_IFCS_CONTEXT_KEY);
+        this.dumpManager = dumpManager;
     }
 
     @Nonnull
@@ -106,9 +83,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
             return;
         }
 
-        // Pass cached details from getAllIds to getDetails to avoid additional dumps
-        final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, ifaceName,
-                index, ctx.getModificationCache(), LOG);
+        final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName);
         LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface);
 
         if (!isRegularInterface(iface)) {
@@ -140,44 +115,13 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
                                         @Nonnull final ReadContext context) throws ReadFailedException {
         final List<InterfaceKey> interfacesKeys;
         LOG.trace("Dumping all interfaces to get all IDs");
-
-        final SwInterfaceDump request = new SwInterfaceDump();
-        request.nameFilter = "".getBytes();
-        request.nameFilterValid = 0;
-
-        final CompletableFuture<SwInterfaceDetailsReplyDump> swInterfaceDetailsReplyDumpCompletableFuture =
-                getFutureJVpp().swInterfaceDump(request).toCompletableFuture();
-        final SwInterfaceDetailsReplyDump ifaces =
-                getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, id);
-
-        if (null == ifaces || null == ifaces.swInterfaceDetails) {
-            LOG.debug("No interfaces for :{} found in VPP", id);
-            return Collections.emptyList();
-        }
-
-        // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes
-        cacheInterfaceDump(context, ifaces);
-
         final MappingContext mappingCtx = context.getMappingContext();
-        final Set<Integer> interfacesIdxs = ifaces.swInterfaceDetails.stream()
+        final Set<Integer> interfacesIdxs = dumpManager.getInterfaces(id, context)
                 .filter(elt -> elt != null)
                 // Filter out disabled interfaces, dont read them
                 // This also prevents child readers in being invoked such as vxlan (which relies on disabling interfaces)
                 .filter(elt -> !interfaceDisableContext
                         .isInterfaceDisabled(elt.swIfIndex, mappingCtx))
-                .map((elt) -> {
-                    // Store interface name from VPP in context if not yet present
-                    if (!interfaceNamingContext.containsName(elt.swIfIndex, mappingCtx)) {
-                        interfaceNamingContext.addName(elt.swIfIndex, toString(elt.interfaceName),
-                                mappingCtx);
-                    }
-                    LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP",
-                            interfaceNamingContext.getName(elt.swIfIndex, mappingCtx),
-                            elt.interfaceName,
-                            elt.swIfIndex);
-
-                    return elt;
-                })
                 // filter out sub-interfaces
                 .filter(InterfaceDataTranslator.INSTANCE::isRegularInterface)
                 .map(elt -> elt.swIfIndex)
@@ -207,7 +151,8 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
 
     @Override
     public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> init(
-            @Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface readValue, @Nonnull final ReadContext ctx) {
+            @Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface readValue,
+            @Nonnull final ReadContext ctx) {
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder()
                         .setName(readValue.getName())
index b3c3679..ec47ee2 100644 (file)
 package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
 
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.math.BigInteger;
-import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.CompletionStage;
 import java.util.stream.Collector;
-import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
@@ -46,7 +40,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanGpeTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanTunnel;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
 
 public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyConsumer {
 
@@ -136,74 +129,6 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
         return yangIfIndex - 1;
     }
 
-
-    /**
-     * Queries VPP for interface description given interface key.
-     *
-     * @param futureJVppCore VPP Java Future API
-     * @param id             InstanceIdentifier, which is passed in ReadFailedException
-     * @param name           interface name
-     * @param index          VPP index of the interface
-     * @param ctx            per-tx scope context containing cached dump with all the interfaces. If the cache is not
-     *                       available or outdated, another dump will be performed.
-     * @return SwInterfaceDetails DTO or null if interface was not found
-     * @throws IllegalArgumentException If interface cannot be found
-     * @throws ReadFailedException      If read operation had failed
-     */
-    @Nonnull
-    default SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVppCore futureJVppCore,
-                                                      @Nonnull final InstanceIdentifier<?> id,
-                                                      @Nonnull final String name, final int index,
-                                                      @Nonnull final ModificationCache ctx,
-                                                      @Nonnull final Logger callerLogger)
-            throws ReadFailedException {
-        requireNonNull(futureJVppCore, "futureJVppCore should not be null");
-        requireNonNull(name, "name should not be null");
-        requireNonNull(ctx, "ctx should not be null");
-
-        final SwInterfaceDump request = new SwInterfaceDump();
-        request.nameFilter = name.getBytes();
-        request.nameFilterValid = 1;
-
-        final Map<Integer, SwInterfaceDetails> allInterfaces = InterfaceCustomizer.getCachedInterfaceDump(ctx);
-
-        // Returned cached if available
-        if (allInterfaces.containsKey(index)) {
-            return allInterfaces.get(index);
-        }
-
-        SwInterfaceDetailsReplyDump ifaces;
-
-        CompletionStage<SwInterfaceDetailsReplyDump> requestFuture = futureJVppCore.swInterfaceDump(request);
-        ifaces = getReplyForRead(requestFuture.toCompletableFuture(), id);
-        if (null == ifaces || null == ifaces.swInterfaceDetails || ifaces.swInterfaceDetails.isEmpty()) {
-            request.nameFilterValid = 0;
-
-            callerLogger.warn("VPP returned null instead of interface by key {} and its not cached", name);
-            callerLogger.warn("Iterating through all the interfaces to find interface: {}", name);
-
-            // Or else just perform full dump and do inefficient filtering
-            requestFuture = futureJVppCore.swInterfaceDump(request);
-            ifaces = getReplyForRead(requestFuture.toCompletableFuture(), id);
-
-            // Update the cache
-            allInterfaces.clear();
-            allInterfaces
-                    .putAll(ifaces.swInterfaceDetails.stream().collect(Collectors.toMap(d -> d.swIfIndex, d -> d)));
-
-            if (allInterfaces.containsKey(index)) {
-                return allInterfaces.get(index);
-            }
-            throw new IllegalArgumentException("Unable to find interface " + name);
-        }
-
-        // SwInterfaceDump's name filter does prefix match, so we need additional filtering:
-        final SwInterfaceDetails iface =
-                ifaces.swInterfaceDetails.stream().filter(d -> d.swIfIndex == index).collect(SINGLE_ITEM_COLLECTOR);
-        allInterfaces.put(index, iface); // update the cache
-        return iface;
-    }
-
     /**
      * Determine interface type based on its VPP name (relying on VPP's interface naming conventions)
      *
@@ -240,20 +165,15 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
     }
 
     /**
-     * Check interface type. Uses interface details from VPP to determine. Uses {@link
-     * #getVppInterfaceDetails(FutureJVppCore, InstanceIdentifier, String, int, ModificationCache, Logger)} internally
-     * so tries to utilize cache before asking VPP.
+     * Check interface type. Uses interface details from VPP to determine.
      */
-    default boolean isInterfaceOfType(@Nonnull final FutureJVppCore jvpp,
-                                      @Nonnull final ModificationCache cache,
+    default boolean isInterfaceOfType(@Nonnull final InterfaceCacheDumpManager dumpManager,
                                       @Nonnull final InstanceIdentifier<?> id,
-                                      final int index,
-                                      @Nonnull final Class<? extends InterfaceType> ifcType,
-                                      @Nonnull final Logger callerLogger)
+                                      @Nonnull final ReadContext ctx,
+                                      @Nonnull final Class<? extends InterfaceType> ifcType)
             throws ReadFailedException {
         final String name = id.firstKeyOf(Interface.class).getName();
-        final SwInterfaceDetails vppInterfaceDetails =
-                getVppInterfaceDetails(jvpp, id, name, index, cache, callerLogger);
+        final SwInterfaceDetails vppInterfaceDetails = dumpManager.getInterfaceDetail(id, ctx, name);
 
         return isInterfaceOfType(ifcType, vppInterfaceDetails);
     }
@@ -264,13 +184,11 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
     }
 
     /**
-     * Checks whether provided {@link SwInterfaceDetails} is detail of sub-interface<br>
-     * <li>subId == unique number of sub-interface within set of sub-interfaces of single interface
-     * <li>swIfIndex == unique index of interface/sub-interface within all interfaces
-     * <li>supSwIfIndex == unique index of parent interface
-     * <li>in case of interface , swIfIndex value equals supSwIfIndex
-     * <li>in case of subinterface, supSwIfIndex equals index of parent interface,
-     * swIfIndex is index of subinterface itselt
+     * Checks whether provided {@link SwInterfaceDetails} is detail of sub-interface<br> <li>subId == unique number of
+     * sub-interface within set of sub-interfaces of single interface <li>swIfIndex == unique index of
+     * interface/sub-interface within all interfaces <li>supSwIfIndex == unique index of parent interface <li>in case of
+     * interface , swIfIndex value equals supSwIfIndex <li>in case of subinterface, supSwIfIndex equals index of parent
+     * interface, swIfIndex is index of subinterface itselt
      */
     default boolean isSubInterface(@Nonnull final SwInterfaceDetails elt) {
         //cant check by subId != 0, because you can pick 0 as value
@@ -278,13 +196,11 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
     }
 
     /**
-     * Checks whether provided {@link SwInterfaceDetails} is detail of interface<br>
-     * <li>subId == unique number of subinterface within set of subinterfaces of single interface
-     * <li>swIfIndex == unique index of interface/subinterface within all interfaces
-     * <li>supSwIfIndex == unique index of parent interface
-     * <li>in case of interface , swIfIndex value equals supSwIfIndex
-     * <li>in case of subinterface, supSwIfIndex equals index of parent interface,
-     * swIfIndex is index of subinterface itselt
+     * Checks whether provided {@link SwInterfaceDetails} is detail of interface<br> <li>subId == unique number of
+     * subinterface within set of subinterfaces of single interface <li>swIfIndex == unique index of
+     * interface/subinterface within all interfaces <li>supSwIfIndex == unique index of parent interface <li>in case of
+     * interface , swIfIndex value equals supSwIfIndex <li>in case of subinterface, supSwIfIndex equals index of parent
+     * interface, swIfIndex is index of subinterface itselt
      */
     default boolean isRegularInterface(@Nonnull final SwInterfaceDetails elt) {
         return !isSubInterface(elt);
index c199dfd..1761b38 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
@@ -31,11 +32,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceStateAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.Interconnection;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.BridgeBased;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.XconnectBased;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -52,9 +53,11 @@ public class L2Customizer extends FutureJVppCustomizer implements InitializingRe
 
     public L2Customizer(@Nonnull final FutureJVppCore futureJVppCore,
                         @Nonnull final NamingContext interfaceContext,
-                        @Nonnull final NamingContext bridgeDomainContext) {
+                        @Nonnull final NamingContext bridgeDomainContext,
+                        @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(futureJVppCore);
-        this.icReadUtils = new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext);
+        this.icReadUtils =
+                new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager);
     }
 
     @Override
index 7dec4c2..46d85cf 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.base.Preconditions;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.ArrayList;
 import java.util.List;
 import javax.annotation.Nonnull;
@@ -40,9 +38,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607._802dot1ad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607._802dot1q;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.RewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTagsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTagsKey;
@@ -55,19 +53,17 @@ import org.slf4j.LoggerFactory;
 /**
  * Customizer for reading vlan tag-rewrite configuration state form the VPP.
  */
-public class RewriteCustomizer extends FutureJVppCustomizer
+public class RewriteCustomizer
         implements ReaderCustomizer<Rewrite, RewriteBuilder>, InterfaceDataTranslator {
 
     // No initialization necessary since its parent Subinterface L2 customzier sets the entire subtree during
     // initialization
 
     private static final Logger LOG = LoggerFactory.getLogger(RewriteCustomizer.class);
-    private final NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public RewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
-                             @Nonnull final NamingContext interfaceContext) {
-        super(futureJVppCore);
-        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+    public RewriteCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) {
+        this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null");
     }
 
     @Override
@@ -89,8 +85,7 @@ public class RewriteCustomizer extends FutureJVppCustomizer
         final String subInterfaceName = getSubInterfaceName(id);
         LOG.debug("Reading attributes for sub interface: {}", subInterfaceName);
 
-        final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, subInterfaceName,
-                interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache(), LOG);
+        final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName);
         LOG.debug("VPP sub-interface details: {}", iface);
 
         checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface");
index 2bf635f..9c39722 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.base.Preconditions;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
@@ -29,13 +30,10 @@ import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
+import java.util.Objects;
 import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan;
@@ -74,17 +72,21 @@ import org.slf4j.LoggerFactory;
  * Customizer for reading sub interfaces form the VPP.
  */
 public class SubInterfaceCustomizer extends FutureJVppCustomizer
-        implements InitializingListReaderCustomizer<SubInterface, SubInterfaceKey, SubInterfaceBuilder>, ByteDataTranslator,
+        implements InitializingListReaderCustomizer<SubInterface, SubInterfaceKey, SubInterfaceBuilder>,
+        ByteDataTranslator,
         InterfaceDataTranslator {
 
     private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class);
     private static final Dot1qTag.VlanId ANY_VLAN_ID = new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any);
-    private NamingContext interfaceContext;
+    private final NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
     public SubInterfaceCustomizer(@Nonnull final FutureJVppCore jvpp,
-                                  @Nonnull final NamingContext interfaceContext) {
+                                  @Nonnull final NamingContext interfaceContext,
+                                  @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
-        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null");
     }
 
     private static String getSubInterfaceName(final InstanceIdentifier<SubInterface> id) {
@@ -119,30 +121,8 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer
         final String ifaceName = key.getName();
         final int ifaceId = interfaceContext.getIndex(ifaceName, context.getMappingContext());
 
-        // TODO HONEYCOMB-189 if we know that full dump was already performed we could use cache
-        // (checking if getCachedInterfaceDump() returns non empty map is not enough, because
-        // we could be part of particular iface state read
-        final SwInterfaceDump request = new SwInterfaceDump();
-        request.nameFilter = "".getBytes();
-        request.nameFilterValid = 0;
-
-        final CompletableFuture<SwInterfaceDetailsReplyDump> swInterfaceDetailsReplyDumpCompletableFuture =
-                getFutureJVpp().swInterfaceDump(request).toCompletableFuture();
-        final SwInterfaceDetailsReplyDump ifaces =
-                getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, id);
-
-        if (null == ifaces || null == ifaces.swInterfaceDetails) {
-            LOG.warn("Looking for sub-interfaces, but no interfaces found in VPP");
-            return Collections.emptyList();
-        }
-
-        // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes
-        context.getModificationCache()
-                .put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream()
-                        .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)));
-
-        final List<SubInterfaceKey> interfacesKeys = ifaces.swInterfaceDetails.stream()
-                .filter(elt -> elt != null)
+        final List<SubInterfaceKey> interfacesKeys = dumpManager.getInterfaces(id,context)
+                .filter(Objects::nonNull)
                 // accept only sub-interfaces for current iface:
                 .filter(elt -> isSubInterface(elt) && elt.supSwIfIndex == ifaceId)
                 .map(details -> new SubInterfaceKey(new Long(details.subId)))
@@ -171,8 +151,7 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer
         final String subInterfaceName = getSubInterfaceName(id);
         LOG.debug("Reading attributes for sub interface: {}", subInterfaceName);
 
-        final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, subInterfaceName,
-                interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache(), LOG);
+        final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName);
         LOG.debug("VPP sub-interface details: {}", iface);
 
         checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface");
index f068ac2..4fd200b 100644 (file)
@@ -18,20 +18,17 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getSubInterfaceName;
 
-import com.google.common.collect.ImmutableMap;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
-import java.util.Map;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.Interconnection;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.BridgeBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.XconnectBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface;
@@ -48,7 +45,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Customizer for reading vlan sub interface L2 operational state
  */
-public class SubInterfaceL2Customizer extends FutureJVppCustomizer
+public class SubInterfaceL2Customizer
         implements InitializingReaderCustomizer<L2, L2Builder> {
 
     private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class);
@@ -56,9 +53,10 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer
 
     public SubInterfaceL2Customizer(@Nonnull final FutureJVppCore futureJVppCore,
                                     @Nonnull final NamingContext interfaceContext,
-                                    @Nonnull final NamingContext bridgeDomainContext) {
-        super(futureJVppCore);
-        this.icReadUtils = new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext);
+                                    @Nonnull final NamingContext bridgeDomainContext,
+                                    @Nonnull final InterfaceCacheDumpManager dumpManager) {
+        this.icReadUtils =
+                new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager);
     }
 
     @Override
@@ -78,7 +76,8 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer
         LOG.debug("Reading attributes for sub-interface L2: {}", id);
         final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class);
         final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class);
-        final String subInterfaceName = getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue());
+        final String subInterfaceName =
+                getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue());
 
         builder.setInterconnection(icReadUtils.readInterconnection(id, subInterfaceName, ctx));
     }
@@ -89,27 +88,31 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer
             @Nonnull final L2 readValue,
             @Nonnull final ReadContext ctx) {
 
-        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder builder=
+        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder
+                builder =
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder();
 
-        if(readValue.getInterconnection() instanceof XconnectBased){
+        if (readValue.getInterconnection() instanceof XconnectBased) {
             XconnectBased state = (XconnectBased) readValue.getInterconnection();
-            builder.setInterconnection(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder()
-                    .setXconnectOutgoingInterface(state.getXconnectOutgoingInterface())
-                    .build());
-        }else {
+            builder.setInterconnection(
+                    new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder()
+                            .setXconnectOutgoingInterface(state.getXconnectOutgoingInterface())
+                            .build());
+        } else {
             BridgeBased state = (BridgeBased) readValue.getInterconnection();
-            builder.setInterconnection(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder()
-                    .setBridgeDomain(state.getBridgeDomain())
-                    .setBridgedVirtualInterface(state.isBridgedVirtualInterface())
-                    .setSplitHorizonGroup(state.getSplitHorizonGroup())
-                    .build());
+            builder.setInterconnection(
+                    new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder()
+                            .setBridgeDomain(state.getBridgeDomain())
+                            .setBridgedVirtualInterface(state.isBridgedVirtualInterface())
+                            .setSplitHorizonGroup(state.getSplitHorizonGroup())
+                            .build());
         }
 
         return Initialized.create(getCfgId(id), builder.setRewrite(readValue.getRewrite()).build());
     }
 
-    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2> getCfgId(final InstanceIdentifier<L2> id) {
+    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2> getCfgId(
+            final InstanceIdentifier<L2> id) {
         return SubInterfaceCustomizer.getCfgId(RWUtils.cutId(id, SubInterface.class))
                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2.class);
     }
index b3c7f78..fb8e6b5 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import static java.lang.String.format;
+
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
@@ -53,12 +56,17 @@ public class TapCustomizer extends FutureJVppCustomizer
         implements InitializingReaderCustomizer<Tap, TapBuilder>, InterfaceDataTranslator, JvppReplyConsumer {
 
     private static final Logger LOG = LoggerFactory.getLogger(TapCustomizer.class);
+    // TODO - HC2VPP-213 - used dump cache manager
     public static final String DUMPED_TAPS_CONTEXT_KEY = TapCustomizer.class.getName() + "dumpedTapsDuringGetAllIds";
     private NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public TapCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+    public TapCustomizer(@Nonnull final FutureJVppCore jvpp,
+                         @Nonnull final NamingContext interfaceContext,
+                         @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
     }
 
     @Override
@@ -79,8 +87,11 @@ public class TapCustomizer extends FutureJVppCustomizer
 
         final InterfaceKey key = id.firstKeyOf(Interface.class);
         final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index,
-                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap.class, LOG)) {
+        final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+
+        if (!isInterfaceOfType(
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap.class,
+                ifcDetails)) {
             return;
         }
 
@@ -115,9 +126,6 @@ public class TapCustomizer extends FutureJVppCustomizer
 
         builder.setTapName(toString(swInterfaceTapDetails.devName));
 
-        final SwInterfaceDetails ifcDetails = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(),
-            interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG);
-
         if (ifcDetails.tag[0] != 0) { // tag supplied
             builder.setTag(toString(ifcDetails.tag));
         }
@@ -129,15 +137,21 @@ public class TapCustomizer extends FutureJVppCustomizer
             @Nonnull final InstanceIdentifier<Tap> id, @Nonnull final Tap readValue, @Nonnull final ReadContext ctx) {
         // The MAC address & tag is set from interface details, those details are retrieved from cache
         final InterfaceKey key = id.firstKeyOf(Interface.class);
-        final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        final SwInterfaceDetails ifcDetails =
-                InterfaceCustomizer.getCachedInterfaceDump(ctx.getModificationCache()).get(index);
+
+        final SwInterfaceDetails ifcDetails;
+        try {
+            ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+        } catch (ReadFailedException e) {
+            throw new IllegalStateException(format("Unable to read interface %s", key.getName()), e);
+        }
 
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.TapBuilder()
                         .setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address)))
                         .setTapName(readValue.getTapName())
-                        .setTag(ifcDetails.tag[0] == 0 ? null : toString(ifcDetails.tag))
+                        .setTag(ifcDetails.tag[0] == 0
+                                ? null
+                                : toString(ifcDetails.tag))
 //                            tapBuilder.setDeviceInstance();
                         .build());
     }
index 282e1a5..4ce646d 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import static java.lang.String.format;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump;
@@ -51,16 +54,22 @@ import org.slf4j.LoggerFactory;
 
 
 public class VhostUserCustomizer extends FutureJVppCustomizer
-        implements InitializingReaderCustomizer<VhostUser, VhostUserBuilder>, InterfaceDataTranslator, JvppReplyConsumer {
+        implements InitializingReaderCustomizer<VhostUser, VhostUserBuilder>, InterfaceDataTranslator,
+        JvppReplyConsumer {
 
+    //TODO - HC2VPP-212 - use dump cache manager
     public static final String DUMPED_VHOST_USERS_CONTEXT_KEY =
             VhostUserCustomizer.class.getName() + "dumpedVhostUsersDuringGetAllIds";
     private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class);
     private NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public VhostUserCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+    public VhostUserCustomizer(@Nonnull final FutureJVppCore jvpp,
+                               @Nonnull final NamingContext interfaceContext,
+                               @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
     }
 
     @Override
@@ -81,9 +90,12 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
 
         final InterfaceKey key = id.firstKeyOf(Interface.class);
         final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index,
+        final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+
+
+        if (!isInterfaceOfType(
                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser.class,
-                LOG)) {
+                ifcDetails)) {
             return;
         }
 
@@ -121,9 +133,6 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
         LOG.trace("Vhost user interface: {} attributes returned from VPP: {}", key.getName(),
                 swInterfaceVhostUserDetails);
 
-        final SwInterfaceDetails ifcDetails = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(),
-            interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG);
-
         builder.setRole(swInterfaceVhostUserDetails.isServer == 1
                 ? VhostUserRole.Server
                 : VhostUserRole.Client);
@@ -147,14 +156,19 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
             @Nonnull final ReadContext ctx) {
         // The tag is set from interface details, those details are retrieved from cache
         final InterfaceKey key = id.firstKeyOf(Interface.class);
-        final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        final SwInterfaceDetails ifcDetails =
-            InterfaceCustomizer.getCachedInterfaceDump(ctx.getModificationCache()).get(index);
+        final SwInterfaceDetails ifcDetails;
+        try {
+            ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+        } catch (ReadFailedException e) {
+            throw new IllegalStateException(format("Unable to find VHost interface %s", key.getName()), e);
+        }
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VhostUserBuilder()
                         .setRole(readValue.getRole())
                         .setSocket(readValue.getSocket())
-                        .setTag(ifcDetails.tag[0] == 0 ? null : toString(ifcDetails.tag))
+                        .setTag(ifcDetails.tag[0] == 0
+                                ? null
+                                : toString(ifcDetails.tag))
                         .build());
     }
 
index b2e3520..c11d239 100644 (file)
@@ -18,13 +18,24 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.concurrent.CompletionStage;
-
 import javax.annotation.Nonnull;
-
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
@@ -44,33 +55,23 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
-import io.fd.honeycomb.translate.read.ReadContext;
-import io.fd.honeycomb.translate.read.ReadFailedException;
-import io.fd.honeycomb.translate.spi.read.Initialized;
-import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
-import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
-
 public class VxlanCustomizer extends FutureJVppCustomizer
-implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTranslator, JvppReplyConsumer {
+        implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTranslator, JvppReplyConsumer {
 
     private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class);
     private final NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public VxlanCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+    public VxlanCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext,
+                           @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
     }
 
     @Override
     public void merge(@Nonnull Builder<? extends DataObject> parentBuilder,
-            @Nonnull Vxlan readValue) {
+                      @Nonnull Vxlan readValue) {
         ((VppInterfaceStateAugmentationBuilder) parentBuilder).setVxlan(readValue);
     }
 
@@ -82,12 +83,12 @@ implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTrans
 
     @Override
     public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Vxlan> id,
-            @Nonnull final VxlanBuilder builder,
-            @Nonnull final ReadContext ctx) throws ReadFailedException {
+                                      @Nonnull final VxlanBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
 
         final InterfaceKey key = id.firstKeyOf(Interface.class);
         final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, VxlanTunnel.class, LOG)) {
+        if (!isInterfaceOfType(dumpManager, id, ctx, VxlanTunnel.class)) {
             return;
         }
 
@@ -135,15 +136,15 @@ implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTrans
         builder.setEncapVrfId((long) swInterfaceVxlanDetails.encapVrfId);
         builder.setVni(new VxlanVni((long) swInterfaceVxlanDetails.vni));
         switch (swInterfaceVxlanDetails.decapNextIndex) {
-        case 1:
-            builder.setDecapNext(L2Input.class);
-            break;
-        case 2:
-            builder.setDecapNext(NshProxy.class);
-            break;
-        default:
-            LOG.trace("Unsupported decap next index for vxlan: {}", swInterfaceVxlanDetails.decapNextIndex);
-            return;
+            case 1:
+                builder.setDecapNext(L2Input.class);
+                break;
+            case 2:
+                builder.setDecapNext(NshProxy.class);
+                break;
+            default:
+                LOG.trace("Unsupported decap next index for vxlan: {}", swInterfaceVxlanDetails.decapNextIndex);
+                return;
         }
         LOG.debug("Vxlan tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder);
     }
@@ -159,15 +160,16 @@ implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTrans
 
     @Override
     public Initialized<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Vxlan> init(
-            @Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan readValue, @Nonnull final ReadContext ctx) {
+            @Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan readValue,
+            @Nonnull final ReadContext ctx) {
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanBuilder()
-                .setDst(readValue.getDst())
-                .setSrc(readValue.getSrc())
-                .setEncapVrfId(readValue.getEncapVrfId())
-                .setVni(new VxlanVni(readValue.getVni()))
-                .setDecapNext(readValue.getDecapNext())
-                .build());
+                        .setDst(readValue.getDst())
+                        .setSrc(readValue.getSrc())
+                        .setEncapVrfId(readValue.getEncapVrfId())
+                        .setVni(new VxlanVni(readValue.getVni()))
+                        .setDecapNext(readValue.getDecapNext())
+                        .build());
     }
 
     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Vxlan> getCfgId(
index 9afbdc7..2e2f60c 100644 (file)
@@ -18,14 +18,15 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
-import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
-import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails;
 import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump;
 import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump;
@@ -57,11 +58,15 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer
         implements InitializingReaderCustomizer<VxlanGpe, VxlanGpeBuilder>, InterfaceDataTranslator, JvppReplyConsumer {
 
     private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
-    private NamingContext interfaceContext;
+    private final NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
 
-    public VxlanGpeCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+    public VxlanGpeCustomizer(@Nonnull final FutureJVppCore jvpp,
+                              @Nonnull final NamingContext interfaceContext,
+                              @Nonnull final InterfaceCacheDumpManager dumpManager) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
     }
 
     @Override
@@ -83,7 +88,7 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer
 
         final InterfaceKey key = id.firstKeyOf(Interface.class);
         final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
-        if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, VxlanGpeTunnel.class, LOG)) {
+        if (!isInterfaceOfType(dumpManager, id, ctx, VxlanGpeTunnel.class)) {
             return;
         }
 
@@ -147,7 +152,8 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer
 
     @Override
     public Initialized<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanGpe> init(
-            @Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe readValue, @Nonnull final ReadContext ctx) {
+            @Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe readValue,
+            @Nonnull final ReadContext ctx) {
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanGpeBuilder()
                         .setLocal(readValue.getLocal())
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java
new file mode 100644 (file)
index 0000000..589d590
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.cache;
+
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Manager for dump data of interfaces. The main purpose of this manager is to cache common interface data between
+ * various classes that process this kind of data. If reader does not use this utility, it introduces a big overhead
+ * because of size/complexity of interfaces dump
+ */
+public interface InterfaceCacheDumpManager {
+
+    /**
+     * Provides stream of all currently configured vpp interfaces
+     *
+     * @param identifier id of currently processed data
+     * @param ctx        context of current transaction
+     * @return {@link Stream} of currently configured interfaces
+     * @throws ReadFailedException if dumping of data was unsuccessful
+     */
+    @Nonnull
+    Stream<SwInterfaceDetails> getInterfaces(@Nonnull final InstanceIdentifier<?> identifier,
+                                             @Nonnull final ReadContext ctx) throws ReadFailedException;
+
+    /**
+     * Provides details of interface
+     *
+     * @param identifier    id of currently processed data
+     * @param ctx           context of current transaction
+     * @param interfaceName name of requested interface
+     * @return {@link SwInterfaceDetails} of requested interface
+     * @throws ReadFailedException if dumping of data was unsuccessful
+     */
+    @Nullable
+    SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier<?> identifier,
+                                          @Nonnull final ReadContext ctx,
+                                          @Nonnull final String interfaceName) throws ReadFailedException;
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java
new file mode 100644 (file)
index 0000000..e9b1140
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.cache;
+
+import static io.fd.hc2vpp.common.translate.util.JvppReplyConsumer.INSTANCE;
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+import static java.util.stream.Collectors.toMap;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manager for dump data of interfaces/sub-interfaces
+ */
+final class InterfaceCacheDumpManagerImpl implements InterfaceCacheDumpManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(InterfaceCacheDumpManagerImpl.class);
+
+    // byNameIndex must be cached, not held as reference here, to have it destroyed with cache after transaction
+    static final String BY_NAME_INDEX_KEY = InterfaceCacheDumpManagerImpl.class.getName() + "_byNameIndex";
+    private NamingContext namingContext;
+    private final DumpCacheManager<SwInterfaceDetailsReplyDump, String> specificDumpManager;
+    private final DumpCacheManager<SwInterfaceDetailsReplyDump, Void> fullDumpManager;
+
+    InterfaceCacheDumpManagerImpl(@Nonnull final FutureJVppCore jvpp,
+                                  @Nonnull final NamingContext namingContext) {
+        this.namingContext = namingContext;
+        specificDumpManager = specificInterfaceDumpManager(jvpp);
+        fullDumpManager = fullInterfaceDumpManager(jvpp,
+                new StaticCacheKeyFactory(StaticCacheKeyFactory.class.getName() + "_dump"));
+    }
+
+    @Override
+    @Nonnull
+    public synchronized Stream<SwInterfaceDetails> getInterfaces(@Nonnull final InstanceIdentifier<?> identifier,
+                                                                 @Nonnull final ReadContext ctx)
+            throws ReadFailedException {
+        LOG.debug("Reading all interfaces[{}]", identifier);
+        return initMapAndGet(identifier, ctx).entrySet().stream().map(Map.Entry::getValue);
+    }
+
+    @Override
+    @Nullable
+    public synchronized SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier<?> identifier,
+                                                              @Nonnull final ReadContext ctx,
+                                                              @Nonnull final String interfaceName)
+            throws ReadFailedException {
+        final Map<String, SwInterfaceDetails> interfaceIndex = getMap(ctx);
+
+        // does not attempt to cover cases with concurrent updates, as tx should be atomic
+        if (interfaceIndex != null) {
+            // tries to find interface in map
+            return interfaceIndex.get(interfaceName);
+        } else {
+            // if map is not present, use specific dump(it will be cached standard way, under key constructed from IID)
+            return dumpSpecificDetail(identifier, ctx, interfaceName);
+        }
+    }
+
+    private SwInterfaceDetails dumpSpecificDetail(@Nonnull final InstanceIdentifier<?> identifier,
+                                                  @Nonnull final ReadContext ctx,
+                                                  @Nonnull final String interfaceName)
+            throws ReadFailedException {
+        LOG.debug("Interface {} not present in cached data, performing specific dump[{}]", interfaceName,
+                identifier);
+        final SwInterfaceDetailsReplyDump reply =
+                specificDumpManager.getDump(identifier, ctx.getModificationCache(), interfaceName)
+                        .or(new SwInterfaceDetailsReplyDump());
+
+        if (reply.swInterfaceDetails.isEmpty()) {
+            return null;
+        }
+
+        return reply.swInterfaceDetails.get(0);
+    }
+
+    private Map<String, SwInterfaceDetails> initMapAndGet(final InstanceIdentifier<?> identifier, final ReadContext ctx)
+            throws ReadFailedException {
+
+        final ModificationCache cache = ctx.getModificationCache();
+        if (!cache.containsKey(BY_NAME_INDEX_KEY)) {
+            LOG.debug("Performing dump[{}]", identifier);
+            final SwInterfaceDetailsReplyDump dump =
+                    fullDumpManager.getDump(identifier, cache, NO_PARAMS)
+                            .or(new SwInterfaceDetailsReplyDump());
+
+            // naming context initialization must be done here, as it is uses getName in next step, therefore it would
+            // create artificial mapping for every interface, because this happens before interface dump is processed
+            dump.swInterfaceDetails.forEach((elt) -> {
+                // Store interface name from VPP in context if not yet present
+                if (!namingContext.containsName(elt.swIfIndex, ctx.getMappingContext())) {
+                    namingContext.addName(elt.swIfIndex, ByteDataTranslator.INSTANCE.toString(elt.interfaceName),
+                            ctx.getMappingContext());
+                }
+                LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP",
+                        getInterfaceName(ctx, elt),
+                        elt.interfaceName,
+                        elt.swIfIndex);
+            });
+
+            final Map<String, SwInterfaceDetails> freshIndex = dump.swInterfaceDetails.stream()
+                    .collect(toMap(detail -> getInterfaceName(ctx, detail),
+                            detail -> detail));
+            putMap(freshIndex, ctx);
+        }
+
+        return getMap(ctx);
+    }
+
+    private String getInterfaceName(final ReadContext ctx, final SwInterfaceDetails elt) {
+        return namingContext.getName(elt.swIfIndex, ctx.getMappingContext());
+    }
+
+    private static Map<String, SwInterfaceDetails> getMap(final ReadContext ctx) {
+        return (Map<String, SwInterfaceDetails>) ctx.getModificationCache().get(BY_NAME_INDEX_KEY);
+    }
+
+    private static void putMap(final Map<String, SwInterfaceDetails> map, final ReadContext ctx) {
+        ctx.getModificationCache().put(BY_NAME_INDEX_KEY, map);
+    }
+
+
+    private static DumpCacheManager<SwInterfaceDetailsReplyDump, Void> fullInterfaceDumpManager(
+            final FutureJVppCore jvpp,
+            final StaticCacheKeyFactory cacheKeyFactory) {
+        return new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceDetailsReplyDump, Void>()
+                .withExecutor(fullInterfaceDumpExecutor(jvpp))
+                .withCacheKeyFactory(cacheKeyFactory)
+                .acceptOnly(SwInterfaceDetailsReplyDump.class)
+                .build();
+    }
+
+    private static DumpCacheManager<SwInterfaceDetailsReplyDump, String> specificInterfaceDumpManager(
+            final FutureJVppCore jvpp) {
+        return new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceDetailsReplyDump, String>()
+                .withExecutor(specificInterfaceDumpExecutor(jvpp))
+                .acceptOnly(SwInterfaceDetailsReplyDump.class)
+                .build();
+    }
+
+    private static EntityDumpExecutor<SwInterfaceDetailsReplyDump, Void> fullInterfaceDumpExecutor(
+            final FutureJVppCore api) {
+        return (identifier, params) -> {
+            final SwInterfaceDump request = new SwInterfaceDump();
+            request.nameFilter = "".getBytes();
+            request.nameFilterValid = 0;
+
+            final CompletableFuture<SwInterfaceDetailsReplyDump>
+                    swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture();
+            return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier);
+        };
+    }
+
+    private static EntityDumpExecutor<SwInterfaceDetailsReplyDump, String> specificInterfaceDumpExecutor(
+            final FutureJVppCore api) {
+        return (identifier, ifaceName) -> {
+            final SwInterfaceDump request = new SwInterfaceDump();
+            request.nameFilter = ifaceName.getBytes();
+            request.nameFilterValid = 1;
+
+            final CompletableFuture<SwInterfaceDetailsReplyDump>
+                    swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture();
+            return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier);
+        };
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java
new file mode 100644 (file)
index 0000000..7a6119b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.cache;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.inject.Named;
+
+public class InterfaceCacheDumpManagerProvider implements Provider<InterfaceCacheDumpManager> {
+
+    @Inject
+    private FutureJVppCore jvpp;
+
+    @Inject
+    @Named("interface-context")
+    private NamingContext namingContext;
+
+    @Override
+    public InterfaceCacheDumpManager get() {
+        return new InterfaceCacheDumpManagerImpl(jvpp, namingContext);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java
new file mode 100644 (file)
index 0000000..e34e915
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.cache;
+
+import io.fd.honeycomb.translate.util.read.cache.CacheKeyFactory;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class StaticCacheKeyFactory implements CacheKeyFactory<Void> {
+
+    private final String key;
+
+    public StaticCacheKeyFactory(@Nonnull final String key) {
+        this.key = key;
+    }
+
+    @Nonnull
+    @Override
+    public String createKey(@Nonnull final InstanceIdentifier<?> actualContextIdentifier,
+                            @Nullable final Void dumpParams) {
+        return key;
+    }
+
+    @Nonnull
+    @Override
+    public Class<?> getCachedDataType() {
+        return SwInterfaceDetailsReplyDump.class;
+    }
+}
index a681706..e53fccd 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfacesstate;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
-import io.fd.honeycomb.translate.read.ReadFailedException;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -34,18 +39,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Ethernet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.EthernetBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
 
 public class EthernetCustomizerTest extends ReaderCustomizerTest<Ethernet, EthernetBuilder> implements
-    InterfaceDumpHelper {
+        InterfaceDumpHelper {
     private static final String IFC_CTX_NAME = "ifc-test-instance";
     private static final String IF_NAME = "local0";
     private static final int IF_INDEX = 1;
     private static final InstanceIdentifier<Ethernet> IID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(Ethernet.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(VppInterfaceStateAugmentation.class).child(Ethernet.class);
     private NamingContext interfaceContext;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public EthernetCustomizerTest() {
         super(Ethernet.class, VppInterfaceStateAugmentationBuilder.class);
     }
@@ -58,15 +65,16 @@ public class EthernetCustomizerTest extends ReaderCustomizerTest<Ethernet, Ether
 
     @Override
     protected ReaderCustomizer<Ethernet, EthernetBuilder> initCustomizer() {
-        return new EthernetCustomizer(api, interfaceContext);
+        return new EthernetCustomizer(dumpCacheManager);
     }
 
-    private void testRead(final int linkDuplex, final EthernetStateAttributes.Duplex duplex) throws ReadFailedException {
+    private void testRead(final int linkDuplex, final EthernetStateAttributes.Duplex duplex)
+            throws ReadFailedException {
         final EthernetBuilder builder = mock(EthernetBuilder.class);
         final short mtu = 123;
-        whenSwInterfaceDumpThenReturn(api, ifaceDetails(mtu, linkDuplex));
+        when(dumpCacheManager.getInterfaceDetail(any(), any(), any())).thenReturn(ifaceDetails(mtu, linkDuplex));
         getCustomizer().readCurrentAttributes(IID, builder, ctx);
-        verify(builder).setMtu((int)mtu);
+        verify(builder).setMtu((int) mtu);
         verify(builder).setDuplex(duplex);
     }
 
@@ -74,7 +82,7 @@ public class EthernetCustomizerTest extends ReaderCustomizerTest<Ethernet, Ether
         final SwInterfaceDetails details = new SwInterfaceDetails();
         details.swIfIndex = IF_INDEX;
         details.linkMtu = mtu;
-        details.linkDuplex = (byte)duplex;
+        details.linkDuplex = (byte) duplex;
         return details;
     }
 
index 76e1b0a..806da68 100644 (file)
@@ -23,16 +23,23 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Map;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -41,11 +48,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Gre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.GreBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.VppInvocationException;
-import io.fd.vpp.jvpp.core.dto.GreTunnelDetails;
-import io.fd.vpp.jvpp.core.dto.GreTunnelDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.GreTunnelDump;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
 
 public class GreCustomizerTest extends ReaderCustomizerTest<Gre, GreBuilder> {
 
@@ -55,23 +57,25 @@ public class GreCustomizerTest extends ReaderCustomizerTest<Gre, GreBuilder> {
 
     private NamingContext interfacesContext;
     static final InstanceIdentifier<Gre> IID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(Gre.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceStateAugmentation.class).child(Gre.class);
+
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
 
     public GreCustomizerTest() {
         super(Gre.class, VppInterfaceStateAugmentationBuilder.class);
     }
 
     @Override
-    public void setUp() throws UnknownHostException, VppInvocationException {
+    public void setUp() throws UnknownHostException, VppInvocationException, ReadFailedException {
         interfacesContext = new NamingContext("gre-tunnel", IFC_CTX_NAME);
         defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
 
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "gre-tunnel4".getBytes();
-        final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
-        map.put(0, v);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IFACE_NAME)).thenReturn(v);
 
         final GreTunnelDetailsReplyDump value = new GreTunnelDetailsReplyDump();
         final GreTunnelDetails greTunnelDetails = new GreTunnelDetails();
@@ -103,29 +107,20 @@ public class GreCustomizerTest extends ReaderCustomizerTest<Gre, GreBuilder> {
         verify(api).greTunnelDump(any(GreTunnelDump.class));
     }
 
-    @Test(expected = NullPointerException.class)
-    public void testReadCurrentAttributesVppNameNotCached() throws Exception {
-        InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
-
-        final GreBuilder builder = getCustomizer().getBuilder(IID);
-        getCustomizer().readCurrentAttributes(IID, builder, ctx);
-    }
-
     @Test
     public void testReadCurrentAttributesWrongType() throws Exception {
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "tap-2".getBytes();
-        InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IFACE_NAME)).thenReturn(v);
 
         final GreBuilder builder = getCustomizer().getBuilder(IID);
         getCustomizer().readCurrentAttributes(IID, builder, ctx);
-
-        // Should be ignored
         verifyZeroInteractions(api);
     }
 
     @Override
     protected ReaderCustomizer<Gre, GreBuilder> initCustomizer() {
-        return new GreCustomizer(api, interfacesContext);
+        return new GreCustomizer(api, interfacesContext, dumpCacheManager);
     }
 }
\ No newline at end of file
index 2f8a30b..d8fa719 100644 (file)
 package io.fd.hc2vpp.v3po.interfacesstate;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
 import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Stream;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
@@ -39,12 +43,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.VppInvocationException;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
 
 public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface, InterfaceKey, InterfaceBuilder>
-    implements InterfaceDataTranslator, InterfaceDumpHelper {
+        implements InterfaceDataTranslator, InterfaceDumpHelper {
 
     private static final String IFC_CTX_NAME = "ifc-test-instance";
     private static final String IFACE0_NAME = "eth0";
@@ -57,6 +58,8 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
     private NamingContext interfacesContext;
     @Mock
     private DisabledInterfacesManager interfaceDisableContext;
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
 
     public InterfaceCustomizerTest() {
         super(Interface.class, InterfacesStateBuilder.class);
@@ -72,16 +75,7 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
 
     @Override
     protected ReaderCustomizer<Interface, InterfaceBuilder> initCustomizer() {
-        return new InterfaceCustomizer(api, interfacesContext, interfaceDisableContext);
-    }
-
-    private void verifySwInterfaceDumpWasInvoked(final int nameFilterValid, final String ifaceName,
-                                                 final int dumpIfcsInvocationCount)
-            throws VppInvocationException {
-        final SwInterfaceDump expected = new SwInterfaceDump();
-        expected.nameFilterValid = (byte) nameFilterValid;
-        expected.nameFilter = ifaceName.getBytes();
-        verify(api, times(dumpIfcsInvocationCount)).swInterfaceDump(expected);
+        return new InterfaceCustomizer(interfacesContext, interfaceDisableContext, dumpCacheManager);
     }
 
     private void assertIfacesAreEqual(final Interface iface, final SwInterfaceDetails details) {
@@ -102,31 +96,16 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
         iface.linkSpeed = 1;
         iface.l2AddressLength = 6;
         iface.l2Address = new byte[iface.l2AddressLength];
-        whenSwInterfaceDumpThenReturn(api, iface);
+        when(dumpCacheManager.getInterfaceDetail(id, ctx, IFACE0_NAME)).thenReturn(iface);
 
         getCustomizer().readCurrentAttributes(id, builder, ctx);
 
-        verifySwInterfaceDumpWasInvoked(1, IFACE0_NAME, 1);
-        assertIfacesAreEqual(builder.build(), iface);
-    }
+        final SwInterfaceDump request = new SwInterfaceDump();
+        request.nameFilter = IFACE0_NAME.getBytes();
+        request.nameFilterValid = 1;
 
-    @Test
-    public void testReadCurrentAttributesFailed() throws Exception {
-        final String ifaceName = IFACE0_NAME;
-        final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
-                .child(Interface.class, new InterfaceKey(ifaceName));
-        final InterfaceBuilder builder = getCustomizer().getBuilder(id);
-
-        whenSwInterfaceDumpThenReturn(api);
-
-        try {
-            getCustomizer().readCurrentAttributes(id, builder, ctx);
-        } catch (IllegalArgumentException e) {
-            verifySwInterfaceDumpWasInvoked(0, ifaceName, 2);
-            return;
-        }
-
-        fail("ReadFailedException was expected");
+        assertIfacesAreEqual(builder.build(), iface);
+        verify(dumpCacheManager, times(1)).getInterfaceDetail(id, ctx, IFACE0_NAME);
     }
 
     @Test
@@ -140,12 +119,16 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
         iface.swIfIndex = 2;
         iface.supSwIfIndex = 1;
         iface.subId = 1;
-        whenSwInterfaceDumpThenReturn(api, iface);
+        when(dumpCacheManager.getInterfaceDetail(id, ctx, SUB_IFACE_NAME)).thenReturn(iface);
 
         getCustomizer().readCurrentAttributes(id, builder, ctx);
 
-        verifySwInterfaceDumpWasInvoked(1, SUB_IFACE_NAME, 1);
+        final SwInterfaceDump request = new SwInterfaceDump();
+        request.nameFilter = SUB_IFACE_NAME.getBytes();
+        request.nameFilterValid = 1;
+
         verifyZeroInteractions(builder);
+        verify(dumpCacheManager, times(1)).getInterfaceDetail(id, ctx, SUB_IFACE_NAME);
     }
 
     @Test
@@ -166,16 +149,19 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
         swSubIf1.subId = 1;
         swSubIf1.supSwIfIndex = 1;
         swSubIf1.interfaceName = SUB_IFACE_NAME.getBytes();
-        whenSwInterfaceDumpThenReturn(api, swIf0, swIf1, swSubIf1);
+        when(dumpCacheManager.getInterfaces(id, ctx)).thenReturn(Stream.of(swIf0, swIf1, swSubIf1));
 
         final List<InterfaceKey> expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME), new InterfaceKey(
                 IFACE1_NAME));
         final List<InterfaceKey> actualIds = getCustomizer().getAllIds(id, ctx);
 
-        verifySwInterfaceDumpWasInvoked(0, "", 1);
+        final SwInterfaceDump request = new SwInterfaceDump();
+        request.nameFilter = "".getBytes();
+        request.nameFilterValid = 0;
 
         // sub-interface should not be on the list
         assertEquals(expectedIds, actualIds);
+        verify(dumpCacheManager, times(1)).getInterfaces(id, ctx);
     }
 
     @Test
@@ -191,12 +177,13 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface,
         final SwInterfaceDetails swIf1 = new SwInterfaceDetails();
         swIf1.swIfIndex = 1;
         swIf1.interfaceName = IFACE1_NAME.getBytes();
-        whenSwInterfaceDumpThenReturn(api, swIf0, swIf1);
+        when(dumpCacheManager.getInterfaces(id, ctx)).thenReturn(Stream.of(swIf0, swIf1));
 
         final List<InterfaceKey> expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME));
         final List<InterfaceKey> actualIds = getCustomizer().getAllIds(id, ctx);
 
         // disabled interface should not be on the list
         assertEquals(expectedIds, actualIds);
+        verify(dumpCacheManager, times(1)).getInterfaces(id, ctx);
     }
 }
index 63cb3d9..53934ff 100644 (file)
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainDetailsReplyDump;
@@ -34,6 +35,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -52,6 +54,9 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
     private NamingContext interfaceContext;
     private NamingContext bridgeDomainContext;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public L2CustomizerTest() {
         super(L2.class, VppInterfaceStateAugmentationBuilder.class);
     }
@@ -64,13 +69,13 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
 
     @Override
     protected ReaderCustomizer<L2, L2Builder> initCustomizer() {
-        return new L2Customizer(api, interfaceContext, bridgeDomainContext);
+        return new L2Customizer(api, interfaceContext, bridgeDomainContext, dumpCacheManager);
     }
 
     private InstanceIdentifier<L2> getL2Id(final String name) {
         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name))
-            .augmentation(
-                VppInterfaceStateAugmentation.class).child(L2.class);
+                .augmentation(
+                        VppInterfaceStateAugmentation.class).child(L2.class);
     }
 
     private void whenBridgeDomainDumpThenReturn(final List<BridgeDomainDetails> bridgeDomainDetails) {
@@ -101,7 +106,6 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
 
     @Test
     public void testRead() throws Exception {
-        final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
         final int ifId = 1;
         final int bdId = 1;
         final String bdName = "bd001";
@@ -111,8 +115,6 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
 
         final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
         ifaceDetails.subId = ifId;
-        cachedInterfaceDump.put(ifId, ifaceDetails);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
 
         // BVIinterfaceContext
         whenBridgeDomainDumpThenReturn(Collections.singletonList(generateBdDetails(ifId, ifId, bdId)));
@@ -124,7 +126,7 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
 
         // Not BVI
         whenBridgeDomainDumpThenReturn(Collections
-            .singletonList(generateBdDetails(ifId, 99 /* Different ifc is marked as BVI in bd details */, bdId)));
+                .singletonList(generateBdDetails(ifId, 99 /* Different ifc is marked as BVI in bd details */, bdId)));
 
         builder = mock(L2Builder.class);
         getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx);
@@ -136,7 +138,7 @@ public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
         final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails();
         bridgeDomainDetails.bviSwIfIndex = bviSwIfIndex;
         bridgeDomainDetails.bdId = bdId;
-        bridgeDomainDetails.swIfDetails = new BridgeDomainSwIf[] {generateBdSwIfDetails(ifId)};
+        bridgeDomainDetails.swIfDetails = new BridgeDomainSwIf[]{generateBdSwIfDetails(ifId)};
         return bridgeDomainDetails;
     }
 }
\ No newline at end of file
index dc748fe..887b3e3 100644 (file)
@@ -19,19 +19,20 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -40,9 +41,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.SubInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.RewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -60,6 +61,9 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest<Rewrite, Rewrite
     @Captor
     private ArgumentCaptor<List<PushTags>> captor;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public RewriteCustomizerTest() {
         super(Rewrite.class, L2Builder.class);
     }
@@ -72,14 +76,15 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest<Rewrite, Rewrite
 
     @Override
     protected ReaderCustomizer<Rewrite, RewriteBuilder> initCustomizer() {
-        return new RewriteCustomizer(api, interfacesContext);
+        return new RewriteCustomizer(dumpCacheManager);
     }
 
     private InstanceIdentifier<Rewrite> getVlanTagRewriteId(final String name, final long index) {
-        final Class<ChildOf<? super SubInterface>> child = (Class)Rewrite.class;
+        final Class<ChildOf<? super SubInterface>> child = (Class) Rewrite.class;
         final InstanceIdentifier id =
-                InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation(
-                        SubinterfaceStateAugmentation.class).child(SubInterfaces.class)
+                InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name))
+                        .augmentation(
+                                SubinterfaceStateAugmentation.class).child(SubInterfaces.class)
                         .child(SubInterface.class, new SubInterfaceKey(index))
                         .child(child);
         return id;
@@ -87,8 +92,6 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest<Rewrite, Rewrite
 
     @Test
     public void testRead() throws ReadFailedException {
-        final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
-
         final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
         ifaceDetails.subId = VLAN_ID;
         ifaceDetails.interfaceName = VLAN_IF_NAME.getBytes();
@@ -97,14 +100,13 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest<Rewrite, Rewrite
         ifaceDetails.vtrTag1 = 123;
         ifaceDetails.vtrTag2 = 321;
         ifaceDetails.vtrPushDot1Q = 1;
-        ifaceDetails.swIfIndex= VLAN_IF_INDEX;
+        ifaceDetails.swIfIndex = VLAN_IF_INDEX;
         ifaceDetails.supSwIfIndex = 2;
-        cachedInterfaceDump.put(VLAN_IF_INDEX, ifaceDetails);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
 
         final RewriteBuilder builder = mock(RewriteBuilder.class);
-
-        getCustomizer().readCurrentAttributes(getVlanTagRewriteId(IF_NAME, VLAN_ID), builder, ctx);
+        final InstanceIdentifier<Rewrite> vlanTagRewriteId = getVlanTagRewriteId(IF_NAME, VLAN_ID);
+        when(dumpCacheManager.getInterfaceDetail(vlanTagRewriteId, ctx, VLAN_IF_NAME)).thenReturn(ifaceDetails);
+        getCustomizer().readCurrentAttributes(vlanTagRewriteId, builder, ctx);
 
         verify(builder).setVlanType(_802dot1q.class);
         verify(builder).setPopTags((short) 2);
index 32e351e..c20e218 100644 (file)
@@ -20,18 +20,20 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
 import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.stream.Stream;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -46,8 +48,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Tags;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInterface, SubInterfaceKey, SubInterfaceBuilder> implements
-    InterfaceDumpHelper {
+public class SubInterfaceCustomizerTest
+        extends ListReaderCustomizerTest<SubInterface, SubInterfaceKey, SubInterfaceBuilder> implements
+        InterfaceDumpHelper {
 
     private static final String IFC_CTX_NAME = "ifc-test-instance";
     private static final String SUPER_IF_NAME = "local0";
@@ -58,6 +61,9 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInte
 
     private NamingContext interfacesContext;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public SubInterfaceCustomizerTest() {
         super(SubInterface.class, SubInterfacesBuilder.class);
     }
@@ -71,18 +77,18 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInte
 
     @Override
     protected ReaderCustomizer<SubInterface, SubInterfaceBuilder> initCustomizer() {
-        return new SubInterfaceCustomizer(api, interfacesContext);
+        return new SubInterfaceCustomizer(api, interfacesContext, dumpCacheManager);
     }
 
     private InstanceIdentifier<SubInterface> getSubInterfaceId(final String name, final long id) {
-        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation(
-                SubinterfaceStateAugmentation.class).child(
-                SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(id));
+        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name))
+                .augmentation(
+                        SubinterfaceStateAugmentation.class).child(
+                        SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(id));
     }
 
     @Test
     public void testRead() throws ReadFailedException {
-        final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
 
         final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
         ifaceDetails.subId = VLAN_IF_ID;
@@ -95,11 +101,12 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInte
         ifaceDetails.subOuterVlanIdAny = 1;
         ifaceDetails.subInnerVlanIdAny = 1;
         ifaceDetails.subExactMatch = 1;
-        cachedInterfaceDump.put(VLAN_IF_INDEX, ifaceDetails);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
 
         final SubInterfaceBuilder builder = mock(SubInterfaceBuilder.class);
-        getCustomizer().readCurrentAttributes(getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID), builder, ctx);
+        final InstanceIdentifier<SubInterface> subInterfaceId = getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID);
+
+        when(dumpCacheManager.getInterfaceDetail(subInterfaceId, ctx, VLAN_IF_NAME)).thenReturn(ifaceDetails);
+        getCustomizer().readCurrentAttributes(subInterfaceId, builder, ctx);
 
         verify(builder).setIdentifier((long) VLAN_IF_ID);
 
@@ -109,7 +116,7 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInte
 
         ArgumentCaptor<Match> matchCaptor = ArgumentCaptor.forClass(Match.class);
         verify(builder).setMatch(matchCaptor.capture());
-        final VlanTagged matchType = (VlanTagged)matchCaptor.getValue().getMatchType();
+        final VlanTagged matchType = (VlanTagged) matchCaptor.getValue().getMatchType();
         assertTrue(matchType.getVlanTagged().isMatchExactTags());
     }
 
@@ -120,10 +127,11 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInte
         iface.swIfIndex = VLAN_IF_INDEX;
         iface.subId = VLAN_IF_ID;
         iface.supSwIfIndex = SUPER_IF_INDEX;
-        whenSwInterfaceDumpThenReturn(api, iface);
 
+        final InstanceIdentifier<SubInterface> subInterfaceId = getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID);
+        when(dumpCacheManager.getInterfaces(subInterfaceId, ctx)).thenReturn(Stream.of(iface));
         final List<SubInterfaceKey> allIds =
-                getCustomizer().getAllIds(getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID), ctx);
+                getCustomizer().getAllIds(subInterfaceId, ctx);
 
         assertEquals(1, allIds.size());
     }
index 39aefb3..ebdf301 100644 (file)
@@ -22,9 +22,11 @@ import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -50,9 +52,13 @@ public class SubInterfaceL2CustomizerTest extends ReaderCustomizerTest<L2, L2Bui
     private static final long SUB_IF_ID = 1;
     private static final int SUB_IF_INDEX = 11;
     private InstanceIdentifier<L2> IID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(SubinterfaceStateAugmentation.class)
-            .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)).child(L2.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(SubinterfaceStateAugmentation.class)
+                    .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID))
+                    .child(L2.class);
+
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
 
     public SubInterfaceL2CustomizerTest() {
         super(L2.class, SubInterfaceBuilder.class);
@@ -68,13 +74,6 @@ public class SubInterfaceL2CustomizerTest extends ReaderCustomizerTest<L2, L2Bui
 
     @Override
     protected ReaderCustomizer<L2, L2Builder> initCustomizer() {
-        return new SubInterfaceL2Customizer(api, interfaceContext, bridgeDomainContext);
-    }
-
-    @Test(expected = ReadFailedException.class)
-    public void testReadFailed() throws ReadFailedException {
-        final L2Builder builder = mock(L2Builder.class);
-        when(api.swInterfaceDump(any())).thenReturn(failedFuture());
-        getCustomizer().readCurrentAttributes(IID, builder, ctx);
+        return new SubInterfaceL2Customizer(api, interfaceContext, bridgeDomainContext, dumpCacheManager);
     }
 }
\ No newline at end of file
index e268f7b..1fbefd6 100644 (file)
@@ -21,12 +21,17 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import io.fd.honeycomb.translate.read.ReadFailedException;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetailsReplyDump;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -35,9 +40,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.TapBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetailsReplyDump;
 
 public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> implements InterfaceDumpHelper {
 
@@ -46,10 +48,13 @@ public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> imp
     private static final String TAP_NAME = "testTapName";
     private static final int IF_INDEX = 1;
     private static final InstanceIdentifier<Tap> IID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(Tap.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(VppInterfaceStateAugmentation.class).child(Tap.class);
     private NamingContext interfaceContext;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public TapCustomizerTest() {
         super(Tap.class, VppInterfaceStateAugmentationBuilder.class);
     }
@@ -58,7 +63,7 @@ public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> imp
     protected void setUp() throws Exception {
         interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
         defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
-        whenSwInterfaceDumpThenReturn(api, ifaceDetails());
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(ifaceDetails());
     }
 
     private SwInterfaceDetails ifaceDetails() {
@@ -71,7 +76,7 @@ public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> imp
 
     @Override
     protected ReaderCustomizer<Tap, TapBuilder> initCustomizer() {
-        return new TapCustomizer(api, interfaceContext);
+        return new TapCustomizer(api, interfaceContext, dumpCacheManager);
     }
 
     @Test
index b83b74e..e58877e 100644 (file)
@@ -21,13 +21,18 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import io.fd.honeycomb.translate.read.ReadFailedException;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
 import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump;
 import java.math.BigInteger;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -37,21 +42,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VhostUser;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VhostUserBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump;
 
 public class VhostUserCustomizerTest extends ReaderCustomizerTest<VhostUser, VhostUserBuilder> implements
-    InterfaceDumpHelper {
+        InterfaceDumpHelper {
     private static final String IFC_CTX_NAME = "ifc-test-instance";
     private static final String IF_NAME = "VirtualEthernet1";
     private static final int IF_INDEX = 1;
     private static final InstanceIdentifier<VhostUser> IID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(VhostUser.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(VppInterfaceStateAugmentation.class).child(VhostUser.class);
 
     private NamingContext interfaceContext;
 
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
     public VhostUserCustomizerTest() {
         super(VhostUser.class, VppInterfaceStateAugmentationBuilder.class);
     }
@@ -60,7 +65,7 @@ public class VhostUserCustomizerTest extends ReaderCustomizerTest<VhostUser, Vho
     protected void setUp() throws Exception {
         interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
         defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
-        whenSwInterfaceDumpThenReturn(api, ifaceDetails());
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(ifaceDetails());
     }
 
     private SwInterfaceDetails ifaceDetails() {
@@ -73,7 +78,7 @@ public class VhostUserCustomizerTest extends ReaderCustomizerTest<VhostUser, Vho
 
     @Override
     protected ReaderCustomizer<VhostUser, VhostUserBuilder> initCustomizer() {
-        return new VhostUserCustomizer(api, interfaceContext);
+        return new VhostUserCustomizer(api, interfaceContext, dumpCacheManager);
     }
 
     @Test
index f5e659f..ba0cf2d 100644 (file)
@@ -23,13 +23,23 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
+import com.google.common.collect.Lists;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Map;
-
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -40,17 +50,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.collect.Lists;
-
-import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.vpp.jvpp.VppInvocationException;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump;
-
 public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilder> {
 
     private static final String IFC_CTX_NAME = "ifc-test-instance";
@@ -60,22 +59,24 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilde
     private NamingContext interfacesContext;
     static final InstanceIdentifier<Vxlan> IID =
             InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class);
+                    .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class);
+
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
 
     public VxlanCustomizerTest() {
         super(Vxlan.class, VppInterfaceStateAugmentationBuilder.class);
     }
 
     @Override
-    public void setUp() throws UnknownHostException, VppInvocationException {
+    public void setUp() throws UnknownHostException, VppInvocationException, ReadFailedException {
         interfacesContext = new NamingContext("vxlan-tunnel", IFC_CTX_NAME);
         defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
 
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "vxlan-tunnel4".getBytes();
-        final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
-        map.put(0, v);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(v);
 
         final VxlanTunnelDetailsReplyDump value = new VxlanTunnelDetailsReplyDump();
         final VxlanTunnelDetails vxlanTunnelDetails = new VxlanTunnelDetails();
@@ -110,9 +111,10 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilde
         verify(api).vxlanTunnelDump(any(VxlanTunnelDump.class));
     }
 
-    @Test(expected = NullPointerException.class)
+    @Test(expected = IllegalArgumentException.class)
     public void testReadCurrentAttributesVppNameNotCached() throws Exception {
-        InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME))
+                .thenThrow(new IllegalArgumentException("Detail for interface not found"));
 
         final VxlanBuilder builder = getCustomizer().getBuilder(IID);
         getCustomizer().readCurrentAttributes(IID, builder, ctx);
@@ -122,7 +124,8 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilde
     public void testReadCurrentAttributesWrongType() throws Exception {
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "tap-2".getBytes();
-        InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(v);
 
         final VxlanBuilder builder = getCustomizer().getBuilder(IID);
         getCustomizer().readCurrentAttributes(IID, builder, ctx);
@@ -133,6 +136,6 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilde
 
     @Override
     protected ReaderCustomizer<Vxlan, VxlanBuilder> initCustomizer() {
-        return new VxlanCustomizer(api, interfacesContext);
+        return new VxlanCustomizer(api, interfacesContext, dumpCacheManager);
     }
 }
\ No newline at end of file
index f8f1e14..ce79430 100644 (file)
@@ -19,20 +19,28 @@ package io.fd.hc2vpp.v3po.interfacesstate;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
-import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Map;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -41,11 +49,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanGpeBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.VppBaseCallException;
-import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
-import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails;
-import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump;
-import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump;
 
 public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, VxlanGpeBuilder> {
 
@@ -55,23 +58,25 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, Vxlan
 
     private NamingContext interfacesContext;
     private static final InstanceIdentifier<VxlanGpe> VXLAN_GPE_ID =
-        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
-            .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class);
+            InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class);
+
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
 
     public VxlanGpeCustomizerTest() {
         super(VxlanGpe.class, VppInterfaceStateAugmentationBuilder.class);
     }
 
     @Override
-    public void setUp() throws UnknownHostException, VppBaseCallException {
+    public void setUp() throws UnknownHostException, VppBaseCallException, ReadFailedException {
         interfacesContext = new NamingContext("vxlan_gpe_inf", IFC_CTX_NAME);
         defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
 
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "vxlan_gpe_inf2".getBytes();
-        final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
-        map.put(0, v);
-        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+        when(dumpCacheManager.getInterfaceDetail(any(), any(), matches(IF_NAME))).thenReturn(v);
 
         final VxlanGpeTunnelDetailsReplyDump value = new VxlanGpeTunnelDetailsReplyDump();
         final VxlanGpeTunnelDetails vxlanGpeTunnelDetails = new VxlanGpeTunnelDetails();
@@ -108,9 +113,10 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, Vxlan
         verify(api).vxlanGpeTunnelDump(any(VxlanGpeTunnelDump.class));
     }
 
-    @Test(expected = NullPointerException.class)
+    @Test(expected = IllegalArgumentException.class)
     public void testReadCurrentAttributesVppNameNotCached() throws Exception {
-        InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
+        when(dumpCacheManager.getInterfaceDetail(VXLAN_GPE_ID, ctx, IF_NAME))
+                .thenThrow(new IllegalArgumentException("Detail for interface not found"));
 
         final VxlanGpeBuilder builder = getCustomizer().getBuilder(VXLAN_GPE_ID);
         getCustomizer().readCurrentAttributes(VXLAN_GPE_ID, builder, ctx);
@@ -120,18 +126,17 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, Vxlan
     public void testReadCurrentAttributesWrongType() throws Exception {
         final SwInterfaceDetails v = new SwInterfaceDetails();
         v.interfaceName = "tap-3".getBytes();
-        InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+        when(dumpCacheManager.getInterfaceDetail(VXLAN_GPE_ID, ctx, IF_NAME)).thenReturn(v);
 
         final VxlanGpeBuilder builder = getCustomizer().getBuilder(VXLAN_GPE_ID);
         getCustomizer().readCurrentAttributes(VXLAN_GPE_ID, builder, ctx);
-
-        // Should be ignored
         verifyZeroInteractions(api);
     }
 
     @Override
     protected ReaderCustomizer<VxlanGpe, VxlanGpeBuilder> initCustomizer() {
-        return new VxlanGpeCustomizer(api, interfacesContext);
+        return new VxlanGpeCustomizer(api, interfacesContext, dumpCacheManager);
     }
 }
 
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java
new file mode 100644 (file)
index 0000000..6f47f16
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.cache;
+
+import static io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManagerImpl.BY_NAME_INDEX_KEY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.test.util.FutureProducer;
+import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceCacheDumpManagerImplTest implements NamingContextHelper, FutureProducer {
+
+    private static final String IFACE_0 = "iface-0";
+    private static final String IFACE_1 = "iface-1";
+    private static final String IFACE_2 = "iface-2";
+    private static final String IFACE_3 = "iface-3";
+
+    @Mock
+    private FutureJVppCore jvpp;
+    @Mock
+    private ReadContext ctx;
+    @Mock
+    private MappingContext mappingContext;
+
+    private InstanceIdentifier<Interface> identifier;
+    private InstanceIdentifier<Interface> identifierThree;
+    private NamingContext namingContext;
+    private ModificationCache cache;
+    private InterfaceCacheDumpManagerImpl manager;
+
+    @Before
+    public void setUp() throws Exception {
+        initMocks(this);
+        namingContext = new NamingContext("interface-", "interface-context");
+        cache = new ModificationCache();
+        manager = new InterfaceCacheDumpManagerImpl(jvpp, namingContext);
+        when(ctx.getModificationCache()).thenReturn(cache);
+        when(ctx.getMappingContext()).thenReturn(mappingContext);
+        identifier = InstanceIdentifier.create(InterfacesState.class)
+                .child(Interface.class, new InterfaceKey(IFACE_0));
+
+        identifierThree = InstanceIdentifier.create(InterfacesState.class)
+                .child(Interface.class, new InterfaceKey(IFACE_3));
+
+        when(jvpp.swInterfaceDump(fullRequest())).thenReturn(future(fullReply()));
+
+        // this one is not in full dump
+        when(jvpp.swInterfaceDump(specificRequest(IFACE_3))).thenReturn(future(specificReplyThree()));
+        defineMapping(mappingContext, IFACE_0, 0, "interface-context");
+        defineMapping(mappingContext, IFACE_1, 1, "interface-context");
+        defineMapping(mappingContext, IFACE_2, 2, "interface-context");
+        defineMapping(mappingContext, IFACE_3, 3, "interface-context");
+    }
+
+    @Test
+    public void getInterfaces() throws Exception {
+        assertFalse(cache.containsKey(BY_NAME_INDEX_KEY));
+        final List<SwInterfaceDetails> interfaces = manager.getInterfaces(identifier, ctx).collect(Collectors.toList());
+        assertEquals(3, interfaces.size());
+        assertTrue(interfaces.contains(detailZero()));
+        assertTrue(interfaces.contains(detailOne()));
+        assertTrue(interfaces.contains(detailTwo()));
+
+        // first request must call jvpp
+        verify(jvpp, times(1)).swInterfaceDump(fullRequest());
+        assertTrue(cache.containsKey(BY_NAME_INDEX_KEY));
+
+        // then cached value should be returned
+        final List<SwInterfaceDetails> cachedInterfaces =
+                manager.getInterfaces(identifier, ctx).collect(Collectors.toList());
+        assertEquals(3, cachedInterfaces.size());
+        assertTrue(cachedInterfaces.contains(detailZero()));
+        assertTrue(cachedInterfaces.contains(detailOne()));
+        assertTrue(cachedInterfaces.contains(detailTwo()));
+
+        //verify that dump wasn't invoked again
+        verifyNoMoreInteractions(jvpp);
+    }
+
+    @Test
+    public void getInterfaceDetailFromCache() throws Exception {
+        final HashMap<Object, Object> cachedMap = new HashMap<>();
+        final SwInterfaceDetails detailZero = detailZero();
+        cachedMap.put(IFACE_0, detailZero);
+        cache.put(BY_NAME_INDEX_KEY, cachedMap);
+        when(jvpp.swInterfaceDump(specificRequest(IFACE_0))).thenReturn(future(specificReplyZero()));
+        final SwInterfaceDetails interfaceDetail = manager.getInterfaceDetail(identifier, ctx, IFACE_0);
+        assertEquals(detailZero, interfaceDetail);
+
+        // must not call jvpp, just get it from cache
+        verifyZeroInteractions(jvpp);
+    }
+
+    @Test
+    public void getInterfaceDetailNotInFullDump() throws Exception {
+        assertFalse(cache.containsKey(BY_NAME_INDEX_KEY));
+        final SwInterfaceDetails specificDetail = manager.getInterfaceDetail(identifierThree, ctx, IFACE_3);
+        assertEquals(detailThree(), specificDetail);
+
+        verify(jvpp, times(1)).swInterfaceDump(specificRequest(IFACE_3));
+    }
+
+    private SwInterfaceDetailsReplyDump fullReply() {
+        final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump();
+        reply.swInterfaceDetails = Arrays.asList(detailZero(), detailOne(), detailTwo());
+        return reply;
+    }
+
+    private static SwInterfaceDetails detailTwo() {
+        SwInterfaceDetails detail3 = new SwInterfaceDetails();
+        detail3.swIfIndex = 2;
+        detail3.interfaceName = IFACE_2.getBytes();
+        return detail3;
+    }
+
+    private static SwInterfaceDetails detailOne() {
+        SwInterfaceDetails detail2 = new SwInterfaceDetails();
+        detail2.swIfIndex = 1;
+        detail2.interfaceName = IFACE_1.getBytes();
+        return detail2;
+    }
+
+    private static SwInterfaceDetails detailThree() {
+        SwInterfaceDetails detail2 = new SwInterfaceDetails();
+        detail2.swIfIndex = 3;
+        detail2.interfaceName = IFACE_3.getBytes();
+        return detail2;
+    }
+
+    private static SwInterfaceDetails detailZero() {
+        SwInterfaceDetails detail1 = new SwInterfaceDetails();
+        detail1.swIfIndex = 0;
+        detail1.interfaceName = IFACE_0.getBytes();
+        return detail1;
+    }
+
+    private SwInterfaceDetailsReplyDump specificReplyThree() {
+        final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump();
+        reply.swInterfaceDetails = Arrays.asList(detailThree());
+        return reply;
+    }
+
+    private SwInterfaceDetailsReplyDump specificReplyZero() {
+        final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump();
+        reply.swInterfaceDetails = Arrays.asList(detailZero());
+        return reply;
+    }
+
+    private static SwInterfaceDump specificRequest(final String ifaceName) {
+        final SwInterfaceDump specificRequest = new SwInterfaceDump();
+        specificRequest.nameFilterValid = 1;
+        specificRequest.nameFilter = ifaceName.getBytes();
+        return specificRequest;
+    }
+
+    private static SwInterfaceDump fullRequest() {
+        final SwInterfaceDump fullRequest = new SwInterfaceDump();
+        fullRequest.nameFilterValid = 0;
+        fullRequest.nameFilter = "".getBytes();
+        return fullRequest;
+    }
+}
\ No newline at end of file