HONEYCOMB-105 Make interface notification creation thread safe
authorMaros Marsalek <[email protected]>
Wed, 29 Jun 2016 14:01:40 +0000 (16:01 +0200)
committerMaros Marsalek <[email protected]>
Wed, 29 Jun 2016 14:06:48 +0000 (16:06 +0200)
Change-Id: Ife48ff6ed3c8290f223fd14df1366927923bad30
Signed-off-by: Maros Marsalek <[email protected]>
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducer.java
v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/NamingContext.java

index 8ca63c1..002d58b 100644 (file)
@@ -15,6 +15,7 @@
  */
 package io.fd.honeycomb.v3po.translate.v3po.notification;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import io.fd.honeycomb.v3po.notification.ManagedNotificationProducer;
 import io.fd.honeycomb.v3po.notification.NotificationCollector;
@@ -74,13 +75,14 @@ public final class InterfaceChangeNotificationProducer implements ManagedNotific
         notificationListenerReg = jvpp.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(
             swInterfaceSetFlagsNotification -> {
                 LOG.trace("Interface notification received: {}", swInterfaceSetFlagsNotification);
+                // TODO this should be lazy
                 collector.onNotification(transformNotification(swInterfaceSetFlagsNotification));
             }
         );
     }
 
     private Notification transformNotification(final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification) {
-        if(swInterfaceSetFlagsNotification.deleted == 1) {
+        if (swInterfaceSetFlagsNotification.deleted == 1) {
             return new InterfaceDeletedBuilder().setName(getIfcName(swInterfaceSetFlagsNotification)).build();
         } else {
             return new InterfaceStateChangeBuilder()
@@ -95,12 +97,14 @@ public final class InterfaceChangeNotificationProducer implements ManagedNotific
      * Get mapped name for the interface. Best effort only! The mapping might not yet be stored in context
      * data tree (write transaction is still in progress and context changes have not been committed yet, or
      * VPP sends the notification before it returns create request(that would store mapping)).
-     *
+     * <p/>
      * In case mapping is not available, index is used as name. TODO inconsistent behavior, maybe just use indices ?
      */
     private InterfaceNameOrIndex getIfcName(final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification) {
-        return interfaceContext.containsName(swInterfaceSetFlagsNotification.swIfIndex, mappingContext)
-            ? new InterfaceNameOrIndex(interfaceContext.getName(swInterfaceSetFlagsNotification.swIfIndex, mappingContext))
+        final Optional<String> optionalName =
+                interfaceContext.getNameIfPresent(swInterfaceSetFlagsNotification.swIfIndex, mappingContext);
+        return optionalName.isPresent()
+            ? new InterfaceNameOrIndex(optionalName.get())
             : new InterfaceNameOrIndex((long) swInterfaceSetFlagsNotification.swIfIndex);
     }
 
@@ -130,9 +134,9 @@ public final class InterfaceChangeNotificationProducer implements ManagedNotific
             LOG.warn("Unable to {} interface notifications", enableDisable == 1 ? "enable" : "disable",  e);
             throw new IllegalStateException("Unable to control interface notifications", e);
         }
-
     }
 
+    @Nonnull
     @Override
     public Collection<Class<? extends Notification>> getNotificationTypes() {
         final ArrayList<Class<? extends Notification>> classes = Lists.newArrayList();
index bcc980d..dc77106 100644 (file)
@@ -76,6 +76,9 @@ public final class NamingContext implements AutoCloseable {
         if (!containsName(index, mappingContext)) {
             final String artificialName = getArtificialName(index);
             LOG.info("Assigning artificial name: {} for index: {}", artificialName, index);
+            for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
+                LOG.error("{}", stackTraceElement.toString());
+            }
             addName(index, artificialName, mappingContext);
         }
 
@@ -87,6 +90,27 @@ public final class NamingContext implements AutoCloseable {
             .collect(SINGLE_ITEM_COLLECTOR).getName();
     }
 
+    /**
+     * Retrieve name for mapping stored provided mappingContext instance. if present
+     *
+     * @param index index of a mapped item
+     * @param mappingContext mapping context providing context data for current transaction
+     *
+     * @return name mapped to provided index
+     */
+    @Nonnull
+    public synchronized Optional<String> getNameIfPresent(final int index,
+                                                          @Nonnull final MappingContext mappingContext) {
+        final Optional<Mappings> read = mappingContext.read(namingContextIid.child(Mappings.class));
+
+        return read.isPresent()
+                ? Optional.of(read.get().getMapping().stream()
+                    .filter(mapping -> mapping.getIndex().equals(index))
+                    .collect(SINGLE_ITEM_COLLECTOR)
+                    .getName())
+                : Optional.absent();
+    }
+
     /**
      * Check whether mapping is present for index.
      *