re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / common / transaction / mngr / TransactionSdncImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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.sdc.common.transaction.mngr;
22
23 import fj.data.Either;
24 import org.openecomp.sdc.be.config.BeEcompErrorManager;
25 import org.openecomp.sdc.be.dao.impl.ESCatalogDAO;
26 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
27 import org.openecomp.sdc.be.resources.data.ESArtifactData;
28 import org.openecomp.sdc.common.log.wrappers.Logger;
29 import org.openecomp.sdc.common.transaction.api.*;
30 import org.openecomp.sdc.common.transaction.api.TransactionUtils.*;
31 import org.openecomp.sdc.common.transaction.impl.ESAction;
32 import org.openecomp.sdc.common.transaction.impl.ESRollbackHandler;
33 import org.openecomp.sdc.common.transaction.impl.TitanCommitHandler;
34 import org.openecomp.sdc.common.transaction.impl.TitanRollbackHandler;
35 import org.openecomp.sdc.common.util.MethodActivationStatusEnum;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40 public class TransactionSdncImpl implements ITransactionSdnc {
41
42     // TODO test using slf4j-test and make this final
43     private static Logger log = Logger.getLogger(TransactionSdncImpl.class);
44     private boolean lastActionAlreadyCalled;
45     private RollbackManager rollbackManager;
46     private CommitManager commitManager;
47     private ESCatalogDAO esCatalogDao;
48     private TitanGenericDao titanGenericDao;
49     private Integer transactionId;
50     private TransactionStatusEnum status;
51     private String userId, actionType;
52
53     TransactionSdncImpl(Integer transactionId, String userId, ActionTypeEnum actionTypeEnum, ESCatalogDAO esCatalogDao, TitanGenericDao titanGenericDao) {
54         this.esCatalogDao = esCatalogDao;
55         this.titanGenericDao = titanGenericDao;
56         this.transactionId = transactionId;
57         this.userId = userId;
58         actionType = actionTypeEnum.name();
59         rollbackManager = new RollbackManager(transactionId, userId, actionType, initRollbackHandlers());
60         commitManager = new CommitManager(transactionId, userId, actionType, initCommitHandlers());
61         status = TransactionStatusEnum.OPEN;
62
63     }
64
65     private List<ICommitHandler> initCommitHandlers() {
66         List<ICommitHandler> commitHandlers = new ArrayList<>();
67         commitHandlers.add(new TitanCommitHandler(titanGenericDao));
68         return commitHandlers;
69     }
70
71     private List<RollbackHandler> initRollbackHandlers() {
72         List<RollbackHandler> rolebackHandlers = new ArrayList<>();
73         rolebackHandlers.add(new TitanRollbackHandler(transactionId, userId, actionType, titanGenericDao));
74         rolebackHandlers.add(new ESRollbackHandler(transactionId, userId, actionType));
75         return rolebackHandlers;
76     }
77
78     private <T> Either<T, TransactionCodeEnum> invokeAction(boolean isLastAction, IDBAction dbAction, DBTypeEnum dbType) {
79
80         Either<T, DBActionCodeEnum> actionResult;
81         log.debug(LogMessages.INVOKE_ACTION, transactionId, dbType.name(), userId, actionType);
82         if (isLastAction) {
83             actionResult = getLastActionResult(dbAction, dbType);
84         } else {
85             actionResult = getActionResult(dbAction, dbType);
86         }
87
88         Either<T, TransactionCodeEnum> result;
89         boolean isRollbackNedded = actionResult.isRight();
90         if (isRollbackNedded) {
91             TransactionCodeEnum transactionCode = transactionRollback();
92             result = Either.right(transactionCode);
93         } else {
94             result = Either.left(actionResult.left().value());
95         }
96         return result;
97     }
98
99     private TransactionCodeEnum transactionRollback() {
100
101         TransactionCodeEnum result;
102         DBActionCodeEnum transactionRollback = rollbackManager.transactionRollback();
103         if (transactionRollback == DBActionCodeEnum.SUCCESS) {
104             result = TransactionCodeEnum.ROLLBACK_SUCCESS;
105             log.info(LogMessages.ROLLBACK_SUCCEEDED_GENERAL, transactionId, userId, actionType);
106             log.info(TransactionUtils.TRANSACTION_MARKER, LogMessages.ROLLBACK_SUCCEEDED_GENERAL, transactionId, userId, actionType);
107
108         } else {
109             result = TransactionCodeEnum.ROLLBACK_FAILED;
110             BeEcompErrorManager.getInstance().logBeSystemError("transactionCommit for transaction " + transactionId);
111
112             log.info(LogMessages.ROLLBACK_FAILED_GENERAL, transactionId, userId, actionType);
113             log.debug(TransactionUtils.TRANSACTION_MARKER, LogMessages.ROLLBACK_FAILED_GENERAL, transactionId, userId, actionType);
114         }
115         return result;
116     }
117
118     public <T> Either<T, TransactionCodeEnum> invokeTitanAction(boolean isLastAction, IDBAction dbAction) {
119         Either<T, TransactionCodeEnum> result;
120         if (status == TransactionStatusEnum.OPEN) {
121             result = invokeAction(isLastAction, dbAction, DBTypeEnum.TITAN);
122         } else {
123             result = handleActionOnClosedTransaction();
124         }
125         updateTransactionStatus(result);
126         return result;
127     }
128
129     public <T> Either<T, TransactionCodeEnum> invokeGeneralDBAction(boolean isLastAction, DBTypeEnum dbType, IDBAction dbAction, IDBAction dbRollbackAction) {
130
131         Either<T, TransactionCodeEnum> result;
132         MethodActivationStatusEnum addingHandlerResult;
133         if (status == TransactionStatusEnum.OPEN) {
134             log.debug(LogMessages.PRE_INVOKE_ACTION, transactionId, dbType.name(), userId, actionType);
135             Either<RollbackHandler, MethodActivationStatusEnum> eitherRollbackHandler = rollbackManager.getRollbackHandler(dbType);
136
137             if (eitherRollbackHandler.isLeft()) {
138                 RollbackHandler rollbackHandler = eitherRollbackHandler.left().value();
139                 addingHandlerResult = rollbackHandler.addRollbackAction(dbRollbackAction);
140             } else {
141                 addingHandlerResult = addToNewRollbackHandler(dbType, dbRollbackAction);
142             }
143
144             if (addingHandlerResult == MethodActivationStatusEnum.SUCCESS) {
145                 result = invokeAction(isLastAction, dbAction, dbType);
146             } else {
147                 result = Either.right(TransactionCodeEnum.PREPARE_ROLLBACK_FAILED);
148             }
149         } else {
150             result = handleActionOnClosedTransaction();
151         }
152         updateTransactionStatus(result);
153         return result;
154     }
155
156     private MethodActivationStatusEnum addToNewRollbackHandler(DBTypeEnum dbType, IDBAction dbRollbackAction) {
157         log.debug(LogMessages.CREATE_ROLLBACK_HANDLER, dbType.name(), transactionId, userId, actionType);
158         MethodActivationStatusEnum result;
159
160         Either<RollbackHandler, MethodActivationStatusEnum> eitherRollbackHandler = rollbackManager.createRollbackHandler(dbType);
161         if (eitherRollbackHandler.isRight()) {
162             result = eitherRollbackHandler.right().value();
163             BeEcompErrorManager.getInstance().logBeSystemError("TransactionManager -  addToNewRollbackHandler");
164             log.info(LogMessages.FAILED_CREATE_ROLLBACK, dbType.name(), transactionId, userId, actionType);
165             log.debug(TransactionUtils.TRANSACTION_MARKER, LogMessages.FAILED_CREATE_ROLLBACK, dbType.name(), transactionId, userId, actionType);
166         } else {
167             RollbackHandler rollbackHandler = eitherRollbackHandler.left().value();
168             rollbackHandler.addRollbackAction(dbRollbackAction);
169             result = MethodActivationStatusEnum.SUCCESS;
170         }
171
172         return result;
173     }
174
175     public Either<DBActionCodeEnum, TransactionCodeEnum> invokeESAction(boolean isLastAction, ESActionTypeEnum esActiontype, ESArtifactData artifactData) {
176
177         Either<DBActionCodeEnum, TransactionCodeEnum> result;
178         if (status == TransactionStatusEnum.OPEN) {
179             Either<RollbackHandler, MethodActivationStatusEnum> eitherEsHandler = rollbackManager.getRollbackHandler(DBTypeEnum.ELASTIC_SEARCH);
180             if (eitherEsHandler.isRight()) {
181                 result = Either.right(TransactionCodeEnum.INTERNAL_ERROR);
182             } else {
183                 ESRollbackHandler esHandler = (ESRollbackHandler) eitherEsHandler.left().value();
184
185                 Either<ESAction, MethodActivationStatusEnum> eitherEsRollbackAction = esHandler.buildEsRollbackAction(esCatalogDao, artifactData, esActiontype);
186                 if (eitherEsRollbackAction.isLeft()) {
187                     esHandler.addRollbackAction(eitherEsRollbackAction.left().value());
188                     result = invokeAction(isLastAction, new ESAction(esCatalogDao, artifactData, esActiontype), DBTypeEnum.ELASTIC_SEARCH);
189                 } else {
190                     result = Either.right(TransactionCodeEnum.PREPARE_ROLLBACK_FAILED);
191                 }
192
193             }
194         } else {
195             result = handleActionOnClosedTransaction();
196         }
197         updateTransactionStatus(result);
198         return result;
199     }
200
201     private <T> void updateTransactionStatus(Either<T, TransactionCodeEnum> result) {
202         if (result.isRight()) {
203             updateTransactionStatus(result.right().value());
204         }
205
206     }
207
208     private <T> Either<T, TransactionCodeEnum> handleActionOnClosedTransaction() {
209         Either<T, TransactionCodeEnum> result = Either.right(TransactionCodeEnum.TRANSACTION_CLOSED);
210         log.debug(LogMessages.ACTION_ON_CLOSED_TRANSACTION, transactionId, userId, actionType);
211         log.info(TransactionUtils.TRANSACTION_MARKER, LogMessages.ACTION_ON_CLOSED_TRANSACTION, transactionId, userId, actionType);
212         return result;
213     }
214
215     private <T> Either<T, DBActionCodeEnum> getLastActionResult(IDBAction dataBaseAction, DBTypeEnum dbType) {
216         Either<T, DBActionCodeEnum> result;
217         if (isLastActionAlreadyCalled()) {
218             result = Either.right(DBActionCodeEnum.FAIL_MULTIPLE_LAST_ACTION);
219             BeEcompErrorManager.getInstance().logBeSystemError("TransactionManager - getLastActionResult");
220             log.debug(LogMessages.DOUBLE_FINISH_FLAG_ACTION, transactionId, dbType.name(), userId, actionType);
221             log.info(TransactionUtils.TRANSACTION_MARKER, LogMessages.DOUBLE_FINISH_FLAG_ACTION, transactionId, dbType.name(), userId, actionType);
222         } else {
223             setLastActionAlreadyCalled(true);
224             result = getActionResult(dataBaseAction, dbType);
225         }
226         return result;
227     }
228
229     private <T> Either<T, DBActionCodeEnum> getActionResult(IDBAction dataBaseAction, DBTypeEnum dbType) {
230         Either<T, DBActionCodeEnum> result;
231         try {
232             T doAction = dataBaseAction.doAction();
233             result = Either.left(doAction);
234         } catch (Exception e) {
235             BeEcompErrorManager.getInstance().logBeSystemError("TransactionManager - getActionResult");
236             log.debug(LogMessages.DB_ACTION_FAILED_WITH_EXCEPTION, dbType.name(), transactionId, e.getMessage(), userId, actionType, e);
237             log.info(TransactionUtils.TRANSACTION_MARKER, LogMessages.DB_ACTION_FAILED_WITH_EXCEPTION, dbType.name(), transactionId, e.getMessage(), userId, actionType);
238
239             result = Either.right(DBActionCodeEnum.FAIL_GENERAL);
240         }
241         return result;
242     }
243
244     public TransactionCodeEnum finishTransaction() {
245         TransactionCodeEnum result;
246         if (status == TransactionStatusEnum.OPEN) {
247             DBActionCodeEnum transactionCommit = commitManager.transactionCommit();
248             if (transactionCommit == DBActionCodeEnum.SUCCESS) {
249                 result = TransactionCodeEnum.SUCCESS;
250                 status = TransactionStatusEnum.CLOSED;
251             } else {
252                 result = transactionRollback();
253             }
254         } else {
255             BeEcompErrorManager.getInstance().logBeSystemError("TransactionManager - finishTransaction");
256             log.debug(LogMessages.COMMIT_ON_CLOSED_TRANSACTION, transactionId, status.name(), userId, actionType);
257             log.info(TransactionUtils.TRANSACTION_MARKER, LogMessages.COMMIT_ON_CLOSED_TRANSACTION, transactionId, status.name(), userId, actionType);
258             result = TransactionCodeEnum.TRANSACTION_CLOSED;
259         }
260         updateTransactionStatus(result);
261         return result;
262     }
263
264     private void updateTransactionStatus(TransactionCodeEnum result) {
265         switch (result) {
266         case SUCCESS:
267             status = TransactionStatusEnum.CLOSED;
268             break;
269         case ROLLBACK_SUCCESS:
270             status = TransactionStatusEnum.CLOSED;
271             break;
272         case ROLLBACK_FAILED:
273             status = TransactionStatusEnum.FAILED_ROLLBACK;
274             break;
275         default:
276             break;
277         }
278
279     }
280
281     private boolean isLastActionAlreadyCalled() {
282         return lastActionAlreadyCalled;
283     }
284
285     private void setLastActionAlreadyCalled(boolean lastAction) {
286         this.lastActionAlreadyCalled = lastAction;
287     }
288
289     // TODO test using slf4j-test and remove this
290     static void setLog(Logger log) {
291         TransactionSdncImpl.log = log;
292     }
293
294     TransactionStatusEnum getStatus() {
295         return status;
296     }
297 }