Initial source code
[oam/tr069-adapter.git] / acs / requestprocessor / src / main / java / org / commscope / tr069adapter / acs / requestprocessor / impl / SessionTimeoutHandler.java
diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/SessionTimeoutHandler.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/SessionTimeoutHandler.java
new file mode 100644 (file)
index 0000000..50af917
--- /dev/null
@@ -0,0 +1,216 @@
+/*\r
+ * ============LICENSE_START========================================================================\r
+ * ONAP : tr-069-adapter\r
+ * =================================================================================================\r
+ * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
+ * =================================================================================================\r
+ * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
+ * may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
+ * either express or implied. See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ===============LICENSE_END=======================================================================\r
+ */\r
+\r
+package org.commscope.tr069adapter.acs.requestprocessor.impl;\r
+\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.CONNECTION_REQUEST;\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.DEVICE_RESPONSE_TIMEOUT;\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SEPERATOR;\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SESSION_TIMEOUT_CALLBACK_JNDI;\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.WAITING_FOR_DEVICE_RESPONSE;\r
+import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.WAITING_FOR_NBI_RESPONSE;\r
+\r
+import java.io.Serializable;\r
+import java.util.List;\r
+\r
+import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;\r
+import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;\r
+import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails;\r
+import org.commscope.tr069adapter.acs.common.exception.DeviceOperationException;\r
+import org.commscope.tr069adapter.acs.common.exception.SessionManagerException;\r
+import org.commscope.tr069adapter.acs.common.utils.ErrorCode;\r
+import org.commscope.tr069adapter.acs.requestprocessor.DeviceOperationInterface;\r
+import org.commscope.tr069adapter.acs.requestprocessor.dao.DeviceRPCRequestRepositoryHelper;\r
+import org.commscope.tr069adapter.acs.requestprocessor.dto.SessionDTO;\r
+import org.commscope.tr069adapter.acs.requestprocessor.dto.SessionState;\r
+import org.commscope.tr069adapter.acs.requestprocessor.entity.TR069DeviceRPCRequestEntity;\r
+import org.commscope.tr069adapter.acs.requestprocessor.helper.TR069RequestProcessEngineUtility;\r
+import org.commscope.tr069adapter.acs.requestprocessor.util.TR069RequestProcessorUtility;\r
+import org.commscope.tr069adapter.common.timer.TimerException;\r
+import org.commscope.tr069adapter.common.timer.TimerListener;\r
+import org.commscope.tr069adapter.common.timer.TimerServiceManagerAPI;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.slf4j.MDC;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Isolation;\r
+import org.springframework.transaction.annotation.Propagation;\r
+import org.springframework.transaction.annotation.Transactional;\r
+\r
+@Component(SESSION_TIMEOUT_CALLBACK_JNDI)\r
+public class SessionTimeoutHandler implements TimerListener {\r
+\r
+\r
+\r
+  private static final Logger logger = LoggerFactory.getLogger(SessionTimeoutHandler.class);\r
+\r
+  private static final String CLIENT_STR = "client";\r
+\r
+  @Autowired\r
+  private SessionManager sessionManager;\r
+\r
+  @Autowired\r
+  TR069EventNotificationService eventNotificationService;\r
+\r
+  @Autowired\r
+  DeviceOperationInterface deviceOperationInterface;\r
+\r
+  @Autowired\r
+  private TimerServiceManagerAPI timerServiceManagerAPI;\r
+\r
+  @Autowired\r
+  private DeviceRPCRequestRepositoryHelper deviceRPCRequestRepositoryHelper;\r
+\r
+  @Autowired\r
+  private TR069RequestProcessEngineUtility tr069ProcessEngineUtility;\r
+\r
+  @Transactional(isolation = Isolation.DEFAULT, timeout = 300,\r
+      propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})\r
+  @Override\r
+  public void notifyTimeout(String timerId, Serializable data) {\r
+\r
+    String timeoutType = (String) data;\r
+\r
+    logger.info("Timeout notification received for the type: {}", timeoutType);\r
+    if (WAITING_FOR_NBI_RESPONSE.equals(timeoutType)) {\r
+      handleNBIResponseTimeout(timerId);\r
+    } else if (WAITING_FOR_DEVICE_RESPONSE.equals(timeoutType)) {\r
+      handleDeviceResponseTimeout(timerId);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Handling the NBI response timeout\r
+   * \r
+   * @param timerId\r
+   */\r
+  private void handleNBIResponseTimeout(String timerId) {\r
+    String[] splitTimerId = timerId.split(SEPERATOR);\r
+    String deviceId = splitTimerId[0];\r
+    String operationId = splitTimerId[1];\r
+    try {\r
+      MDC.put(CLIENT_STR, deviceId);\r
+      // Only session must be moved to terminated state in such case\r
+      logger.debug("The NBI operation request {} has timeout", operationId);\r
+\r
+      TR069DeviceDetails deviceDetails = deviceOperationInterface.getDeviceDetails(deviceId);\r
+      List<TR069DeviceRPCRequestEntity> deviceRPCRequestEntityList =\r
+          deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(deviceId,\r
+              Long.valueOf(operationId));\r
+\r
+      if (deviceRPCRequestEntityList != null) {\r
+        logger.debug(\r
+            "Device details and the NBI Operation request are successfully fetched for operationId: {}",\r
+            operationId);\r
+        DeviceRPCRequest nbiDeviceOperationrequest =\r
+            TR069RequestProcessorUtility.convertToDTO(deviceRPCRequestEntityList);\r
+        DeviceRPCResponse deviceRPCResponse = tr069ProcessEngineUtility\r
+            .buildTimedOutOperationResult(deviceDetails, nbiDeviceOperationrequest);\r
+\r
+        eventNotificationService.sendOperationResultToNBI(deviceRPCResponse);\r
+        logger.debug("Successfully notified timed out operation result to NBI");\r
+\r
+        // Marking the NBI Request as processed\r
+        for (TR069DeviceRPCRequestEntity deviceRPCRequestEntity : deviceRPCRequestEntityList) {\r
+          deviceRPCRequestEntity.setIsProcessed(Integer.valueOf(1));\r
+        }\r
+        deviceRPCRequestRepositoryHelper.saveAll(deviceRPCRequestEntityList);\r
+\r
+        logger.debug("Stopping the connection request timer if any running");\r
+        String connectionRequestTimerId = deviceId + SEPERATOR + CONNECTION_REQUEST;\r
+        timerServiceManagerAPI.stopTimer(connectionRequestTimerId);\r
+      }\r
+    } catch (DeviceOperationException e) {\r
+      logger.error(\r
+          "Fetching device details failed for timed out operation processing for operation id: {} Reason: {}",\r
+          operationId, e.getMessage());\r
+    } catch (TimerException e) {\r
+      logger.debug(\r
+          "Failed stopping the timer job for connection request retry timer for operation id: {} Reason: {}",\r
+          operationId, e.getMessage());\r
+    } catch (Exception e) {\r
+      logger.error(\r
+          "An unknown exception occurred while timed out operation processing for operation id: {} Reason: {}",\r
+          operationId, e.getMessage());\r
+    } finally {\r
+      MDC.remove(CLIENT_STR);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Handling the device inform response timeout\r
+   * \r
+   * @param sessionId\r
+   */\r
+  private void handleDeviceResponseTimeout(String sessionId) {\r
+    SessionDTO session = null;\r
+    try {\r
+      session = sessionManager.getSessionBySessionId(sessionId);\r
+    } catch (SessionManagerException e) {\r
+      if (ErrorCode.SESSION_EXPIRED.equals(e.getErrorCode())) {\r
+        logger.info(\r
+            "The session {} does not exist or already in TERMINATED state, hence ignoring the timeout notification",\r
+            sessionId);\r
+        return;\r
+      }\r
+\r
+      logger.debug("Session fetching failed, Reason: {} ", e.getMessage());\r
+    }\r
+\r
+    try {\r
+      // Only session must be moved to terminated state in such case\r
+      if (session != null) {\r
+        MDC.put(CLIENT_STR, session.getDeviceId());\r
+        boolean isSessionReset = false;\r
+\r
+        String deviceId = session.getDeviceId();\r
+        Long operationId = session.getCurrentOperationId();\r
+        if (operationId != null && operationId != 0l\r
+            && !SessionState.TERMINATED.equals(session.getSessionState())) {\r
+          List<TR069DeviceRPCRequestEntity> deviceRPCRequestEntityList =\r
+              deviceRPCRequestRepositoryHelper.findByDeviceIdAndOperationId(deviceId, operationId);\r
+          Integer isProcessed = deviceRPCRequestEntityList.get(0).getIsProcessed();\r
+          if (isProcessed != null && isProcessed == 0) {\r
+            logger.debug(\r
+                "The Device RPC request is still in processing state, hence resetting the session timer");\r
+            timerServiceManagerAPI.modifyTimer(sessionId, DEVICE_RESPONSE_TIMEOUT,\r
+                WAITING_FOR_DEVICE_RESPONSE);\r
+            logger.debug("Successfully restarted the session timer for session: {} ", sessionId);\r
+            isSessionReset = true;\r
+          }\r
+        }\r
+\r
+        if (!isSessionReset) {\r
+          logger.debug("Updating the session state to terminated");\r
+          session.setSessionState(SessionState.TERMINATED);\r
+          sessionManager.updateSession(session);\r
+          logger.debug("Successfully handled timeout notification of Device Response");\r
+        }\r
+      }\r
+    } catch (Exception e) {\r
+      logger.error(\r
+          "An error occurred while checking the NBI state to reset the session timer, Reason: {}",\r
+          e.getMessage());\r
+      logger.debug("Updating the session to TERMINATED failed during timeout, Reason: {}",\r
+          e.getMessage());\r
+    } finally {\r
+      MDC.remove(CLIENT_STR);\r
+    }\r
+  }\r
+}\r