From 5543345d32514bfa38292a5080e57b915e39ea1d Mon Sep 17 00:00:00 2001 From: Michal Cmarada Date: Mon, 27 May 2019 13:54:02 +0200 Subject: HC2VPP-411: remove deprecated interface-state - new ietf-interfaces obsoletes interfaces-state container, only interfaces container should be used from now on. Change-Id: Ifb24611a3dca987bdf6b029d32e01d9b1f479fe8 Signed-off-by: Michal Cmarada --- .../v3po/read/cache/InterfaceCacheDumpManager.java | 59 ++++++ .../read/cache/InterfaceCacheDumpManagerImpl.java | 202 +++++++++++++++++++++ .../cache/InterfaceCacheDumpManagerProvider.java | 38 ++++ .../read/cache/InterfaceStatisticsManager.java | 26 +++ .../read/cache/InterfaceStatisticsManagerImpl.java | 37 ++++ .../cache/InterfaceStatisticsManagerProvider.java | 27 +++ 6 files changed, 389 insertions(+) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java (limited to 'v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java new file mode 100644 index 000000000..3d8df7e6c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java @@ -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.read.cache; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.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 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/read/cache/InterfaceCacheDumpManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java new file mode 100644 index 000000000..0aee8e459 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java @@ -0,0 +1,202 @@ +/* + * 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.read.cache; + +import static io.fd.hc2vpp.common.translate.util.JvppReplyConsumer.INSTANCE; +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.honeycomb.translate.util.read.cache.StaticCacheKeyFactory; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.dto.SwInterfaceDetailsReplyDump; +import io.fd.jvpp.core.dto.SwInterfaceDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import io.fd.jvpp.core.types.InterfaceIndex; +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 specificDumpManager; + private final DumpCacheManager fullDumpManager; + + InterfaceCacheDumpManagerImpl(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext namingContext) { + this.namingContext = namingContext; + specificDumpManager = specificInterfaceDumpManager(jvpp); + fullDumpManager = fullInterfaceDumpManager(jvpp, + new StaticCacheKeyFactory(InterfaceCacheDumpManagerImpl.class.getName() + "_dump", SwInterfaceDetailsReplyDump.class)); + } + + @Override + @Nonnull + public synchronized Stream 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 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) + .orElse(new SwInterfaceDetailsReplyDump()); + + if (reply.swInterfaceDetails.isEmpty()) { + return null; + } + + return reply.swInterfaceDetails.get(0); + } + + private Map 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) + .orElse(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 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 getMap(final ReadContext ctx) { + return (Map) ctx.getModificationCache().get(BY_NAME_INDEX_KEY); + } + + private static void putMap(final Map map, final ReadContext ctx) { + ctx.getModificationCache().put(BY_NAME_INDEX_KEY, map); + } + + + private static DumpCacheManager fullInterfaceDumpManager( + final FutureJVppCore jvpp, + final StaticCacheKeyFactory cacheKeyFactory) { + return new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(fullInterfaceDumpExecutor(jvpp)) + .withCacheKeyFactory(cacheKeyFactory) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static DumpCacheManager specificInterfaceDumpManager( + final FutureJVppCore jvpp) { + return new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(specificInterfaceDumpExecutor(jvpp)) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static EntityDumpExecutor fullInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, params) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.swIfIndex = new InterfaceIndex(); + request.swIfIndex.interfaceindex = ~0; + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } + + private static EntityDumpExecutor specificInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, ifaceName) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.swIfIndex = new InterfaceIndex(); + request.swIfIndex.interfaceindex =~0; + request.nameFilter = ifaceName.getBytes(); + request.nameFilterValid = 1; + + final CompletableFuture + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java new file mode 100644 index 000000000..6fb4f730f --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java @@ -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.read.cache; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.inject.Named; + +public class InterfaceCacheDumpManagerProvider implements Provider { + + @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/read/cache/InterfaceStatisticsManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java new file mode 100644 index 000000000..d23f06eac --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.read.cache; + +public interface InterfaceStatisticsManager { + + boolean isStatisticsEnabled(); + + void enableStatistics(); + + void disableStatistics(); +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java new file mode 100644 index 000000000..8450d3484 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.read.cache; + +public class InterfaceStatisticsManagerImpl implements InterfaceStatisticsManager { + + private boolean isEnabled; + + @Override + public boolean isStatisticsEnabled() { + return isEnabled; + } + + @Override + public void enableStatistics() { + isEnabled = true; + } + + @Override + public void disableStatistics() { + isEnabled = false; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java new file mode 100644 index 000000000..b62487b56 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.read.cache; + +import com.google.inject.Provider; + +public class InterfaceStatisticsManagerProvider implements Provider { + + @Override + public InterfaceStatisticsManager get() { + return new InterfaceStatisticsManagerImpl(); + } +} -- cgit 1.2.3-korg