Initial source code
[oam/tr069-adapter.git] / acs / requestprocessor / src / main / java / org / commscope / tr069adapter / acs / requestprocessor / impl / SessionTimeoutHandler.java
1 /*\r
2  * ============LICENSE_START========================================================================\r
3  * ONAP : tr-069-adapter\r
4  * =================================================================================================\r
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
6  * =================================================================================================\r
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
9  * may obtain a copy of the License at\r
10  *\r
11  * http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
14  * either express or implied. See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  * ===============LICENSE_END=======================================================================\r
17  */\r
18 \r
19 package org.commscope.tr069adapter.acs.requestprocessor.impl;\r
20 \r
21 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.CONNECTION_REQUEST;\r
22 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.DEVICE_RESPONSE_TIMEOUT;\r
23 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SEPERATOR;\r
24 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SESSION_TIMEOUT_CALLBACK_JNDI;\r
25 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.WAITING_FOR_DEVICE_RESPONSE;\r
26 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.WAITING_FOR_NBI_RESPONSE;\r
27 \r
28 import java.io.Serializable;\r
29 import java.util.List;\r
30 \r
31 import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;\r
32 import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;\r
33 import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails;\r
34 import org.commscope.tr069adapter.acs.common.exception.DeviceOperationException;\r
35 import org.commscope.tr069adapter.acs.common.exception.SessionManagerException;\r
36 import org.commscope.tr069adapter.acs.common.utils.ErrorCode;\r
37 import org.commscope.tr069adapter.acs.requestprocessor.DeviceOperationInterface;\r
38 import org.commscope.tr069adapter.acs.requestprocessor.dao.DeviceRPCRequestRepositoryHelper;\r
39 import org.commscope.tr069adapter.acs.requestprocessor.dto.SessionDTO;\r
40 import org.commscope.tr069adapter.acs.requestprocessor.dto.SessionState;\r
41 import org.commscope.tr069adapter.acs.requestprocessor.entity.TR069DeviceRPCRequestEntity;\r
42 import org.commscope.tr069adapter.acs.requestprocessor.helper.TR069RequestProcessEngineUtility;\r
43 import org.commscope.tr069adapter.acs.requestprocessor.util.TR069RequestProcessorUtility;\r
44 import org.commscope.tr069adapter.common.timer.TimerException;\r
45 import org.commscope.tr069adapter.common.timer.TimerListener;\r
46 import org.commscope.tr069adapter.common.timer.TimerServiceManagerAPI;\r
47 import org.slf4j.Logger;\r
48 import org.slf4j.LoggerFactory;\r
49 import org.slf4j.MDC;\r
50 import org.springframework.beans.factory.annotation.Autowired;\r
51 import org.springframework.stereotype.Component;\r
52 import org.springframework.transaction.annotation.Isolation;\r
53 import org.springframework.transaction.annotation.Propagation;\r
54 import org.springframework.transaction.annotation.Transactional;\r
55 \r
56 @Component(SESSION_TIMEOUT_CALLBACK_JNDI)\r
57 public class SessionTimeoutHandler implements TimerListener {\r
58 \r
59 \r
60 \r
61   private static final Logger logger = LoggerFactory.getLogger(SessionTimeoutHandler.class);\r
62 \r
63   private static final String CLIENT_STR = "client";\r
64 \r
65   @Autowired\r
66   private SessionManager sessionManager;\r
67 \r
68   @Autowired\r
69   TR069EventNotificationService eventNotificationService;\r
70 \r
71   @Autowired\r
72   DeviceOperationInterface deviceOperationInterface;\r
73 \r
74   @Autowired\r
75   private TimerServiceManagerAPI timerServiceManagerAPI;\r
76 \r
77   @Autowired\r
78   private DeviceRPCRequestRepositoryHelper deviceRPCRequestRepositoryHelper;\r
79 \r
80   @Autowired\r
81   private TR069RequestProcessEngineUtility tr069ProcessEngineUtility;\r
82 \r
83   @Transactional(isolation = Isolation.DEFAULT, timeout = 300,\r
84       propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})\r
85   @Override\r
86   public void notifyTimeout(String timerId, Serializable data) {\r
87 \r
88     String timeoutType = (String) data;\r
89 \r
90     logger.info("Timeout notification received for the type: {}", timeoutType);\r
91     if (WAITING_FOR_NBI_RESPONSE.equals(timeoutType)) {\r
92       handleNBIResponseTimeout(timerId);\r
93     } else if (WAITING_FOR_DEVICE_RESPONSE.equals(timeoutType)) {\r
94       handleDeviceResponseTimeout(timerId);\r
95     }\r
96   }\r
97 \r
98   /**\r
99    * Handling the NBI response timeout\r
100    * \r
101    * @param timerId\r
102    */\r
103   private void handleNBIResponseTimeout(String timerId) {\r
104     String[] splitTimerId = timerId.split(SEPERATOR);\r
105     String deviceId = splitTimerId[0];\r
106     String operationId = splitTimerId[1];\r
107     try {\r
108       MDC.put(CLIENT_STR, deviceId);\r
109       // Only session must be moved to terminated state in such case\r
110       logger.debug("The NBI operation request {} has timeout", operationId);\r
111 \r
112       TR069DeviceDetails deviceDetails = deviceOperationInterface.getDeviceDetails(deviceId);\r
113       List<TR069DeviceRPCRequestEntity> deviceRPCRequestEntityList =\r
114           deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(deviceId,\r
115               Long.valueOf(operationId));\r
116 \r
117       if (deviceRPCRequestEntityList != null) {\r
118         logger.debug(\r
119             "Device details and the NBI Operation request are successfully fetched for operationId: {}",\r
120             operationId);\r
121         DeviceRPCRequest nbiDeviceOperationrequest =\r
122             TR069RequestProcessorUtility.convertToDTO(deviceRPCRequestEntityList);\r
123         DeviceRPCResponse deviceRPCResponse = tr069ProcessEngineUtility\r
124             .buildTimedOutOperationResult(deviceDetails, nbiDeviceOperationrequest);\r
125 \r
126         eventNotificationService.sendOperationResultToNBI(deviceRPCResponse);\r
127         logger.debug("Successfully notified timed out operation result to NBI");\r
128 \r
129         // Marking the NBI Request as processed\r
130         for (TR069DeviceRPCRequestEntity deviceRPCRequestEntity : deviceRPCRequestEntityList) {\r
131           deviceRPCRequestEntity.setIsProcessed(Integer.valueOf(1));\r
132         }\r
133         deviceRPCRequestRepositoryHelper.saveAll(deviceRPCRequestEntityList);\r
134 \r
135         logger.debug("Stopping the connection request timer if any running");\r
136         String connectionRequestTimerId = deviceId + SEPERATOR + CONNECTION_REQUEST;\r
137         timerServiceManagerAPI.stopTimer(connectionRequestTimerId);\r
138       }\r
139     } catch (DeviceOperationException e) {\r
140       logger.error(\r
141           "Fetching device details failed for timed out operation processing for operation id: {} Reason: {}",\r
142           operationId, e.getMessage());\r
143     } catch (TimerException e) {\r
144       logger.debug(\r
145           "Failed stopping the timer job for connection request retry timer for operation id: {} Reason: {}",\r
146           operationId, e.getMessage());\r
147     } catch (Exception e) {\r
148       logger.error(\r
149           "An unknown exception occurred while timed out operation processing for operation id: {} Reason: {}",\r
150           operationId, e.getMessage());\r
151     } finally {\r
152       MDC.remove(CLIENT_STR);\r
153     }\r
154   }\r
155 \r
156   /**\r
157    * Handling the device inform response timeout\r
158    * \r
159    * @param sessionId\r
160    */\r
161   private void handleDeviceResponseTimeout(String sessionId) {\r
162     SessionDTO session = null;\r
163     try {\r
164       session = sessionManager.getSessionBySessionId(sessionId);\r
165     } catch (SessionManagerException e) {\r
166       if (ErrorCode.SESSION_EXPIRED.equals(e.getErrorCode())) {\r
167         logger.info(\r
168             "The session {} does not exist or already in TERMINATED state, hence ignoring the timeout notification",\r
169             sessionId);\r
170         return;\r
171       }\r
172 \r
173       logger.debug("Session fetching failed, Reason: {} ", e.getMessage());\r
174     }\r
175 \r
176     try {\r
177       // Only session must be moved to terminated state in such case\r
178       if (session != null) {\r
179         MDC.put(CLIENT_STR, session.getDeviceId());\r
180         boolean isSessionReset = false;\r
181 \r
182         String deviceId = session.getDeviceId();\r
183         Long operationId = session.getCurrentOperationId();\r
184         if (operationId != null && operationId != 0l\r
185             && !SessionState.TERMINATED.equals(session.getSessionState())) {\r
186           List<TR069DeviceRPCRequestEntity> deviceRPCRequestEntityList =\r
187               deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(deviceId, operationId);\r
188           Integer isProcessed = deviceRPCRequestEntityList.get(0).getIsProcessed();\r
189           if (isProcessed != null && isProcessed == 0) {\r
190             logger.debug(\r
191                 "The Device RPC request is still in processing state, hence resetting the session timer");\r
192             timerServiceManagerAPI.modifyTimer(sessionId, DEVICE_RESPONSE_TIMEOUT,\r
193                 WAITING_FOR_DEVICE_RESPONSE);\r
194             logger.debug("Successfully restarted the session timer for session: {} ", sessionId);\r
195             isSessionReset = true;\r
196           }\r
197         }\r
198 \r
199         if (!isSessionReset) {\r
200           logger.debug("Updating the session state to terminated");\r
201           session.setSessionState(SessionState.TERMINATED);\r
202           sessionManager.updateSession(session);\r
203           logger.debug("Successfully handled timeout notification of Device Response");\r
204         }\r
205       }\r
206     } catch (Exception e) {\r
207       logger.error(\r
208           "An error occurred while checking the NBI state to reset the session timer, Reason: {}",\r
209           e.getMessage());\r
210       logger.debug("Updating the session to TERMINATED failed during timeout, Reason: {}",\r
211           e.getMessage());\r
212     } finally {\r
213       MDC.remove(CLIENT_STR);\r
214     }\r
215   }\r
216 }\r