3c0e00a6a80fcfbbad941d2a982c59a0236a54e2
[appc.git] / appc-adapters / appc-chef-adapter / appc-chef-adapter-bundle / src / main / java / org / openecomp / appc / adapter / chef / impl / RequestContext.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.adapter.chef.impl;
26
27 import org.onap.appc.Constants;
28 import org.onap.appc.configuration.Configuration;
29 import org.onap.appc.configuration.ConfigurationFactory;
30 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
31
32 /**
33  * This class is used to track and maintain recovery and time-to-live information for a request as it is being
34  * processed.
35  */
36 public class RequestContext {
37     /**
38      * The number of seconds of wait time between successive attempts to connect to the provider. This is used to
39      * recover from provider outages or failures. It is not used to recover from logical errors, such as an invalid
40      * request, server not found, etc.
41      */
42     private Integer retryDelay;
43
44     /**
45      * The number of times we will attempt to connect to the provider. This is used to recover from provider outages or
46      * failures. It is not used to recover from logical errors, such as an invalid request, server not found, etc.
47      */
48     private Integer retryLimit;
49
50     /**
51      * The total time, in milliseconds, that the provider can have to process this request. If the accumulated time
52      * exceeds the time to live, then the request is failed with a timeout exception, regardless of the state of the
53      * provider. Note that the caller may supply this as a value in seconds, in which case it must be converted to
54      * milliseconds for the request context.
55      */
56     private Long timeToLive;
57
58     /**
59      * The accumulated time, in milliseconds, that has been used so far to process the request. This is compared to the
60      * time to live each time it is updated. If the accumulated time exceeds the time to live, then the request is
61      * failed with a timeout exception, regardless of the state of the provider.
62      */
63     private long accumulatedTime;
64
65     /**
66      * The total number of retries attempted so far
67      */
68     private int attempt;
69
70     /**
71      * The time when the stopwatch was started
72      */
73     private long startTime = -1;
74
75     /**
76      * The service logic (DG) context from the SLI
77      */
78     private SvcLogicContext svcLogicContext;
79
80     /**
81      * The configuration
82      */
83     private Configuration configuration = ConfigurationFactory.getConfiguration();
84
85     /**
86      * Set to true whenever the retry limit has been exceeded, reset to false when reset() is called.
87      */
88     private boolean retryFailed;
89
90     /**
91      * Creates the request context
92      *
93      * @param context
94      *            The service logic (SLI) context associated with the current DG
95      */
96     public RequestContext(SvcLogicContext context) {
97         setSvcLogicContext(context);
98     }
99
100     /**
101      * @return The retry delay, in seconds. If zero, then no retry is to be performed
102      */
103     public int getRetryDelay() {
104         if (retryDelay == null) {
105             int value = configuration.getIntegerProperty(Constants.PROPERTY_RETRY_DELAY);
106             retryDelay = Integer.valueOf(value);
107         }
108
109         return retryDelay.intValue();
110     }
111
112     /**
113      * This method is a helper that allows the caller to delay for the retry interval time and not have to handle the
114      * thread interruption, timer handling, etc.
115      */
116     public void delay() {
117         long time = getRetryDelay() * 1000L;
118         long future = System.currentTimeMillis() + time;
119         if (time != 0) {
120             while (System.currentTimeMillis() < future && time > 0) {
121                 try {
122                     Thread.sleep(time);
123                 } catch (InterruptedException e) {
124                     /*
125                      * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that
126                      * case, the thread is resumed before the delay time has actually expired, so re-calculate the
127                      * amount of delay time needed and reenter the sleep until we get to the future time.
128                      */
129                     time = future - System.currentTimeMillis();
130                 }
131             }
132         }
133     }
134
135     /**
136      * @return The number of retries that are allowed per connection
137      */
138     public int getRetryLimit() {
139         if (retryLimit == null) {
140             int value = configuration.getIntegerProperty(Constants.PROPERTY_RETRY_LIMIT);
141             retryLimit = Integer.valueOf(value);
142         }
143
144         return retryLimit.intValue();
145     }
146
147     /**
148      * Check and count the connection attempt.
149      *
150      * @return True if the connection should be attempted. False indicates that the number of retries has been exhausted
151      *         and it should NOT be attempted.
152      */
153     public boolean attempt() {
154         if (retryFailed || attempt >= getRetryLimit()) {
155             retryFailed = true;
156             return false;
157         }
158         attempt++;
159
160         return true;
161     }
162
163     /**
164      * @return The number of retry attempts so far
165      */
166     public int getAttempts() {
167         return attempt;
168     }
169
170     /**
171      * @return True if the retry limit has been exceeded, false otherwise
172      */
173     public boolean isFailed() {
174         return retryFailed;
175     }
176
177     /**
178      * This method both checks the time to live to see if it has been exceeded and accumulates the total time used so
179      * far.
180      * <p>
181      * Each time this method is called it accumulates the total duration since the last time it was called to the total
182      * time accumulator. It then checks the total time to the time to live and if greater, it returns false. As long as
183      * the total time used is less than or equal to the time to live limit, the method returns true. It is important to
184      * call this method at the very beginning of the process so that all parts of the process are tracked.
185      * </p>
186      *
187      * @return True if the total time to live has not been exceeded. False indicates that the total time to live has
188      *         been exceeded and no further processing should be performed.
189      */
190     public boolean isAlive() {
191         long now = System.currentTimeMillis();
192         if (startTime == -1) {
193             startTime = now;
194             return true;
195         }
196         accumulatedTime += (now - startTime);
197         startTime = now;
198         if (accumulatedTime > timeToLive) {
199             return false;
200         }
201         return true;
202     }
203
204     /**
205      * @return The total amount of time used, in milliseconds.
206      */
207     public long getTotalDuration() {
208         return accumulatedTime;
209     }
210
211     /**
212      * This method is called to reset the retry counters. It has no effect on the time to live accumulator.
213      */
214     public void reset() {
215         attempt = 0;
216     }
217
218     /**
219      * Sets the time to live to the value, expressed in seconds
220      *
221      * @param time
222      *            The time to live, in seconds
223      */
224     public void setTimeToLiveSeconds(int time) {
225         setTimeToLiveMS(time * 1000L);
226     }
227
228     /**
229      * Sets the time to live to the value, expressed in milliseconds
230      *
231      * @param time
232      *            The time to live, in milliseconds
233      */
234     public void setTimeToLiveMS(long time) {
235         this.timeToLive = time;
236     }
237
238     /**
239      * @return The service logic context associated with this request
240      */
241     public SvcLogicContext getSvcLogicContext() {
242         return svcLogicContext;
243     }
244
245     /**
246      * @param svcLogicContext
247      *            The service logic context to be associated with this request
248      */
249     public void setSvcLogicContext(SvcLogicContext svcLogicContext) {
250         this.svcLogicContext = svcLogicContext;
251     }
252 }