Fix sonars in policy-pap
[policy/pap.git] / main / src / main / java / org / onap / policy / pap / main / comm / PdpTracker.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP PAP
4  * ================================================================================
5  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pap.main.comm;
22
23 import java.util.HashMap;
24 import java.util.Map;
25 import lombok.Builder;
26 import lombok.NonNull;
27 import org.onap.policy.models.base.PfModelException;
28 import org.onap.policy.models.pdp.concepts.Pdp;
29 import org.onap.policy.models.pdp.concepts.PdpGroup;
30 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
31 import org.onap.policy.models.provider.PolicyModelsProvider;
32 import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper;
33 import org.onap.policy.pap.main.PolicyPapRuntimeException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Tracks PDPs. When a PDP is added to the tracker, a timer is started. If the PDP is not
39  * re-added to the tracker before the timer expires, then
40  * {@link PdpModifyRequestMap#removeFromGroups(String)} is called.
41  */
42 public class PdpTracker {
43     private static final Logger logger = LoggerFactory.getLogger(PdpTracker.class);
44
45     /**
46      * PDP expiration timers.
47      */
48     private final TimerManager timers;
49
50     /**
51      * Maps a PDP name to its expiration timer.
52      */
53     private final Map<String, TimerManager.Timer> pdp2timer = new HashMap<>();
54
55     /**
56      * PDP modification lock.
57      */
58     private final Object modifyLock;
59
60     /**
61      * Used to remove a PDP from its group/subgroup.
62      */
63     private final PdpModifyRequestMap requestMap;
64
65
66     /**
67      * Constructs the object. Loads the list of PDPs to be tracked, from the DB.
68      *
69      * @param requestMap map used to remove a PDP from its group/subgroup
70      * @param modifyLock object to be locked while data structures are updated
71      * @param timers timers used to detect missed heart beats
72      * @param daoFactory DAO factory
73      */
74     @Builder
75     public PdpTracker(@NonNull PdpModifyRequestMap requestMap, @NonNull Object modifyLock, @NonNull TimerManager timers,
76                     @NonNull PolicyModelsProviderFactoryWrapper daoFactory) {
77
78         this.requestMap = requestMap;
79         this.modifyLock = modifyLock;
80         this.timers = timers;
81
82         loadPdps(daoFactory);
83     }
84
85     /**
86      * Loads the PDPs from the DB.
87      *
88      * @param daoFactory DAO factory
89      */
90     private void loadPdps(PolicyModelsProviderFactoryWrapper daoFactory) {
91         synchronized (modifyLock) {
92             try (PolicyModelsProvider dao = daoFactory.create()) {
93                 for (PdpGroup group : dao.getPdpGroups(null)) {
94                     loadPdpsFromGroup(group);
95                 }
96
97             } catch (PfModelException e) {
98                 throw new PolicyPapRuntimeException("cannot load PDPs from the DB", e);
99             }
100         }
101     }
102
103     /**
104      * Loads the PDPs appearing within a group.
105      *
106      * @param group group whose PDPs are to be loaded
107      */
108     private void loadPdpsFromGroup(PdpGroup group) {
109         for (PdpSubGroup subgrp : group.getPdpSubgroups()) {
110             for (Pdp pdp : subgrp.getPdpInstances()) {
111                 add(pdp.getInstanceId());
112             }
113         }
114     }
115
116     /**
117      * Adds a PDP to the tracker and starts its timer. If a timer is already running, the
118      * old timer is cancelled.
119      *
120      * @param pdpName name of the PDP
121      */
122     public void add(String pdpName) {
123         synchronized (modifyLock) {
124             var timer = pdp2timer.remove(pdpName);
125             if (timer != null) {
126                 timer.cancel();
127             }
128
129             timer = timers.register(pdpName, this::handleTimeout);
130             pdp2timer.put(pdpName, timer);
131         }
132     }
133
134     /**
135      * Handles a timeout. Removes the PDP from {@link #pdp2timer}.
136      *
137      * @param pdpName name of the PDP whose timer has expired
138      */
139     private void handleTimeout(String pdpName) {
140         synchronized (modifyLock) {
141             // remove timer - no need to cancel it, as TimerManager does that
142             logger.warn("missed heart beats - removing PDP {}", pdpName);
143             pdp2timer.remove(pdpName);
144
145             try {
146                 requestMap.removeFromGroups(pdpName);
147
148             } catch (PfModelException e) {
149                 logger.warn("unable to remove PDP {} from its group/subgroup", pdpName, e);
150             }
151         }
152     }
153 }