c58c9db7d3880752786c93de0ecd43f18fe9bf86
[ccsdk/sli/core.git] / dblib / provider / src / main / java / org / openecomp / sdnc / sli / resource / dblib / pm / SQLExecutionMonitor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openecomp
4  * ================================================================================
5  * Copyright (C) 2016 - 2017 AT&T
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.openecomp.sdnc.sli.resource.dblib.pm;
22
23 import java.io.Serializable;
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.Observable;
27 import java.util.Observer;
28 import java.util.SortedSet;
29 import java.util.Timer;
30 import java.util.TimerTask;
31 import java.util.TreeSet;
32 import java.util.concurrent.atomic.AtomicLong;
33
34 import org.openecomp.sdnc.sli.resource.dblib.DBResourceObserver;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 public class SQLExecutionMonitor extends Observable
39 {
40         private static Logger LOGGER = LoggerFactory.getLogger(SQLExecutionMonitor.class);
41         
42         final static long MILISECOND = 1000000L;
43         final static long SECOND = 1000L*MILISECOND;
44         
45         private final Timer timer;
46         // collection
47         private final SortedSet<TestObject> innerSet;
48         private SQLExecutionMonitorObserver parent = null; 
49         private final AtomicLong completionCounter;
50         private boolean activeState = false;
51         private final long interval;
52         private final long initialDelay;
53         private final long EXPECTED_TIME_TO_COMPLETE;
54         private final long UNPROCESSED_FAILOVER_THRESHOLD;
55
56         private final class MonitoringTask extends TimerTask 
57         {
58                 
59                 public void run() 
60                 {
61                         try {
62                                 TestObject testObj = new TestObject();
63                                 testObj.setStartTime(testObj.getStartTime() - EXPECTED_TIME_TO_COMPLETE);
64
65                                 // take a snapshot of the current task list
66                                 TestObject[] array = innerSet.toArray(new TestObject[0]);
67                                 SortedSet<TestObject> copyCurrent = new TreeSet<TestObject>(Arrays.asList(array));
68                                 // get the list of the tasks that are older than the specified
69                                 // interval.
70                                 SortedSet<TestObject> unprocessed = copyCurrent.headSet(testObj);
71
72                                 long succesfulCount = completionCounter.get();
73                                 int unprocessedCount = unprocessed.size();
74                                 
75                                 if (!unprocessed.isEmpty() && unprocessedCount > UNPROCESSED_FAILOVER_THRESHOLD && succesfulCount == 0)
76                                 {
77                                         // switch the Connection Pool to passive
78                                         setChanged();
79                                         notifyObservers("Open JDBC requests=" + unprocessedCount+" in "+SQLExecutionMonitor.this.parent.getDbConnectionName());
80                                 }
81                         } catch (Exception exc) {
82                                 LOGGER.error("", exc);
83                         } finally {
84                                 completionCounter.set(0L);
85                         }
86                 }
87         }
88
89         public static class TestObject implements Comparable<TestObject>, Serializable 
90         {
91
92                 private static final long serialVersionUID = 1L;
93                 private long starttime;
94                 private long randId;
95
96                 public TestObject()
97                 {
98                         starttime = System.nanoTime();
99                 }
100
101                 public long getStartTime()
102                 {
103                         return starttime;
104                 }
105
106                 public void setStartTime(long newTime) 
107                 {
108                         starttime = newTime;
109                 }
110
111                 public int compareTo(TestObject o)
112                 {
113                         if( this == o)
114                                 return 0;
115                         if(this.starttime > o.getStartTime())
116                                 return 1;
117                         if(this.starttime < o.getStartTime())
118                                 return -1;
119
120                         if(this.hashCode() > o.hashCode())
121                                 return 1;
122                         if(this.hashCode() < o.hashCode())
123                                 return -1;
124
125                         return 0;
126                 }
127
128                 public String toString()
129                 {
130                         return Long.toString(starttime)+"#"+ this.hashCode();
131                 }
132         
133                 public boolean equals(Object obj)
134                 {
135                         if (this == obj)
136                                 return true;
137
138                         return (obj instanceof TestObject 
139                             && starttime == ((TestObject) obj).getStartTime()
140                             && hashCode() == ((TestObject) obj).hashCode());            
141                 }
142         }
143
144         public SQLExecutionMonitor(SQLExecutionMonitorObserver parent)
145         {
146                 this.parent = parent;
147                 completionCounter = new AtomicLong(0L);
148                 interval = parent.getInterval();
149                 initialDelay = parent.getInitialDelay();
150                 this.UNPROCESSED_FAILOVER_THRESHOLD = parent.getUnprocessedFailoverThreshold();
151                 this.EXPECTED_TIME_TO_COMPLETE = parent.getExpectedCompletionTime()*MILISECOND;
152                 
153                 innerSet = Collections.synchronizedSortedSet(new TreeSet<TestObject>());
154                 timer = new Timer();
155         }
156         
157         public void cleanup()
158         {
159                 timer.cancel();
160         }
161         
162         // registerRequest
163         public TestObject registerRequest()
164         {
165                 if(activeState)
166                 {
167                         TestObject test = new TestObject();
168                         if(innerSet.add(test))
169                                 return test;
170                 }
171                 return null;
172         }
173
174         // deregisterSuccessfulReguest
175         public boolean deregisterReguest(TestObject test)
176         {
177                 if(test == null)
178                         return false;
179                 // remove from the collection
180                 if(innerSet.remove(test) && activeState)
181                 {
182                         completionCounter.incrementAndGet();
183                         return true;
184                 }
185                 return false; 
186         }
187
188         public void terminate() {
189                 timer.cancel();
190         }
191
192         /**
193          * @return the parent
194          */
195         public final Object getParent() {
196                 return parent;
197         }
198         
199         public void addObserver(Observer observer)
200         {
201                 if(observer instanceof DBResourceObserver)
202                 {
203                         DBResourceObserver dbObserver = (DBResourceObserver)observer;
204                         if(dbObserver.isMonitorDbResponse())
205                         {
206                                 if(countObservers() == 0)
207                                 {
208                                         TimerTask remindTask = new MonitoringTask();
209                                         timer.schedule(remindTask, initialDelay, interval);
210                                         activeState = true;
211                                 }
212                         }
213                 }
214                 super.addObserver(observer);
215         }
216         
217         public void deleteObserver(Observer observer)
218         {
219                 super.deleteObserver(observer);
220                 if(observer instanceof DBResourceObserver)
221                 {
222                         DBResourceObserver dbObserver = (DBResourceObserver)observer;
223                         if(dbObserver.isMonitorDbResponse())
224                         {
225                                 if(countObservers() == 0)
226                                 {
227                                         timer.cancel();
228                                         activeState = false;
229                                 }
230                         }
231                 }
232         }
233         
234         public final int getPorcessedConnectionsCount() {
235                 return innerSet.size();
236         }
237 }