BGPCEP-574: Remove old ImportPolicyPeerTracker
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / ExportPolicyPeerTrackerImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.EnumMap;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.function.BiConsumer;
16 import javax.annotation.concurrent.GuardedBy;
17 import javax.annotation.concurrent.ThreadSafe;
18 import org.opendaylight.protocol.bgp.rib.impl.spi.PeerExportGroupRegistry;
19 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
20 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
21 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup.PeerExporTuple;
22 import org.opendaylight.protocol.concepts.AbstractRegistration;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.SendReceive;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerRole;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * There is one ExportPolicyPeerTracker per table
34  * - peerTables: keep track of registered peers, the ones which support this table.
35  * - peerTables: flag indicates whether the structure of the peer has been created, and therefore it can start
36  * to be updated.
37  * - peerAddPathTables: keeps track of peer which supports Additional Path for this table and which Add Path
38  * configuration they are using.
39  * - groups: Contains peers grouped by peerRole and therefore sharing the same export policy.
40  */
41 @ThreadSafe
42 final class ExportPolicyPeerTrackerImpl implements ExportPolicyPeerTracker {
43     private static final Logger LOG = LoggerFactory.getLogger(ExportPolicyPeerTrackerImpl.class);
44     @GuardedBy("this")
45     private final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
46     @GuardedBy("this")
47     private final Map<PeerId, SendReceive> peerAddPathTables = new HashMap<>();
48     @GuardedBy("this")
49     private final Map<PeerId, Boolean> peerTables = new HashMap<>();
50     private final PolicyDatabase policyDatabase;
51     private final TablesKey localTableKey;
52     @GuardedBy("this")
53     private final Map<PeerRole, PeerExportGroupRegistry> groups = new EnumMap<>(PeerRole.class);
54
55     ExportPolicyPeerTrackerImpl(final PolicyDatabase policyDatabase, final TablesKey localTablesKey) {
56         this.policyDatabase = requireNonNull(policyDatabase);
57         this.localTableKey = localTablesKey;
58     }
59
60     private synchronized AbstractRegistration addToExportGroups(final PeerId peerId,
61             final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
62         final PeerExportGroupRegistry peerExp = this.groups.computeIfAbsent(peerRole,
63                 k -> new PeerExportGroupImpl(this.policyDatabase.exportPolicyForRole(peerRole)));
64
65         final AbstractRegistration registration = peerExp.registerPeer(peerId, new PeerExporTuple(peerPath, peerRole));
66
67         return new AbstractRegistration() {
68             @Override
69             protected void removeRegistration() {
70                 registration.close();
71                 if (ExportPolicyPeerTrackerImpl.this.groups.get(peerRole).isEmpty()) {
72                     ExportPolicyPeerTrackerImpl.this.groups.remove(peerRole);
73                 }
74             }
75         };
76     }
77
78     @Override
79     public synchronized AbstractRegistration registerPeer(final PeerId peerId, final SendReceive sendReceive,
80             final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
81         if (sendReceive != null) {
82             this.peerAddPathTables.put(peerId, sendReceive);
83             LOG.debug("Supported Add BestPath table {} added to peer {}", sendReceive, peerId);
84         }
85         this.peerTables.put(peerId, false);
86         this.peerRoles.put(peerPath, peerRole);
87         LOG.debug("Supported table {} added to peer {} role {}", this.localTableKey, peerId, peerRole);
88         final AbstractRegistration registration = addToExportGroups(peerId, peerPath, peerRole);
89
90         final Object lock = this;
91         return new AbstractRegistration() {
92             @Override
93             protected void removeRegistration() {
94                 synchronized (lock) {
95                     final SendReceive sendReceiveValue = ExportPolicyPeerTrackerImpl.this.peerAddPathTables.remove(peerId);
96                     if (sendReceiveValue != null) {
97                         LOG.debug("Supported Add BestPath table {} removed to peer {}", sendReceiveValue, peerId);
98                     }
99                     ExportPolicyPeerTrackerImpl.this.peerTables.remove(peerId);
100                     LOG.debug("Removed peer {} from supported table {}", peerId, ExportPolicyPeerTrackerImpl.this.localTableKey);
101                     ExportPolicyPeerTrackerImpl.this.peerRoles.remove(peerPath);
102                     registration.close();
103                 }
104             }
105         };
106     }
107
108     @Override
109     public synchronized PeerExportGroup getPeerGroup(final PeerRole role) {
110         return this.groups.get(requireNonNull(role));
111     }
112
113     @Override
114     public synchronized boolean isTableSupported(final PeerId peerId) {
115         return this.peerTables.containsKey(peerId);
116     }
117
118     @Override
119     public synchronized PeerRole getRole(final YangInstanceIdentifier peerId) {
120         return this.peerRoles.get(peerId);
121     }
122
123     @Override
124     public synchronized boolean isAddPathSupportedByPeer(final PeerId peerId) {
125         final SendReceive sendReceive = this.peerAddPathTables.get(peerId);
126         return sendReceive != null && (sendReceive.equals(SendReceive.Both) || sendReceive.equals(SendReceive.Receive));
127     }
128
129     @Override
130     public synchronized void registerPeerAsInitialized(final PeerId peerId) {
131         this.peerTables.computeIfPresent(peerId, (k, v) -> true);
132     }
133
134     @Override
135     public synchronized boolean isTableStructureInitialized(final PeerId peerId) {
136         return this.peerTables.get(peerId);
137     }
138
139     final class PeerExportGroupImpl implements PeerExportGroupRegistry {
140         @GuardedBy("this")
141         private final Map<PeerId, PeerExporTuple> peers = new HashMap<>();
142         private final AbstractExportPolicy policy;
143
144         public PeerExportGroupImpl(final AbstractExportPolicy policy) {
145             this.policy = requireNonNull(policy);
146         }
147
148         @Override
149         public ContainerNode effectiveAttributes(final PeerRole role, final ContainerNode attributes) {
150             return attributes == null || role == null ? null : this.policy.effectiveAttributes(role, attributes);
151         }
152
153         @Override
154         public boolean containsPeer(final PeerId routePeerId) {
155             synchronized (this.peers) {
156                 return this.peers.containsKey(routePeerId);
157             }
158         }
159
160         @Override
161         public void forEach(final BiConsumer<PeerId, YangInstanceIdentifier> action) {
162             synchronized (ExportPolicyPeerTrackerImpl.this) {
163                 synchronized (this.peers) {
164                     for (final Map.Entry<PeerId, PeerExporTuple> pid : this.peers.entrySet()) {
165                         action.accept(pid.getKey(), pid.getValue().getYii());
166                     }
167                 }
168             }
169         }
170
171         @Override
172         public AbstractRegistration registerPeer(final PeerId peerId, final PeerExporTuple peerExporTuple) {
173             synchronized (ExportPolicyPeerTrackerImpl.this) {
174                 synchronized (this.peers) {
175                     this.peers.put(peerId, peerExporTuple);
176                 }
177
178                 return new AbstractRegistration() {
179                     @Override
180                     protected void removeRegistration() {
181                         synchronized (ExportPolicyPeerTrackerImpl.this) {
182                             synchronized (PeerExportGroupImpl.this.peers) {
183                                 PeerExportGroupImpl.this.peers.remove(peerId);
184                             }
185                         }
186                     }
187                 };
188             }
189         }
190
191         @Override
192         public boolean isEmpty() {
193             synchronized (this.peers) {
194                 return this.peers.isEmpty();
195             }
196         }
197     }
198 }