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