BUG-2982 : moved path-attributes container to grouping
[bgpcep.git] / bgp / rib-spi / src / main / java / org / opendaylight / protocol / bgp / rib / spi / AbstractAdjRIBs.java
index d242103e89b04b2a24c08ad199210a7f8eb1542e..8e2002c41cff575e0dcf767654485408b3e7ccab 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.protocol.bgp.rib.spi;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Preconditions;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -18,17 +18,17 @@ import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
@@ -39,18 +39,19 @@ import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Deprecated
 @ThreadSafe
 public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K extends Identifier<D>> implements AdjRIBsIn<I, D>, RouteEncoder {
     protected abstract static class RIBEntryData<I, D extends Identifiable<K> & Route, K extends Identifier<D>> {
-        private final PathAttributes attributes;
+        private final Attributes attributes;
         private final Peer peer;
 
-        protected RIBEntryData(final Peer peer, final PathAttributes attributes) {
+        protected RIBEntryData(final Peer peer, final Attributes attributes) {
             this.attributes = Preconditions.checkNotNull(attributes);
             this.peer = Preconditions.checkNotNull(peer);
         }
 
-        public PathAttributes getPathAttributes() {
+        public Attributes getAttributes() {
             return this.attributes;
         }
 
@@ -69,7 +70,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
 
         @Override
         public final String toString() {
-            return addToStringAttributes(Objects.toStringHelper(this)).toString();
+            return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
         }
 
         protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
@@ -77,106 +78,13 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
         }
     }
 
-    /**
-     * A single RIB table entry, which holds multiple versions of the entry's state and elects the authoritative based
-     * on ordering specified by the supplied comparator.
-     *
-     */
-    private final class RIBEntry {
-        /*
-         * TODO: we could dramatically optimize performance by using the comparator
-         *       to retain the candidate states ordered -- thus selection would occur
-         *       automatically through insertion, without the need of a second walk.
-         */
-        private final Map<Peer, RIBEntryData<I, D, K>> candidates = new HashMap<>();
-        private final I key;
-
-        @GuardedBy("this")
-        private KeyedInstanceIdentifier<D, K> name;
-        @GuardedBy("this")
-        private RIBEntryData<I, D, K> currentState;
-
-        RIBEntry(final I key) {
-            this.key = Preconditions.checkNotNull(key);
-        }
-
-        private KeyedInstanceIdentifier<D, K> getName() {
-            if (this.name == null) {
-                this.name = identifierForKey(AbstractAdjRIBs.this.basePath, this.key);
-                LOG.trace("Entry {} grew key {}", this, this.name);
-            }
-            return this.name;
-        }
-
-        /**
-         * Based on given comparator, finds a new best candidate for initial route.
-         *
-         * @param comparator
-         * @param initial
-         * @return
-         */
-        private RIBEntryData<I, D, K> findCandidate(final BGPObjectComparator comparator, final RIBEntryData<I, D, K> initial) {
-            RIBEntryData<I, D, K> newState = initial;
-            for (final RIBEntryData<I, D, K> s : this.candidates.values()) {
-                if (newState == null || comparator.compare(newState, s) > 0) {
-                    newState = s;
-                }
-            }
-
-            return newState;
-        }
-
-        /**
-         * Advertize newly elected best candidate to datastore.
-         *
-         * @param transaction
-         * @param candidate
-         */
-        private void electCandidate(final AdjRIBsTransaction transaction, final RIBEntryData<I, D, K> candidate) {
-            LOG.trace("Electing state {} to supersede {}", candidate, this.currentState);
-
-            if (this.currentState == null || !this.currentState.equals(candidate)) {
-                LOG.trace("Elected new state for {}: {}", getName(), candidate);
-                transaction.advertise(AbstractAdjRIBs.this, this.key, getName(), candidate.getPeer(), candidate.getDataObject(this.key, getName().getKey()));
-                this.currentState = candidate;
-            }
-        }
-
-        /**
-         * Removes RIBEntry from database. If we are removing best path, elect another candidate (using BPS).
-         * If there are no other candidates, remove the path completely.
-         * @param transaction
-         * @param peer
-         * @return true if the list of the candidates for this path is empty
-         */
-        synchronized boolean removeState(final AdjRIBsTransaction transaction, final Peer peer) {
-            final RIBEntryData<I, D, K> data = this.candidates.remove(peer);
-            LOG.trace("Removed data {}", data);
-
-            final RIBEntryData<I, D, K> candidate = findCandidate(transaction.comparator(), null);
-            if (candidate != null) {
-                electCandidate(transaction, candidate);
-            } else {
-                LOG.trace("Final candidate disappeared, removing entry {}", getName());
-                transaction.withdraw(AbstractAdjRIBs.this, this.key, getName());
-            }
-
-            return this.candidates.isEmpty();
-        }
-
-        synchronized void setState(final AdjRIBsTransaction transaction, final Peer peer, final RIBEntryData<I, D, K> state) {
-            this.candidates.put(Preconditions.checkNotNull(peer), Preconditions.checkNotNull(state));
-            electCandidate(transaction, findCandidate(transaction.comparator(), state));
-        }
-    }
-
     private static final Logger LOG = LoggerFactory.getLogger(AbstractAdjRIBs.class);
     private final KeyedInstanceIdentifier<Tables, TablesKey> basePath;
     private final BgpTableType tableType;
     private final Update eor;
 
     @GuardedBy("this")
-    private final Map<I, RIBEntry> entries = new HashMap<>();
+    private final Map<I, RIBEntry<I, D, K>> entries = new HashMap<>();
 
     @GuardedBy("this")
     private final Map<Peer, Boolean> peers = new HashMap<>();
@@ -184,16 +92,16 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     protected AbstractAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
         this.basePath = Preconditions.checkNotNull(basePath);
         this.tableType = new BgpTableTypeImpl(basePath.getKey().getAfi(), basePath.getKey().getSafi());
-        this.eor = new UpdateBuilder().setPathAttributes(new PathAttributesBuilder().addAugmentation(
-            PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(new MpReachNlriBuilder(this.tableType)
+        this.eor = new UpdateBuilder().setAttributes(new AttributesBuilder().addAugmentation(
+            Attributes1.class, new Attributes1Builder().setMpReachNlri(new MpReachNlriBuilder(this.tableType)
                 .build()).build()).build()).build();
     }
 
     @Override
     public final synchronized void clear(final AdjRIBsTransaction trans, final Peer peer) {
-        final Iterator<Entry<I, RIBEntry>> i = this.entries.entrySet().iterator();
+        final Iterator<Entry<I, RIBEntry<I, D, K>>> i = this.entries.entrySet().iterator();
         while (i.hasNext()) {
-            final Entry<I, RIBEntry> e = i.next();
+            final Entry<I, RIBEntry<I, D, K>> e = i.next();
 
             if (e.getValue().removeState(trans, peer)) {
                 i.remove();
@@ -201,14 +109,14 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
         }
 
         this.peers.remove(peer);
-        trans.setUptodate(this.basePath, !this.peers.values().contains(Boolean.FALSE));
+        trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
     }
 
     public final synchronized void addAllEntries(final AdjRIBsTransaction trans) {
-        for (final Entry<I, RIBEntry> e : this.entries.entrySet()) {
-            final RIBEntry entry = e.getValue();
+        for (final Entry<I, RIBEntry<I, D, K>> e : this.entries.entrySet()) {
+            final RIBEntry<I, D, K> entry = e.getValue();
             final RIBEntryData<I, D, K> state = entry.currentState;
-            trans.advertise(this, e.getKey(), entry.name, state.peer, state.getDataObject(entry.key, entry.name.getKey()));
+            trans.advertise(this, e.getKey(), entry.name, state.peer, state.getDataObject(entry.getKey(), entry.name.getKey()));
         }
     }
 
@@ -218,16 +126,40 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
      * @param basePath datastore base path under which the entry to be stored
      * @param id object identifier
      * @return Data store identifier, may not be null
+     *
+     * @deprecated Please override {@link #identifierForKey(Object)} instead. The basePath
+     *             argument is constant for a particular instance and is the one your
+     *             constructor specifies.
      */
+    @Deprecated
     protected abstract KeyedInstanceIdentifier<D, K> identifierForKey(InstanceIdentifier<Tables> basePath, I id);
 
+    /**
+     * Return the base path specified at construction time.
+     *
+     * @return Base path.
+     */
+    protected final KeyedInstanceIdentifier<Tables, TablesKey> getBasePath() {
+        return this.basePath;
+    }
+
+    /**
+     * Construct a datastore identifier for an entry key.
+     *
+     * @param id object identifier
+     * @return Data store identifier, may not be null
+     */
+    protected KeyedInstanceIdentifier<D, K> identifierForKey(final I id) {
+        return identifierForKey(getBasePath(), id);
+    }
+
     public void addWith(final MpUnreachNlriBuilder builder, final InstanceIdentifier<?> key) {
         this.addWithdrawal(builder, keyForIdentifier(this.routeIdentifier(key)));
     }
 
     /**
      * Transform a withdrawn identifier into a the corresponding NLRI in MP_UNREACH attribute.
-     *
+     * @param builder MpUnreachNlriBuilder
      * @param id Route key
      */
     protected abstract void addWithdrawal(MpUnreachNlriBuilder builder, I id);
@@ -237,7 +169,8 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
      * @param id instance identifier
      * @return router identifier
      */
-    public abstract @Nullable KeyedInstanceIdentifier<D, K> routeIdentifier(InstanceIdentifier<?> id);
+    @Nullable
+    public abstract KeyedInstanceIdentifier<D, K> routeIdentifier(InstanceIdentifier<?> id);
 
     /**
      * Craates route key out of instance identifier
@@ -247,7 +180,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     public abstract I keyForIdentifier(KeyedInstanceIdentifier<D, K> id);
 
     /**
-     * Common backend for {@link AdjRIBsIn#addRoutes()} implementations.
+     * Common backend for {@link AdjRIBsIn#addRoutes(AdjRIBsTransaction, Peer, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Attributes)} implementations.
      * If a new route is added, check first for its existence in Map of entries.
      * If the route is already there, change it's state. Then check for peer in
      * Map of peers, if it's not there, add it.
@@ -260,28 +193,28 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     protected final synchronized void add(final AdjRIBsTransaction trans, final Peer peer, final I id, final RIBEntryData<I, D, K> data) {
         LOG.debug("Adding state {} for {} peer {}", data, id, peer);
 
-        RIBEntry e = this.entries.get(Preconditions.checkNotNull(id));
+        RIBEntry<I, D, K> e = this.entries.get(Preconditions.checkNotNull(id));
         if (e == null) {
-            e = new RIBEntry(id);
+            e = new RIBEntry<I, D, K>(this, id);
             this.entries.put(id, e);
         }
 
         e.setState(trans, peer, data);
         if (!this.peers.containsKey(peer)) {
             this.peers.put(peer, Boolean.FALSE);
-            trans.setUptodate(this.basePath, Boolean.FALSE);
+            trans.setUptodate(getBasePath(), Boolean.FALSE);
         }
     }
 
     /**
-     * Common backend for {@link AdjRIBsIn#removeRoutes()} implementations.
+     * Common backend for {@link AdjRIBsIn#removeRoutes(AdjRIBsTransaction, Peer, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri)} implementations.
      *
      * @param trans Transaction context
      * @param peer Originating peer
      * @param id Data store instance identifier
      */
     protected final synchronized void remove(final AdjRIBsTransaction trans, final Peer peer, final I id) {
-        final RIBEntry e = this.entries.get(id);
+        final RIBEntry<I, D, K> e = this.entries.get(id);
         if (e != null && e.removeState(trans, peer)) {
             LOG.debug("Removed last state, removing entry for {}", id);
             this.entries.remove(id);
@@ -291,7 +224,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     @Override
     public final void markUptodate(final AdjRIBsTransaction trans, final Peer peer) {
         this.peers.put(peer, Boolean.TRUE);
-        trans.setUptodate(this.basePath, !this.peers.values().contains(Boolean.FALSE));
+        trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
     }
 
     @Override
@@ -302,21 +235,21 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     @Override
     public Update updateMessageFor(final Object key, final Route route) {
         final UpdateBuilder ub = new UpdateBuilder();
-        final PathAttributesBuilder pab = new PathAttributesBuilder();
+        final AttributesBuilder pab = new AttributesBuilder();
 
         if (route != null) {
             final MpReachNlriBuilder reach = new MpReachNlriBuilder(this.tableType);
 
             addAdvertisement(reach, (D)route);
             pab.fieldsFrom(route.getAttributes());
-            pab.addAugmentation(PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(reach.build()).build()).build();
+            pab.addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(reach.build()).build()).build();
         } else {
             final MpUnreachNlriBuilder unreach = new MpUnreachNlriBuilder(this.tableType);
             addWithdrawal(unreach, (I)key);
-            pab.addAugmentation(PathAttributes2.class, new PathAttributes2Builder().setMpUnreachNlri(unreach.build()).build()).build();
+            pab.addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(unreach.build()).build()).build();
         }
 
-        ub.setPathAttributes(pab.build());
+        ub.setAttributes(pab.build());
         return ub.build();
     }