aboutsummaryrefslogtreecommitdiffstats
path: root/app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/workingstatemanager/impl/WorkingStateManagerImpl.java
blob: 732a413045ed9bf0223acc98696ce075f12ff78f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*-
 * ============LICENSE_START=======================================================
 * openECOMP : APP-C
 * ================================================================================
 * Copyright (C) 2017 AT&T Intellectual Property. All rights
 * 						reserved.
 * ================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============LICENSE_END=========================================================
 */

package org.openecomp.appc.workingstatemanager.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.openecomp.appc.configuration.ConfigurationFactory;
import org.openecomp.appc.executor.objects.Params;
import org.openecomp.appc.message.RequestHandlerMessages;
import org.openecomp.appc.util.MessageFormatter;
import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
import org.openecomp.appc.workingstatemanager.objects.VnfWorkingStateDto;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
import org.apache.commons.lang3.StringUtils;


public class WorkingStateManagerImpl extends JdbcWorkingStateManager {

    private static final String SQL_RETRIEVE_VNF_STATE_MANAGEMENT = "SELECT VNF_ID,STATE,OWNER_ID,UPDATED,VER FROM VNF_STATE_MANAGEMENT WHERE VNF_ID=?";
    private static final String SQL_INSERT_VNF_STATE_MANAGEMENT = "INSERT IGNORE INTO VNF_STATE_MANAGEMENT (VNF_ID,STATE,OWNER_ID,UPDATED,VER) VALUES (?, ?, ?, ?, ?)";
    private static final String SQL_UPDATE_VNF_STATE_MANAGEMENT = "UPDATE VNF_STATE_MANAGEMENT SET OWNER_ID=?, UPDATED=?, STATE=?, VER=? WHERE VNF_ID=? AND VER=?";
    private static final String SQL_CURRENT_TIMESTAMP = "SELECT CURRENT_TIMESTAMP()";
    private static int maxAttempts = ConfigurationFactory.getConfiguration().getIntegerProperty("org.openecomp.appc.workingstatemanager.maxAttempts",20);

    private static Map<String,VNFWorkingState> workingStateMap = new ConcurrentHashMap<>();
    private static final EELFLogger logger = EELFManager.getInstance().getLogger(WorkingStateManagerImpl.class);


    /**
     * 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.
     * @param vnfId vnf Id to be verified for stable state
     * @return True if vnf Exists and state is STABLE else False.
     */
    @Override
    public boolean isVNFStable(String vnfId){
        if (logger.isTraceEnabled()) {
            logger.trace("Entering to isVNFStable with vnfId = "+ vnfId);
        }
        Connection connection = null;
        boolean vnfStable = false;
        try {
            connection = openDbConnection();
            VnfWorkingStateDto vnfWorkingStateDto = retrieveVnfWorkingState(connection, vnfId);
            vnfStable = isVNFStable(vnfWorkingStateDto);
        } catch (SQLException e) {
            String errMsg = StringUtils.isEmpty(e.getMessage())? e.toString() :e.getMessage();
            throw new RuntimeException(errMsg);
        } finally {
            if(connection != null) {
                closeDbConnection(connection);
        }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Exiting from isVNFStable for vnfId = "+ vnfId+" with Result = "+vnfStable);
        }
        return vnfStable;
    }

    /**
     * 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
     * if the registered ownerId is equal to the given ownerId or if the forceFlag is true.
     * 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.
     * @param vnfId vnf Id to be updated
     * @param workingState new working state
     * @param ownerId
     * @param forceFlag - force to update also on case given onwerId is different then the registered one
     */
    @Override
    public boolean setWorkingState(String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag){
        boolean updated = false;
        if (logger.isTraceEnabled()) {
            logger.trace("Entering to setWorkingState with vnfId = "+ ObjectUtils.toString(vnfId)+ ", VNFWorkingState = " +  workingState.name() + ", ownerId = "+ownerId+", forceFlag = "+forceFlag);
        }
        Connection connection = null;
        try {
            connection = openDbConnection();
            updated = setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag, maxAttempts);
        } catch (SQLException e) {
            String errMsg = StringUtils.isEmpty(e.getMessage())? e.toString() :e.getMessage();
            throw new RuntimeException(errMsg);
        } finally {
            if(connection != null) {
                closeDbConnection(connection);
            }
        }

        logger.trace("setWorkingState exit with output updated = "+updated);
        return updated;
    }

    public boolean setWorkingStateIfStableOrSameOwnerIdOrForce(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag, int maxAttempts) throws SQLException {
        return setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag,1,maxAttempts);
    }
    public boolean setWorkingStateIfStableOrSameOwnerIdOrForce(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, boolean forceFlag,int attempt, int maxAttempts) throws SQLException {
        boolean updated = false;
        VnfWorkingStateDto vnfWorkingStateDto = retrieveVnfWorkingState(connection, vnfId);
        Long currentVersion = vnfWorkingStateDto != null ? vnfWorkingStateDto.getVer() : null;
        if(forceFlag || isVNFStable(vnfWorkingStateDto) || vnfWorkingStateDto.getOwnerId().equals(ownerId)){
            updated = storeWorkingStateIfSameVersion(connection, vnfId, workingState, ownerId, currentVersion);

            Params params = new Params().addParam("vnfId", vnfId).addParam("workingState",workingState.name())
                    .addParam("attempt",attempt).addParam("maxAttempts",maxAttempts).addParam("ownerId",ownerId).addParam("forceFlag",forceFlag);
            String logMessage;
            if(updated) {
                logMessage = MessageFormatter.format(RequestHandlerMessages.VNF_WORKING_STATE_UPDATED, params.getParams());
            }else {
                logMessage = MessageFormatter.format(RequestHandlerMessages.VNF_WORKING_STATE_WAS_NOT_UPDATED, params.getParams());
            }
            logger.debug(logMessage);
            if(!updated && attempt<maxAttempts){
                setWorkingStateIfStableOrSameOwnerIdOrForce(connection, vnfId, workingState, ownerId, forceFlag,++attempt,maxAttempts);
            }

        }
        return updated;
    }


    public boolean storeWorkingStateIfSameVersion(Connection connection, String vnfId, VNFWorkingState workingState, String ownerId, Long currentVersion) throws SQLException {
        boolean stored = false;
        if (currentVersion != null) {
            stored = updateStateIfSameVersion(connection, vnfId, ownerId, workingState.name(), currentVersion);
        } else {
            stored = addVnfWorkingStateIfNotExists(connection, vnfId, ownerId, workingState.name());
        }

        return stored;
    }

    private boolean isVNFStable(VnfWorkingStateDto vnfWorkingStateDto) {
        if( vnfWorkingStateDto == null || vnfWorkingStateDto.getState() ==VNFWorkingState.STABLE){
            return true;
        }
        return false;
    }

    public boolean updateStateIfSameVersion(Connection connection, String vnfId, String ownerId, String state, long currentVer) throws SQLException {
        try(PreparedStatement statement = connection.prepareStatement(SQL_UPDATE_VNF_STATE_MANAGEMENT)) {
            long newVer = (currentVer >= Long.MAX_VALUE) ? 1 : (currentVer + 1);
            statement.setString(1, ownerId);
            statement.setLong(2, getCurrentTime(connection));
            statement.setString(3, state);
            statement.setLong(4, newVer);
            statement.setString(5, vnfId);
            statement.setLong(6, currentVer);
            return (statement.executeUpdate() != 0);
        }
    }

    protected VnfWorkingStateDto retrieveVnfWorkingState(Connection connection, String vnfId) throws SQLException {
        VnfWorkingStateDto res = null;

        try(PreparedStatement statement = connection.prepareStatement(SQL_RETRIEVE_VNF_STATE_MANAGEMENT)) { //VNF_ID,STATE,OWNER_ID,UPDATED,VER
            statement.setString(1, vnfId);
            try(ResultSet resultSet = statement.executeQuery()) {
                if(resultSet.next()) {
                    res = new VnfWorkingStateDto(vnfId);
                    String stateString = resultSet.getString(2);
                    VNFWorkingState vnfWorkingState = VNFWorkingState.valueOf(stateString);
                    res.setState(vnfWorkingState);
                    res.setOwnerId(resultSet.getString(3));
                    res.setUpdated(resultSet.getLong(4));
                    res.setVer(resultSet.getLong(5));
                }
            }
        }
        return res;
    }

    private long getCurrentTime(Connection connection) throws SQLException {
        long res = -1;
        if(connection != null) {
            try(PreparedStatement statement = connection.prepareStatement(SQL_CURRENT_TIMESTAMP)) {
                try(ResultSet resultSet = statement.executeQuery()) {
                    if(resultSet.next()) {
                        res = resultSet.getTimestamp(1).getTime();
                    }
                }
            }
        }
        if(res == -1) {
            res = System.currentTimeMillis();
        }
        return res;
        }

    protected boolean addVnfWorkingStateIfNotExists(Connection connection, String vnfId, String ownerId, String state) throws SQLException {
        boolean added = false;
        try(PreparedStatement statement = connection.prepareStatement(SQL_INSERT_VNF_STATE_MANAGEMENT)) { //VNF_ID,STATE,OWNER_ID,UPDATED,VER
            statement.setString(1, vnfId);
            statement.setString(2, state);
            statement.setString(3, ownerId);
            statement.setLong(4, getCurrentTime(connection));
            statement.setLong(5, 1L);
            int rowCount = statement.executeUpdate();
            added = rowCount != 0 ? true : false;
        }
        return added;
    }
}