3431d2774051bf17f212013ec13b1027552071d1
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / openecomp / appc / workingstatemanager / impl / WorkingStateManagerImpl.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 package org.openecomp.appc.workingstatemanager.impl;
26
27 import java.sql.Connection;
28 import java.sql.PreparedStatement;
29 import java.sql.ResultSet;
30 import java.sql.SQLException;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33
34 import org.apache.commons.lang.ObjectUtils;
35 import org.apache.commons.lang3.StringUtils;
36 import org.openecomp.appc.configuration.ConfigurationFactory;
37 import org.openecomp.appc.executor.objects.Params;
38 import org.openecomp.appc.message.RequestHandlerMessages;
39 import org.openecomp.appc.util.MessageFormatter;
40 import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
41 import org.openecomp.appc.workingstatemanager.objects.VnfWorkingStateDto;
42 import com.att.eelf.configuration.EELFLogger;
43 import com.att.eelf.configuration.EELFManager;
44 import org.apache.commons.lang3.StringUtils;
45
46
47 public class WorkingStateManagerImpl extends JdbcWorkingStateManager {
48
49     private static final String SQL_RETRIEVE_VNF_STATE_MANAGEMENT = "SELECT VNF_ID,STATE,OWNER_ID,UPDATED,VER FROM VNF_STATE_MANAGEMENT WHERE VNF_ID=?";
50     private static final String SQL_INSERT_VNF_STATE_MANAGEMENT = "INSERT IGNORE INTO VNF_STATE_MANAGEMENT (VNF_ID,STATE,OWNER_ID,UPDATED,VER) VALUES (?, ?, ?, ?, ?)";
51     private static final String SQL_UPDATE_VNF_STATE_MANAGEMENT = "UPDATE VNF_STATE_MANAGEMENT SET OWNER_ID=?, UPDATED=?, STATE=?, VER=? WHERE VNF_ID=? AND VER=?";
52     private static final String SQL_CURRENT_TIMESTAMP = "SELECT CURRENT_TIMESTAMP()";
53     private static int maxAttempts = ConfigurationFactory.getConfiguration().getIntegerProperty("org.openecomp.appc.workingstatemanager.maxAttempts",20);
54
55     private static Map<String,VNFWorkingState> workingStateMap = new ConcurrentHashMap<>();
56     private static final EELFLogger logger = EELFManager.getInstance().getLogger(WorkingStateManagerImpl.class);
57
58
59     /**
60      * Return true if vnf state exists in working state map and state is STABLE else return false. If vnf does not exists in working state map throws vnf not found  exception.
61      * @param vnfId vnf Id to be verified for stable state
62      * @return True if vnf Exists and state is STABLE else False.
63      */
64     @Override
65     public boolean isVNFStable(String vnfId){
66         if (logger.isTraceEnabled()) {
67             logger.trace("Entering to isVNFStable with vnfId = "+ vnfId);
68         }
69         Connection connection = null;
70         boolean vnfStable = false;
71         try {
72             connection = openDbConnection();
73             VnfWorkingStateDto vnfWorkingStateDto = retrieveVnfWorkingState(connection, vnfId);
74             vnfStable = isVNFStable(vnfWorkingStateDto);
75         } catch (SQLException e) {
76             String errMsg = StringUtils.isEmpty(e.getMessage())? e.toString() :e.getMessage();
77             throw new RuntimeException(errMsg);
78         } finally {
79             if(connection != null) {
80                 closeDbConnection(connection);
81         }
82         }
83         if (logger.isTraceEnabled()) {
84             logger.trace("Exiting from isVNFStable for vnfId = "+ vnfId+" with Result = "+vnfStable);
85         }
86         return vnfStable;
87     }
88
89     /**
90      * Updates working state for given vnf Id. Returns true if update was allowed and succeeded. Update will success only if the existing vnf state is 'STABLE' or
91      * if the registered ownerId is equal to the given ownerId or if the forceFlag is true.
92      * Note on case of simultaneously updates the latest updates will be failed, and another attempts will be done after refetching the updated data from persistent store.
93      * @param vnfId vnf Id to be updated
94      * @param workingState new working state
95      * @param ownerId
96      * @param forceFlag - force to update also on case given onwerId is different then the registered one
97      */
98     @Override
99     public boolean setWorkingState(String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag){
100         boolean updated = false;
101         if (logger.isTraceEnabled()) {
102             logger.trace("Entering to setWorkingState with vnfId = "+ ObjectUtils.toString(vnfId)+ ", VNFWorkingState = " +  workingState.name() + ", ownerId = "+ownerId+", forceFlag = "+forceFlag);
103         }
104         Connection connection = null;
105         try {
106             connection = openDbConnection();
107             updated = setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag, maxAttempts);
108         } catch (SQLException e) {
109             String errMsg = StringUtils.isEmpty(e.getMessage())? e.toString() :e.getMessage();
110             throw new RuntimeException(errMsg);
111         } finally {
112             if(connection != null) {
113                 closeDbConnection(connection);
114             }
115         }
116
117         logger.trace("setWorkingState exit with output updated = "+updated);
118         return updated;
119     }
120
121     public boolean setWorkingStateIfStableOrSameOwnerIdOrForce(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag, int maxAttempts) throws SQLException {
122         return setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag,1,maxAttempts);
123     }
124     public boolean setWorkingStateIfStableOrSameOwnerIdOrForce(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag,int attempt, int maxAttempts) throws SQLException {
125         boolean updated = false;
126         VnfWorkingStateDto vnfWorkingStateDto = retrieveVnfWorkingState(connection, vnfId);
127         Long currentVersion = vnfWorkingStateDto != null ? vnfWorkingStateDto.getVer() : null;
128         if(forceFlag || isVNFStable(vnfWorkingStateDto) || 
129                         ( vnfWorkingStateDto != null && vnfWorkingStateDto.getOwnerId().equals(ownerId)) ) {
130             updated = storeWorkingStateIfSameVersion(connection, vnfId, workingState, ownerId, currentVersion);
131
132             Params params = new Params().addParam("vnfId", vnfId).addParam("workingState",workingState.name())
133                     .addParam("attempt",attempt).addParam("maxAttempts",maxAttempts).addParam("ownerId",ownerId).addParam("forceFlag",forceFlag);
134             String logMessage;
135             if(updated) {
136                 logMessage = MessageFormatter.format(RequestHandlerMessages.VNF_WORKING_STATE_UPDATED, params.getParams());
137             }else {
138                 logMessage = MessageFormatter.format(RequestHandlerMessages.VNF_WORKING_STATE_WAS_NOT_UPDATED, params.getParams());
139             }
140             logger.debug(logMessage);
141             if(!updated && attempt<maxAttempts){
142                 setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag,++attempt,maxAttempts);
143             }
144
145         }
146         return updated;
147     }
148
149
150     public boolean storeWorkingStateIfSameVersion(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, Long currentVersion) throws SQLException {
151         boolean stored = false;
152         if (currentVersion != null) {
153             stored = updateStateIfSameVersion(connection, vnfId, ownerId, workingState.name(), currentVersion);
154         } else {
155             stored = addVnfWorkingStateIfNotExists(connection, vnfId, ownerId, workingState.name());
156         }
157
158         return stored;
159     }
160
161     private boolean isVNFStable(VnfWorkingStateDto vnfWorkingStateDto) {
162         if( vnfWorkingStateDto == null || vnfWorkingStateDto.getState() ==VNFWorkingState.STABLE){
163             return true;
164         }
165         return false;
166     }
167
168     public boolean updateStateIfSameVersion(Connection connection, String vnfId, String ownerId, String state, long currentVer) throws SQLException {
169         try(PreparedStatement statement = connection.prepareStatement(SQL_UPDATE_VNF_STATE_MANAGEMENT)) {
170             long newVer = (currentVer >= Long.MAX_VALUE) ? 1 : (currentVer + 1);
171             statement.setString(1, ownerId);
172             statement.setLong(2, getCurrentTime(connection));
173             statement.setString(3, state);
174             statement.setLong(4, newVer);
175             statement.setString(5, vnfId);
176             statement.setLong(6, currentVer);
177             return (statement.executeUpdate() != 0);
178         }
179     }
180
181     protected VnfWorkingStateDto retrieveVnfWorkingState(Connection connection, String vnfId) throws SQLException {
182         VnfWorkingStateDto res = null;
183
184         try(PreparedStatement statement = connection.prepareStatement(SQL_RETRIEVE_VNF_STATE_MANAGEMENT)) { //VNF_ID,STATE,OWNER_ID,UPDATED,VER
185             statement.setString(1, vnfId);
186             try(ResultSet resultSet = statement.executeQuery()) {
187                 if(resultSet.next()) {
188                     res = new VnfWorkingStateDto(vnfId);
189                     String stateString = resultSet.getString(2);
190                     VNFWorkingState vnfWorkingState = VNFWorkingState.valueOf(stateString);
191                     res.setState(vnfWorkingState);
192                     res.setOwnerId(resultSet.getString(3));
193                     res.setUpdated(resultSet.getLong(4));
194                     res.setVer(resultSet.getLong(5));
195                 }
196             }
197         }
198         return res;
199     }
200
201     private long getCurrentTime(Connection connection) throws SQLException {
202         long res = -1;
203         if(connection != null) {
204             try(PreparedStatement statement = connection.prepareStatement(SQL_CURRENT_TIMESTAMP)) {
205                 try(ResultSet resultSet = statement.executeQuery()) {
206                     if(resultSet.next()) {
207                         res = resultSet.getTimestamp(1).getTime();
208                     }
209                 }
210             }
211         }
212         if(res == -1) {
213             res = System.currentTimeMillis();
214         }
215         return res;
216         }
217
218     protected boolean addVnfWorkingStateIfNotExists(Connection connection, String vnfId, String ownerId, String state) throws SQLException {
219         boolean added = false;
220         try(PreparedStatement statement = connection.prepareStatement(SQL_INSERT_VNF_STATE_MANAGEMENT)) { //VNF_ID,STATE,OWNER_ID,UPDATED,VER
221             statement.setString(1, vnfId);
222             statement.setString(2, state);
223             statement.setString(3, ownerId);
224             statement.setLong(4, getCurrentTime(connection));
225             statement.setLong(5, 1L);
226             int rowCount = statement.executeUpdate();
227             added = rowCount != 0 ? true : false;
228         }
229         return added;
230     }
231 }