Replace Preconditions.CheckNotNull per RequireNonNull
[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.Optional;
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.rev130919.SendReceive;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.SimpleRoutingPolicy;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
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         final Optional<SimpleRoutingPolicy> optSimpleRoutingPolicy) {
82         if (sendReceive != null) {
83             this.peerAddPathTables.put(peerId, sendReceive);
84             LOG.debug("Supported Add BestPath table {} added to peer {}", sendReceive, peerId);
85         }
86         final SimpleRoutingPolicy simpleRoutingPolicy = optSimpleRoutingPolicy.orElse(null);
87         if (SimpleRoutingPolicy.AnnounceNone != simpleRoutingPolicy) {
88             this.peerTables.put(peerId, false);
89         }
90         this.peerRoles.put(peerPath, peerRole);
91         LOG.debug("Supported table {} added to peer {} role {}", this.localTableKey, peerId, peerRole);
92         final AbstractRegistration registration = addToExportGroups(peerId, peerPath, peerRole);
93
94         final Object lock = this;
95         return new AbstractRegistration() {
96             @Override
97             protected void removeRegistration() {
98                 synchronized (lock) {
99                     final SendReceive sendReceiveValue = ExportPolicyPeerTrackerImpl.this.peerAddPathTables.remove(peerId);
100                     if (sendReceiveValue != null) {
101                         LOG.debug("Supported Add BestPath table {} removed to peer {}", sendReceiveValue, peerId);
102                     }
103                     ExportPolicyPeerTrackerImpl.this.peerTables.remove(peerId);
104                     LOG.debug("Removed peer {} from supported table {}", peerId, ExportPolicyPeerTrackerImpl.this.localTableKey);
105                     ExportPolicyPeerTrackerImpl.this.peerRoles.remove(peerPath);
106                     registration.close();
107                 }
108             }
109         };
110     }
111
112     @Override
113     public synchronized PeerExportGroup getPeerGroup(final PeerRole role) {
114         return this.groups.get(requireNonNull(role));
115     }
116
117     @Override
118     public synchronized boolean isTableSupported(final PeerId peerId) {
119         return this.peerTables.containsKey(peerId);
120     }
121
122     @Override
123     public synchronized PeerRole getRole(final YangInstanceIdentifier peerId) {
124         return this.peerRoles.get(peerId);
125     }
126
127     @Override
128     public synchronized boolean isAddPathSupportedByPeer(final PeerId peerId) {
129         final SendReceive sendReceive = this.peerAddPathTables.get(peerId);
130         return sendReceive != null && (sendReceive.equals(SendReceive.Both) || sendReceive.equals(SendReceive.Receive));
131     }
132
133     @Override
134     public synchronized void registerPeerAsInitialized(final PeerId peerId) {
135         this.peerTables.computeIfPresent(peerId, (k, v) -> true);
136     }
137
138     @Override
139     public synchronized boolean isTableStructureInitialized(final PeerId peerId) {
140         return this.peerTables.get(peerId);
141     }
142 }