HONEYCOMB-9: Add Read context
authorMaros Marsalek <[email protected]>
Tue, 12 Apr 2016 08:13:06 +0000 (10:13 +0200)
committerMaros Marsalek <[email protected]>
Tue, 12 Apr 2016 08:13:06 +0000 (10:13 +0200)
Change-Id: I42179d5c7244bfe4c62ee1efffad414a1cfe4b0b
Signed-off-by: Maros Marsalek <[email protected]>
23 files changed:
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReadContext.java [new file with mode: 0644]
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/ListVppReaderCustomizer.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/NoopReaderCustomizer.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/Context.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java
v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java
v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTreeTest.java
v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateTest.java

index 9f34fcb..1982bc7 100644 (file)
@@ -107,9 +107,7 @@ public final class VppConfigDataTree implements VppDataTree {
         final DOMDataReadOnlyTransaction beforeTx = new VppReadOnlyTransaction(EMPTY_OPERATIONAL, takeSnapshot());
         final ConfigSnapshot modificationSnapshot = new ConfigSnapshot(modification);
         final DOMDataReadOnlyTransaction afterTx = new VppReadOnlyTransaction(EMPTY_OPERATIONAL, modificationSnapshot);
-        final WriteContext ctx = new TransactionWriteContext(serializer, beforeTx, afterTx);
-
-        try {
+        try(final WriteContext ctx = new TransactionWriteContext(serializer, beforeTx, afterTx)) {
             writer.update(nodesBefore, nodesAfter, ctx);
         } catch (WriterRegistry.BulkUpdateException e) {
             LOG.warn("Failed to apply all changes", e);
index d0acd05..d73c22a 100644 (file)
@@ -27,7 +27,9 @@ import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import java.util.Collection;
 import java.util.Map;
 import javax.annotation.Nonnull;
@@ -82,11 +84,11 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
             org.opendaylight.controller.md.sal.common.api.data.ReadFailedException> read(
             @Nonnull final YangInstanceIdentifier yangInstanceIdentifier) {
 
-        try {
+        try(ReadContext ctx = new ReadContextImpl()) {
             if (checkNotNull(yangInstanceIdentifier).equals(YangInstanceIdentifier.EMPTY)) {
-                return Futures.immediateCheckedFuture(readRoot());
+                return Futures.immediateCheckedFuture(readRoot(ctx));
             } else {
-                return Futures.immediateCheckedFuture(readNode(yangInstanceIdentifier));
+                return Futures.immediateCheckedFuture(readNode(yangInstanceIdentifier, ctx));
             }
         } catch (ReadFailedException e) {
             return Futures.immediateFailedCheckedFuture(
@@ -95,7 +97,8 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
         }
     }
 
-    private Optional<NormalizedNode<?, ?>> readNode(final YangInstanceIdentifier yangInstanceIdentifier)
+    private Optional<NormalizedNode<?, ?>> readNode(final YangInstanceIdentifier yangInstanceIdentifier,
+                                                    final ReadContext ctx)
             throws ReadFailedException {
         LOG.debug("VppOperationalDataTree.readNode(), yangInstanceIdentifier={}", yangInstanceIdentifier);
         final InstanceIdentifier<?> path = serializer.fromYangInstanceIdentifier(yangInstanceIdentifier);
@@ -104,7 +107,7 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
 
         final Optional<? extends DataObject> dataObject;
 
-        dataObject = readerRegistry.read(path);
+        dataObject = readerRegistry.read(path, ctx);
         if (dataObject.isPresent()) {
             final NormalizedNode<?, ?> value = toNormalizedNodeFunction(path).apply(dataObject.get());
             return Optional.<NormalizedNode<?, ?>>fromNullable(value);
@@ -113,7 +116,7 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
         }
     }
 
-    private Optional<NormalizedNode<?, ?>> readRoot() throws ReadFailedException {
+    private Optional<NormalizedNode<?, ?>> readRoot(final ReadContext ctx) throws ReadFailedException {
         LOG.debug("VppOperationalDataTree.readRoot()");
 
         final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> dataNodeBuilder =
@@ -121,7 +124,7 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
                         .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(SchemaContext.NAME));
 
         final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects =
-                readerRegistry.readAll();
+                readerRegistry.readAll(ctx);
 
         for (final InstanceIdentifier<? extends DataObject> instanceIdentifier : dataObjects.keySet()) {
             final YangInstanceIdentifier rootElementId = serializer.toYangInstanceIdentifier(instanceIdentifier);
@@ -187,4 +190,20 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
             }
         };
     }
+
+    private static final class ReadContextImpl implements ReadContext {
+        public final Context ctx = new Context();
+
+        @Nonnull
+        @Override
+        public Context getContext() {
+            return ctx;
+        }
+
+        @Override
+        public void close() {
+            // Make sure to clear the storage in case some customizer stored it  to prevent memory leaks
+            ctx.close();
+        }
+    }
 }
index 72d17b7..fc6a51a 100644 (file)
@@ -20,6 +20,7 @@ import com.google.common.base.Optional;
 import com.google.common.collect.Multimap;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
 import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.CompositeChildVppReader;
@@ -96,16 +97,16 @@ public class VppReaderRegistry implements ReaderRegistry {
 
     @Nonnull
     @Override
-    public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll()
-            throws io.fd.honeycomb.v3po.impl.trans.ReadFailedException {
-        return reader.readAll();
+    public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll(
+        @Nonnull final ReadContext ctx) throws io.fd.honeycomb.v3po.impl.trans.ReadFailedException {
+        return reader.readAll(ctx);
     }
 
     @Nonnull
     @Override
-    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id)
-            throws ReadFailedException {
-        return reader.read(id);
+    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+                                               @Nonnull final ReadContext ctx) throws ReadFailedException {
+        return reader.read(id, ctx);
     }
 
     @Nonnull
index aad3080..8135e8c 100644 (file)
@@ -39,10 +39,13 @@ public interface ChildVppReader<C extends DataObject> extends VppReader<C> {
      *                      determine the exact position within more complex subtrees.
      * @param parentBuilder Builder of parent DataObject. Objects read on this level (if any) must be placed into the
      *                      parent builder.
+     * @param ctx Read context
+     *
      * @throws ReadFailedException if read was unsuccessful
      */
     void read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
-              @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException;
+              @Nonnull final Builder<? extends DataObject> parentBuilder,
+              @Nonnull final ReadContext ctx) throws ReadFailedException;
 
 }
 
index ce392c6..e37c766 100644 (file)
@@ -37,10 +37,12 @@ public interface ListVppReader<D extends DataObject & Identifiable<K>, K extends
      * Read all elements in this list
      *
      * @param id Wildcarded identifier of list managed by this reader
+     * @param ctx Read context
      *
      * @return List of all entries in this list
      * @throws ReadFailedException if read was unsuccessful
      */
     @Nonnull
-    List<D> readList(@Nonnull final InstanceIdentifier<D> id) throws ReadFailedException;
+    List<D> readList(@Nonnull final InstanceIdentifier<D> id,
+                     @Nonnull final ReadContext ctx) throws ReadFailedException;
 }
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReadContext.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReadContext.java
new file mode 100644 (file)
index 0000000..6aa64b3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 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.honeycomb.v3po.impl.trans.r;
+
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
+import javax.annotation.Nonnull;
+
+/**
+ * Read Context
+ */
+public interface ReadContext extends AutoCloseable {
+
+    /**
+     * Get key value storage for customizers
+     *
+     * @return Context for customizers
+     */
+    @Nonnull
+    Context getContext();
+
+    @Override
+    void close();
+}
index 6a99376..a117553 100644 (file)
@@ -33,10 +33,12 @@ public interface ReaderRegistry extends VppReader<DataObject> {
      * Performs read on all registered root readers and merges the results into a Multimap. Keys represent identifiers
      * for root DataObjects from the data tree modeled by YANG.
      *
+     * @param ctx Read context
+     *
      * @return multimap that preserves deterministic iteration order across non-distinct key values
      * @throws ReadFailedException if read was unsuccessful
      */
     @Nonnull
-    Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll()
+    Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll(@Nonnull final ReadContext ctx)
             throws ReadFailedException;
 }
index 02189e4..ff42b57 100644 (file)
@@ -32,8 +32,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 @Beta
 public interface VppReader<D extends DataObject> extends SubtreeManager<D> {
 
-    // TODO add vpp read context that will be shared by all readers during a single read to keep useful information
-    // preventing possible duplicate reads from VPP
     // TODO make async
 
     /**
@@ -42,11 +40,13 @@ public interface VppReader<D extends DataObject> extends SubtreeManager<D> {
      * @param id unique identifier of subtree to be read. The subtree must contain managed data object type. For
      *           identifiers pointing below node managed by this reader, it's reader's responsibility to filter out the
      *           right node or to delegate the read to a child reader.
+     * @param ctx Read context
+     *
      * @return List of DataObjects identified by id. If the ID points to a single node, it will be wrapped in a list
      * @throws ReadFailedException if read was unsuccessful
      */
     @Nonnull
-    Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) throws
-            ReadFailedException;
+    Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+                                        @Nonnull ReadContext ctx) throws ReadFailedException;
 
 }
index 061cfc9..436aace 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
 import io.fd.honeycomb.v3po.impl.trans.util.ReflectionUtils;
 import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
@@ -68,8 +69,10 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
 
     /**
      * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present.
+     *
      */
-    protected Optional<D> readCurrent(final InstanceIdentifier<D> id) throws
+    protected Optional<D> readCurrent(final InstanceIdentifier<D> id,
+                                      @Nonnull final ReadContext ctx) throws
             ReadFailedException {
         LOG.debug("{}: Reading current: {}", this, id);
         final B builder = getBuilder(id);
@@ -77,17 +80,17 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
         final D emptyValue = builder.build();
 
         LOG.trace("{}: Reading current attributes", this);
-        readCurrentAttributes(id, builder);
+        readCurrentAttributes(id, builder, ctx);
 
         // TODO expect exceptions from reader
         for (ChildVppReader<? extends ChildOf<D>> child : childReaders.values()) {
             LOG.debug("{}: Reading child from: {}", this, child);
-            child.read(id, builder);
+            child.read(id, builder, ctx);
         }
 
         for (ChildVppReader<? extends Augmentation<D>> child : augReaders.values()) {
             LOG.debug("{}: Reading augment from: {}", this, child);
-            child.read(id, builder);
+            child.read(id, builder, ctx);
         }
 
         // Need to check whether anything was filled in to determine if data is present or not.
@@ -103,17 +106,19 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
     @Nonnull
     @Override
     @SuppressWarnings("unchecked")
-    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id)
+    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+                                               @Nonnull final ReadContext ctx)
             throws ReadFailedException {
         LOG.trace("{}: Reading : {}", this, id);
         if (id.getTargetType().equals(getManagedDataObjectType().getTargetType())) {
-            return readCurrent((InstanceIdentifier<D>) id);
+            return readCurrent((InstanceIdentifier<D>) id, ctx);
         } else {
-            return readSubtree(id);
+            return readSubtree(id, ctx);
         }
     }
 
-    private Optional<? extends DataObject> readSubtree(final InstanceIdentifier<? extends DataObject> id)
+    private Optional<? extends DataObject> readSubtree(final InstanceIdentifier<? extends DataObject> id,
+                                                       @Nonnull final ReadContext ctx)
             throws ReadFailedException {
         LOG.debug("{}: Reading subtree: {}", this, id);
         final Class<? extends DataObject> next = VppRWUtils.getNextId(id, getManagedDataObjectType()).getType();
@@ -121,12 +126,12 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
 
         if (vppReader != null) {
             LOG.debug("{}: Reading subtree: {} from: {}", this, id, vppReader);
-            return vppReader.read(id);
+            return vppReader.read(id, ctx);
         } else {
             LOG.debug("{}: Dedicated subtree reader missing for: {}. Reading current and filtering", this, next);
             // If there's no dedicated reader, use read current
             final InstanceIdentifier<D> currentId = VppRWUtils.cutId(id, getManagedDataObjectType());
-            final Optional<D> current = readCurrent(currentId);
+            final Optional<D> current = readCurrent(currentId, ctx);
             // then perform post-reading filtering (return only requested sub-node)
             final Optional<? extends DataObject> readSubtree = current.isPresent()
                 ? filterSubtree(current.get(), id, getManagedDataObjectType().getTargetType())
@@ -142,9 +147,10 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
      *
      * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present.
      * @param builder Builder object for current node where the read attributes must be placed
+     * @param ctx Current read context
      */
-    protected abstract void readCurrentAttributes(final InstanceIdentifier<D> id, B builder) throws
-            ReadFailedException;
+    protected abstract void readCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final B builder,
+                                                  @Nonnull final ReadContext ctx) throws ReadFailedException;
 
     /**
      * Return new instance of a builder object for current node
index f18a5b3..e6872d1 100644 (file)
@@ -20,6 +20,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ChildVppReaderCustomizer;
 import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
 import java.util.List;
@@ -79,8 +80,9 @@ public final class CompositeChildVppReader<C extends DataObject, B extends Build
 
     @Override
     public final void read(@Nonnull final InstanceIdentifier<? extends DataObject> parentId,
-                           @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException {
-        final Optional<C> read = readCurrent(VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType()));
+                           @Nonnull final Builder<? extends DataObject> parentBuilder,
+                           @Nonnull final ReadContext ctx) throws ReadFailedException {
+        final Optional<C> read = readCurrent(VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType()), ctx);
 
         if(read.isPresent()) {
             customizer.merge(parentBuilder, read.get());
@@ -88,9 +90,10 @@ public final class CompositeChildVppReader<C extends DataObject, B extends Build
     }
 
     @Override
-    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder)
+    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder,
+                                         @Nonnull final ReadContext ctx)
             throws ReadFailedException {
-        customizer.readCurrentAttributes(id, builder);
+        customizer.readCurrentAttributes(id, builder, ctx.getContext());
     }
 
     @Override
index a9ca3e7..9d7ad34 100644 (file)
@@ -23,6 +23,7 @@ import com.google.common.base.Optional;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader;
 import io.fd.honeycomb.v3po.impl.trans.r.ListVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ListVppReaderCustomizer;
 import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
 import java.util.ArrayList;
@@ -91,19 +92,21 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K>
 
     @Override
     public void read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
-                     @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException {
+                     @Nonnull final Builder<? extends DataObject> parentBuilder,
+                     @Nonnull final ReadContext ctx) throws ReadFailedException {
         // Create ID pointing to current node
         final InstanceIdentifier<C> currentId = VppRWUtils.appendTypeToId(id, getManagedDataObjectType());
         // Read all, since current ID is definitely wildcarded
-        final List<C> ifcs = readList(currentId);
+        final List<C> ifcs = readList(currentId, ctx);
         customizer.merge(parentBuilder, ifcs);
     }
 
     @Override
     @Nonnull
-    public List<C> readList(@Nonnull final InstanceIdentifier<C> id) throws ReadFailedException {
+    public List<C> readList(@Nonnull final InstanceIdentifier<C> id,
+                            @Nonnull final ReadContext ctx) throws ReadFailedException {
         LOG.trace("{}: Reading all list entries", this);
-        final List<K> allIds = customizer.getAllIds(id);
+        final List<K> allIds = customizer.getAllIds(id, ctx.getContext());
         LOG.debug("{}: Reading list entries for: {}", this, allIds);
 
         final ArrayList<C> allEntries = new ArrayList<>(allIds.size());
@@ -111,7 +114,7 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K>
             final InstanceIdentifier.IdentifiableItem<C, K> currentBdItem =
                     VppRWUtils.getCurrentIdItem(id, key);
             final InstanceIdentifier<C> keyedId = VppRWUtils.replaceLastInId(id, currentBdItem);
-            final Optional<C> read = readCurrent(keyedId);
+            final Optional<C> read = readCurrent(keyedId, ctx);
             final DataObject singleItem = read.get();
             checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(singleItem.getClass()));
             allEntries.add(getManagedDataObjectType().getTargetType().cast(singleItem));
@@ -120,9 +123,10 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K>
     }
 
     @Override
-    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder)
+    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder,
+                                         @Nonnull final ReadContext ctx)
             throws ReadFailedException {
-        customizer.readCurrentAttributes(id, builder);
+        customizer.readCurrentAttributes(id, builder, ctx.getContext());
     }
 
     @Override
index d5d82e7..34d4dce 100644 (file)
@@ -19,6 +19,7 @@ package io.fd.honeycomb.v3po.impl.trans.r.impl;
 import com.google.common.annotations.Beta;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.RootVppReaderCustomizer;
 import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
@@ -77,9 +78,10 @@ public final class CompositeRootVppReader<C extends DataObject, B extends Builde
     }
 
     @Override
-    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder)
+    protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder,
+                                         @Nonnull final ReadContext ctx)
             throws ReadFailedException {
-        customizer.readCurrentAttributes(id, builder);
+        customizer.readCurrentAttributes(id, builder, ctx.getContext());
     }
 
     @Override
index 694f21c..c87050b 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.honeycomb.v3po.impl.trans.r.impl.spi;
 
 import com.google.common.annotations.Beta;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import java.util.List;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.concepts.Builder;
@@ -39,10 +40,11 @@ public interface ListVppReaderCustomizer<C extends DataObject & Identifiable<K>,
     /**
      * Return list with IDs of all list nodes to be read.
      *
-     * @param id wildcarded ID pointing to list node managed by enclosing reader
+     * @param id Wildcarded ID pointing to list node managed by enclosing reader
+     * @param context Read context
      */
     @Nonnull
-    List<K> getAllIds(@Nonnull final InstanceIdentifier<C> id);
+    List<K> getAllIds(@Nonnull final InstanceIdentifier<C> id, @Nonnull final Context context);
     // TODO does it make sense with vpp APIs ? Should we replace it with a simple readAll ?
 
     /**
index 299e943..b35a1c6 100644 (file)
@@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.trans.r.impl.spi;
 
 import com.google.common.annotations.Beta;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -46,6 +47,6 @@ public interface RootVppReaderCustomizer<C extends DataObject, B extends Builder
      * @param builder builder for creating read value
      * @throws ReadFailedException if read was unsuccessful
      */
-    void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) throws
-            ReadFailedException;
+    void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder,
+                               @Nonnull final Context ctx) throws ReadFailedException;
 }
index 2052407..51334e6 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Multimap;
 import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
 import io.fd.honeycomb.v3po.impl.trans.r.ListVppReader;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
 import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
 import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
@@ -59,8 +60,9 @@ public final class DelegatingReaderRegistry implements ReaderRegistry {
 
     @Override
     @Nonnull
-    public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll()
-            throws ReadFailedException {
+    public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll(
+        @Nonnull final ReadContext ctx) throws ReadFailedException {
+
         LOG.debug("Reading from all delegates: {}", this);
         LOG.trace("Reading from all delegates: {}", rootReaders.values());
 
@@ -70,12 +72,12 @@ public final class DelegatingReaderRegistry implements ReaderRegistry {
 
             if (rootReader instanceof ListVppReader) {
                 final List<? extends DataObject> listEntries =
-                        ((ListVppReader) rootReader).readList(rootReader.getManagedDataObjectType());
+                        ((ListVppReader) rootReader).readList(rootReader.getManagedDataObjectType(), ctx);
                 if (!listEntries.isEmpty()) {
                     objects.putAll(rootReader.getManagedDataObjectType(), listEntries);
                 }
             } else {
-                final Optional<? extends DataObject> read = rootReader.read(rootReader.getManagedDataObjectType());
+                final Optional<? extends DataObject> read = rootReader.read(rootReader.getManagedDataObjectType(), ctx);
                 if (read.isPresent()) {
                     objects.putAll(rootReader.getManagedDataObjectType(), Collections.singletonList(read.get()));
                 }
@@ -87,7 +89,8 @@ public final class DelegatingReaderRegistry implements ReaderRegistry {
 
     @Nonnull
     @Override
-    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id)
+    public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+                                               @Nonnull final ReadContext ctx)
             throws ReadFailedException {
         final InstanceIdentifier.PathArgument first = checkNotNull(
                 Iterables.getFirst(id.getPathArguments(), null), "Empty id");
@@ -95,7 +98,7 @@ public final class DelegatingReaderRegistry implements ReaderRegistry {
         checkNotNull(vppReader,
                 "Unable to read %s. Missing reader. Current readers for: %s", id, rootReaders.keySet());
         LOG.debug("Reading from delegate: {}", vppReader);
-        return vppReader.read(id);
+        return vppReader.read(id, ctx);
     }
 
     /**
index 1ce0930..657af97 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.honeycomb.v3po.impl.trans.r.util;
 
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.RootVppReaderCustomizer;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -24,7 +25,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 public abstract class NoopReaderCustomizer<C extends DataObject, B extends Builder<C>> implements RootVppReaderCustomizer<C, B> {
 
     @Override
-    public void readCurrentAttributes(InstanceIdentifier<C> id, final B builder) {
+    public void readCurrentAttributes(InstanceIdentifier<C> id, final B builder, final Context context) {
         // Noop
     }
 }
index 6efcf2e..089d229 100644 (file)
@@ -22,7 +22,7 @@ import java.util.HashMap;
 /**
  * Simple context class that provides transient storage during one or more read/write operations
  */
-public class Context {
+public class Context implements AutoCloseable {
 
     protected final HashMap<Object, Object> map;
 
@@ -42,7 +42,8 @@ public class Context {
         return map.put(o, o2);
     }
 
-    public void close() throws Exception {
+    @Override
+    public void close() {
         map.clear();
     }
 }
index 3aaf832..191fdf8 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * Context providing information about current state of DataTree to writers
  */
 @Beta
-public interface WriteContext {
+public interface WriteContext extends AutoCloseable {
 
     /**
      * Read any data object before current modification was applied
@@ -54,4 +54,7 @@ public interface WriteContext {
      */
     @Nonnull
     Context getContext();
+
+    @Override
+    void close();
 }
index 8efcc61..21e5f19 100644 (file)
@@ -34,7 +34,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 /**
  * Transaction based WriteContext
  */
-public final class TransactionWriteContext implements WriteContext, AutoCloseable {
+public final class TransactionWriteContext implements WriteContext {
 
     private final DOMDataReadOnlyTransaction beforeTx;
     private final DOMDataReadOnlyTransaction afterTx;
@@ -95,7 +95,7 @@ public final class TransactionWriteContext implements WriteContext, AutoCloseabl
      * Does not close the transactions
      */
     @Override
-    public void close() throws Exception {
+    public void close() {
         ctx.close();
     }
 }
index 8784175..08daa4e 100644 (file)
@@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.vppstate;
 
 import com.google.common.collect.Lists;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ListVppReaderCustomizer;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import io.fd.honeycomb.v3po.impl.trans.util.VppApiCustomizer;
 import java.util.ArrayList;
 import java.util.List;
@@ -48,7 +49,7 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer
 
     @Override
     public void readCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
-                                      @Nonnull final BridgeDomainBuilder builder) {
+                                      @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) {
         final BridgeDomainKey key = id.firstKeyOf(id.getTargetType());
         // TODO find out if bd exists based on name and if not return
 
@@ -113,11 +114,13 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer
 
     @Nonnull
     @Override
-    public List<BridgeDomainKey> getAllIds(@Nonnull final InstanceIdentifier<BridgeDomain> id) {
+    public List<BridgeDomainKey> getAllIds(@Nonnull final InstanceIdentifier<BridgeDomain> id, @Nonnull final Context context) {
         final int[] bIds = getVppApi().bridgeDomainDump(-1);
         final List<BridgeDomainKey> allIds = new ArrayList<>(bIds.length);
         for (int bId : bIds) {
             // FIXME this is highly inefficient having to dump all of the bridge domain details
+            // Use context to store already read information
+            // TODO Or just remove the getAllIds method and replace with a simple readAll
             final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bId);
             final String bName = bridgeDomainDetails.name;
             allIds.add(new BridgeDomainKey(bName));
index d56c4e5..4cdacaa 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.honeycomb.v3po.impl.vppstate;
 
 import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ChildVppReaderCustomizer;
+import io.fd.honeycomb.v3po.impl.trans.util.Context;
 import io.fd.honeycomb.v3po.impl.trans.util.VppApiCustomizer;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder;
@@ -47,7 +48,8 @@ public final class VersionCustomizer
     }
 
     @Override
-    public void readCurrentAttributes(@Nonnull InstanceIdentifier<Version> id, @Nonnull final VersionBuilder builder) {
+    public void readCurrentAttributes(@Nonnull InstanceIdentifier<Version> id, @Nonnull final VersionBuilder builder,
+                                      @Nonnull final Context context) {
         final vppVersion vppVersion = getVppApi().getVppVersion();
         builder.setBranch(vppVersion.gitBranch);
         builder.setName(vppVersion.programName);
index 8939f8f..493a019 100644 (file)
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.same;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
@@ -33,6 +34,7 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.CheckedFuture;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
 import java.util.Map;
 import org.junit.Before;
@@ -68,6 +70,8 @@ public class VppOperationalDataTreeTest {
     private SchemaContext globalContext;
     @Mock
     private DataSchemaNode schemaNode;
+    @Mock
+    private ReadContext readCtx;
 
     @Before
     public void setUp() {
@@ -86,7 +90,7 @@ public class VppOperationalDataTreeTest {
         doReturn(id).when(serializer).fromYangInstanceIdentifier(yangId);
 
         final DataObject dataObject = mock(DataObject.class);
-        doReturn(Optional.of(dataObject)).when(reader).read(id);
+        doReturn(Optional.of(dataObject)).when(reader).read(same(id), any(ReadContext.class));
 
         when(serializer.toNormalizedNode(id, dataObject)).thenReturn(entry);
         final DataContainerChild<?, ?> expectedValue = mock(DataContainerChild.class);
@@ -95,7 +99,7 @@ public class VppOperationalDataTreeTest {
         final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future = operationalData.read(yangId);
 
         verify(serializer).fromYangInstanceIdentifier(yangId);
-        verify(reader).read(id);
+        verify(reader).read(same(id), any(ReadContext.class));
         final Optional<NormalizedNode<?, ?>> result = future.get();
         assertTrue(result.isPresent());
         assertEquals(expectedValue, result.get());
@@ -105,19 +109,19 @@ public class VppOperationalDataTreeTest {
     public void testReadNonExistingNode() throws Exception {
         final YangInstanceIdentifier yangId = mock(YangInstanceIdentifier.class);
         doReturn(id).when(serializer).fromYangInstanceIdentifier(yangId);
-        doReturn(Optional.absent()).when(reader).read(id);
+        doReturn(Optional.absent()).when(reader).read(same(id), any(ReadContext.class));
 
         final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future = operationalData.read(yangId);
 
         verify(serializer).fromYangInstanceIdentifier(yangId);
-        verify(reader).read(id);
+        verify(reader).read(same(id), any(ReadContext.class));
         final Optional<NormalizedNode<?, ?>> result = future.get();
         assertFalse(result.isPresent());
     }
 
     @Test
     public void testReadFailed() throws Exception{
-        doThrow(io.fd.honeycomb.v3po.impl.trans.ReadFailedException.class).when(reader).readAll();
+        doThrow(io.fd.honeycomb.v3po.impl.trans.ReadFailedException.class).when(reader).readAll(any(ReadContext.class));
 
         final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future =
                 operationalData.read( YangInstanceIdentifier.EMPTY);
@@ -138,7 +142,7 @@ public class VppOperationalDataTreeTest {
         final VppState vppState = mock(VppState.class);
         Multimap<InstanceIdentifier<?>, DataObject> dataObjects = LinkedListMultimap.create();
         dataObjects.put(vppStateII, vppState);
-        doReturn(dataObjects).when(reader).readAll();
+        doReturn(dataObjects).when(reader).readAll(any(ReadContext.class));
 
         // Init serializer
         final YangInstanceIdentifier vppYangId = YangInstanceIdentifier.builder().node(VppState.QNAME).build();
@@ -152,7 +156,7 @@ public class VppOperationalDataTreeTest {
         final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future =
                 operationalData.read(YangInstanceIdentifier.EMPTY);
 
-        verify(reader).readAll();
+        verify(reader).readAll(any(ReadContext.class));
         verify(serializer).toYangInstanceIdentifier(vppStateII);
         verify(serializer).toNormalizedNode(vppStateII, vppState);
 
index f44ca52..5cb678e 100644 (file)
@@ -20,11 +20,13 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
+import io.fd.honeycomb.v3po.impl.trans.r.ReadContext;
 import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.CompositeListVppReader;
 import io.fd.honeycomb.v3po.impl.trans.r.impl.CompositeRootVppReader;
@@ -73,11 +75,14 @@ public class VppStateTest {
     private DelegatingReaderRegistry readerRegistry;
     private vppBridgeDomainDetails bdDetails;
     private vppBridgeDomainDetails bdDetails2;
+    private ReadContext ctx;
 
     @Before
     public void setUp() throws Exception {
         api = PowerMockito.mock(vppApi.class);
 
+        ctx = mock(ReadContext.class);
+
         bdDetails = new vppBridgeDomainDetails();
         setIfcs(bdDetails);
         setBaseAttrs(bdDetails, "bdn1", 1);
@@ -145,7 +150,7 @@ public class VppStateTest {
 
     @Test
     public void testReadAll() throws Exception {
-        final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects = readerRegistry.readAll();
+        final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects = readerRegistry.readAll(ctx);
         assertEquals(dataObjects.size(), 1);
         final DataObject dataObject = Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet())));
         assertTrue(dataObject instanceof VppState);
@@ -166,17 +171,17 @@ public class VppStateTest {
 
     @Test
     public void testReadSpecific() throws Exception {
-        final Optional<? extends DataObject> read = readerRegistry.read(InstanceIdentifier.create(VppState.class));
+        final Optional<? extends DataObject> read = readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx);
         assertTrue(read.isPresent());
         assertVersion((VppState) read.get());
     }
 
     @Test
     public void testReadBridgeDomains() throws Exception {
-        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class)).get();
+        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
 
         Optional<? extends DataObject> read =
-            readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class));
+            readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class), ctx);
         assertTrue(read.isPresent());
         assertEquals(readRoot.getBridgeDomains(), read.get());
     }
@@ -190,38 +195,38 @@ public class VppStateTest {
         Optional<? extends DataObject> read =
             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
                 BridgeDomain.class, new BridgeDomainKey("bdn1"))
-                .child(L2Fib.class, new L2FibKey(new PhysAddress("01:02:03:04:05:06"))));
+                .child(L2Fib.class, new L2FibKey(new PhysAddress("01:02:03:04:05:06"))), ctx);
         assertTrue(read.isPresent());
 
         // non existing l2fib
         read =
             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
                 BridgeDomain.class, new BridgeDomainKey("bdn1"))
-                .child(L2Fib.class, new L2FibKey(new PhysAddress("FF:FF:FF:04:05:06"))));
+                .child(L2Fib.class, new L2FibKey(new PhysAddress("FF:FF:FF:04:05:06"))), ctx);
         assertFalse(read.isPresent());
     }
 
     @Test
     public void testReadBridgeDomainAll() throws Exception {
-        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class)).get();
+        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
 
         final CompositeListVppReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> bridgeDomainReader =
             VppStateUtils.getBridgeDomainReader(api);
 
         final List<BridgeDomain> read =
             bridgeDomainReader.readList(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
-                BridgeDomain.class));
+                BridgeDomain.class), ctx);
 
         assertEquals(readRoot.getBridgeDomains().getBridgeDomain(), read);
     }
 
     @Test
     public void testReadBridgeDomain() throws Exception {
-        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class)).get();
+        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
 
         final Optional<? extends DataObject> read =
             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
-                BridgeDomain.class, new BridgeDomainKey("bdn1")));
+                BridgeDomain.class, new BridgeDomainKey("bdn1")), ctx);
 
         assertTrue(read.isPresent());
         assertEquals(Iterables.find(readRoot.getBridgeDomains().getBridgeDomain(), new Predicate<BridgeDomain>() {
@@ -238,16 +243,16 @@ public class VppStateTest {
     public void testReadBridgeDomainNotExisting() throws Exception {
         final Optional<? extends DataObject> read =
             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
-                BridgeDomain.class, new BridgeDomainKey("NOT EXISTING")));
+                BridgeDomain.class, new BridgeDomainKey("NOT EXISTING")), ctx);
         assertFalse(read.isPresent());
     }
 
     @Test
     public void testReadVersion() throws Exception {
-        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class)).get();
+        VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
 
         Optional<? extends DataObject> read =
-            readerRegistry.read(InstanceIdentifier.create(VppState.class).child(Version.class));
+            readerRegistry.read(InstanceIdentifier.create(VppState.class).child(Version.class), ctx);
         assertTrue(read.isPresent());
         assertEquals(readRoot.getVersion(), read.get());
     }