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