Ravi Nori has uploaded a new change for review. Change subject: engine : command infrastructure should know when the "execute" phase finished ......................................................................
engine : command infrastructure should know when the "execute" phase finished When the engine is started after crashing/stopped while a command with async tasks is running, we should know after the restart whether the "Execution" phase of the command has ended or not, so that we'll know whether the command can be recovered or not. Change-Id: Ie36e7d8a0263d5dd90fabe914a76711d5c001e72 Bug-Url: https://bugzilla.redhat.com/1118249 Signed-off-by: Ravi Nori <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CommandBase.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandCoordinatorImpl.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandExecutor.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCache.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCacheImpl.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/TaskManagerUtil.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/interfaces/CommandCRUDOperations.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/CommandBaseTest.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CommandEntity.java A backend/manager/modules/compat/src/main/java/org/ovirt/engine/core/compat/backendcompat/CommandExecutionStatus.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDao.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDaoDbFacadeImpl.java M packaging/dbscripts/command_entities_sp.sql A packaging/dbscripts/upgrade/03_05_0790_add_executed_to_command_entities.sql 14 files changed, 108 insertions(+), 17 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/94/30694/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CommandBase.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CommandBase.java index 6351d8d..13953ad 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CommandBase.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CommandBase.java @@ -1150,6 +1150,7 @@ } finally { // If we failed to execute due to exception or some other reason, we compensate for the failure. if (exceptionOccurred || !getSucceeded()) { + setCommandStatus(CommandStatus.FAILED); setSucceeded(false); compensate(); } else { @@ -1277,6 +1278,7 @@ // Transaction was aborted - we must sure we compensation for all previous applicative stages of the command compensate(); } finally { + setCommandExecuted(); try { if (getCommandShouldBeLogged()) { logRenamedEntity(); @@ -2129,7 +2131,9 @@ getReturnValue()), cmdContext); } finally { - TransactionSupport.resume(transaction); + if (transaction != null) { + TransactionSupport.resume(transaction); + } } } @@ -2138,7 +2142,9 @@ try { TaskManagerUtil.removeCommand(getCommandId()); } finally { - TransactionSupport.resume(transaction); + if (transaction != null) { + TransactionSupport.resume(transaction); + } } } @@ -2153,6 +2159,19 @@ try { TaskManagerUtil.updateCommandStatus(getCommandId(), getTaskType(), commandStatus); } finally { + if (transaction != null) { + TransactionSupport.resume(transaction); + } + } + } + } + + public void setCommandExecuted() { + Transaction transaction = TransactionSupport.suspend(); + try { + TaskManagerUtil.updateCommandExecuted(getCommandId()); + } finally { + if (transaction != null) { TransactionSupport.resume(transaction); } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandCoordinatorImpl.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandCoordinatorImpl.java index a15137a..0227183 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandCoordinatorImpl.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandCoordinatorImpl.java @@ -68,6 +68,11 @@ @Override public void persistCommand(CommandEntity cmdEntity) { + CommandEntity existingCmdEntity = commandsCache.get(cmdEntity.getId()); + if (existingCmdEntity != null) { + cmdEntity.setExecuted(existingCmdEntity.isExecuted()); + cmdEntity.setCallBackNotified(existingCmdEntity.isCallBackNotified()); + } commandsCache.put(cmdEntity); if (cmdEntity.isCallBackEnabled()) { buildCmdHierarchy(cmdEntity); @@ -173,6 +178,10 @@ commandsCache.updateCommandStatus(commandId, taskType, status); } + public void updateCommandExecuted(Guid commandId) { + commandsCache.updateCommandExecuted(commandId); + } + public void updateCallBackNotified(final Guid commandId) { commandsCache.updateCallBackNotified(commandId); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandExecutor.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandExecutor.java index b6d2b4e..8721a1e 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandExecutor.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandExecutor.java @@ -74,7 +74,9 @@ break; case ACTIVE: case ACTIVE_ASYNC: - callBack.doPolling(cmdId, coco.getChildCommandIds(cmdId)); + if (coco.getCommandEntity(cmdId).isExecuted()) { + callBack.doPolling(cmdId, coco.getChildCommandIds(cmdId)); + } break; default: break; @@ -85,16 +87,10 @@ private void initCommandExecutor() { if (!cmdExecutorInitialized) { for (CommandEntity cmdEntity : coco.getCommandsWithCallBackEnabled()) { - switch(cmdEntity.getCommandStatus()) { - case ACTIVE_SYNC: - case NOT_STARTED: - coco.retrieveCommand(cmdEntity.getId()).setCommandStatus(CommandStatus.FAILED_RESTARTED); - break; - default: - if (!cmdEntity.isCallBackNotified()) { - addToCallBackMap(cmdEntity); - } - break; + if (!cmdEntity.isExecuted()) { + coco.retrieveCommand(cmdEntity.getId()).setCommandStatus(CommandStatus.FAILED_RESTARTED); + } else if (!cmdEntity.isCallBackNotified()) { + addToCallBackMap(cmdEntity); } } cmdExecutorInitialized = true; diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCache.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCache.java index 4e63442..cc54a2a 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCache.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCache.java @@ -22,6 +22,8 @@ public void updateCommandStatus(Guid commandId, AsyncTaskType taskType, CommandStatus status); + public void updateCommandExecuted(Guid commandId); + public void updateCallBackNotified(Guid commandId); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCacheImpl.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCacheImpl.java index 5d470d9..50043bb 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCacheImpl.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/CommandsCacheImpl.java @@ -74,6 +74,13 @@ } } + public void updateCommandExecuted(final Guid commandId) { + CommandEntity cmdEntity = get(commandId); + if (cmdEntity != null) { + cmdEntity.setExecuted(true); + DbFacade.getInstance().getCommandEntityDao().updateExecuted(commandId); + } + } public void updateCallBackNotified(final Guid commandId) { CommandEntity cmdEntity = get(commandId); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/TaskManagerUtil.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/TaskManagerUtil.java index 44e8d17..bf33989 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/TaskManagerUtil.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/TaskManagerUtil.java @@ -21,6 +21,7 @@ import org.ovirt.engine.core.compat.CommandStatus; import org.ovirt.engine.core.compat.DateTime; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.compat.backendcompat.CommandExecutionStatus; public class TaskManagerUtil { @@ -163,6 +164,16 @@ coco.updateCommandStatus(commandId, taskType, status); } + public static CommandExecutionStatus getCommandExecutionStatus(Guid commandId) { + CommandEntity cmdEntity = coco.getCommandEntity(commandId); + return cmdEntity == null ? CommandExecutionStatus.UNKNOWN : + cmdEntity.isExecuted() ? CommandExecutionStatus.EXECUTED : CommandExecutionStatus.NOT_EXECUTED; + } + + public static void updateCommandExecuted(Guid commandId) { + coco.updateCommandExecuted(commandId); + } + public static Future<VdcReturnValueBase> executeAsyncCommand(VdcActionType actionType, VdcActionParametersBase parameters, CommandContext cmdContext) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/interfaces/CommandCRUDOperations.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/interfaces/CommandCRUDOperations.java index de8da30..70f98af 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/interfaces/CommandCRUDOperations.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/tasks/interfaces/CommandCRUDOperations.java @@ -22,5 +22,6 @@ public void removeAllCommandsInHierarchy(Guid commandId); public void removeAllCommandsBeforeDate(DateTime cutoff); public void updateCommandStatus(Guid commandId, AsyncTaskType taskType, CommandStatus status); + public void updateCommandExecuted(Guid commandId); public void updateCallBackNotified(Guid commandId); } diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/CommandBaseTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/CommandBaseTest.java index f3c310b..a6efd3d 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/CommandBaseTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/CommandBaseTest.java @@ -86,6 +86,10 @@ @Override public void setCommandStatus(CommandStatus status) { } + + @Override + public void setCommandExecuted() { + } } @Before diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CommandEntity.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CommandEntity.java index c1ea5bc..0f22808 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CommandEntity.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CommandEntity.java @@ -23,6 +23,7 @@ private CommandStatus commandStatus = CommandStatus.UNKNOWN; private boolean callBackEnabled = false; private boolean callBackNotified = false; + private boolean executed = false; @Override public int hashCode() { @@ -161,4 +162,12 @@ public void setStepId(Guid stepId) { this.stepId = stepId; } + + public boolean isExecuted() { + return executed; + } + + public void setExecuted(boolean executed) { + this.executed = executed; + } } diff --git a/backend/manager/modules/compat/src/main/java/org/ovirt/engine/core/compat/backendcompat/CommandExecutionStatus.java b/backend/manager/modules/compat/src/main/java/org/ovirt/engine/core/compat/backendcompat/CommandExecutionStatus.java new file mode 100644 index 0000000..4fe3d8f --- /dev/null +++ b/backend/manager/modules/compat/src/main/java/org/ovirt/engine/core/compat/backendcompat/CommandExecutionStatus.java @@ -0,0 +1,7 @@ +package org.ovirt.engine.core.compat.backendcompat; + +public enum CommandExecutionStatus { + UNKNOWN, // the CommandEntity for the commands is not in database + EXECUTED, // the command's execute method completed execution + NOT_EXECUTED; // the command's execute method did not complete execution +} diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDao.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDao.java index 6f9d2f2..e0efee8 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDao.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDao.java @@ -12,6 +12,8 @@ void updateStatus(Guid command, CommandStatus status); + void updateExecuted(Guid id); + void updateNotified(Guid id); void removeAllBeforeDate(Date cutoff); diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDaoDbFacadeImpl.java index 44a7430..ea081f1 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/CommandEntityDaoDbFacadeImpl.java @@ -34,6 +34,7 @@ result.setActionParameters(deserializeParameters(resultSet.getString("action_parameters"), resultSet.getString("action_parameters_class"))); result.setReturnValue(deserializeReturnValue(resultSet.getString("return_value"), resultSet.getString("return_value_class"))); result.setCommandStatus(getCommandStatus(resultSet.getString("status"))); + result.setExecuted(resultSet.getBoolean("executed")); result.setCallBackEnabled(resultSet.getBoolean("callback_enabled")); result.setCallBackNotified(resultSet.getBoolean("callback_notified")); return result; @@ -63,6 +64,7 @@ .addValue("action_parameters", serializeParameters(entity.getActionParameters())) .addValue("action_parameters_class", entity.getActionParameters() == null ? null : entity.getActionParameters().getClass().getName()) .addValue("status", entity.getCommandStatus().toString()) + .addValue("executed", entity.isExecuted()) .addValue("callback_enabled", entity.isCallBackEnabled()) .addValue("return_value", serializeReturnValue(entity.getReturnValue())) .addValue("return_value_class", entity.getReturnValue() == null ? null : entity.getReturnValue().getClass().getName()); @@ -123,6 +125,11 @@ } @Override + public void updateExecuted(Guid id) { + getCallsHandler().executeModification("UpdateCommandEntityExecuted", createIdParameterMapper(id).addValue("executed", true)); + } + + @Override public void removeAllBeforeDate(Date cutoff) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("date", cutoff); diff --git a/packaging/dbscripts/command_entities_sp.sql b/packaging/dbscripts/command_entities_sp.sql index 1c8fc78..e3cbfa1 100644 --- a/packaging/dbscripts/command_entities_sp.sql +++ b/packaging/dbscripts/command_entities_sp.sql @@ -6,14 +6,15 @@ v_action_parameters text, v_action_parameters_class varchar(256), v_status varchar(20), + v_executed boolean, v_callback_enabled boolean, v_return_value text, v_return_value_class varchar(256)) RETURNS VOID AS $procedure$ BEGIN - INSERT INTO command_entities(command_id, command_type, root_command_id, job_id, step_id, action_parameters, action_parameters_class, created_at, status, callback_enabled, return_value, return_value_class) - VALUES(v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, NOW(), v_status, v_callback_enabled, v_return_value, v_return_value_class); + INSERT INTO command_entities(command_id, command_type, root_command_id, job_id, step_id, action_parameters, action_parameters_class, created_at, status, executed, callback_enabled, return_value, return_value_class) + VALUES(v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, NOW(), v_status, v_executed, v_callback_enabled, v_return_value, v_return_value_class); END; $procedure$ LANGUAGE plpgsql; @@ -26,6 +27,7 @@ v_action_parameters text, v_action_parameters_class varchar(256), v_status varchar(20), + v_executed boolean, v_callback_enabled boolean, v_return_value text, v_return_value_class varchar(256)) @@ -40,6 +42,7 @@ action_parameters = v_action_parameters, action_parameters_class = v_action_parameters_class, status = v_status, + executed = v_executed, callback_enabled = v_callback_enabled, return_value = v_return_value, return_value_class = v_return_value_class @@ -55,6 +58,18 @@ BEGIN UPDATE command_entities SET status = v_status + WHERE command_id = v_command_id; +END; $procedure$ +LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION UpdateCommandEntityExecuted(v_command_id uuid, + v_executed boolean) +RETURNS VOID + AS $procedure$ +BEGIN + UPDATE command_entities + SET executed = v_executed WHERE command_id = v_command_id; END; $procedure$ LANGUAGE plpgsql; @@ -80,6 +95,7 @@ v_action_parameters text, v_action_parameters_class varchar(256), v_status varchar(20), + v_executed boolean, v_callback_enabled boolean, v_return_value text, v_return_value_class varchar(256)) @@ -87,9 +103,9 @@ AS $procedure$ BEGIN IF NOT EXISTS (SELECT 1 from command_entities where command_id = v_command_id) THEN - PERFORM InsertCommandEntity (v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, v_status, v_callback_enabled, v_return_value, v_return_value_class); + PERFORM InsertCommandEntity (v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, v_status, v_executed, v_callback_enabled, v_return_value, v_return_value_class); ELSE - PERFORM UpdateCommandEntity (v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, v_status, v_callback_enabled, v_return_value, v_return_value_class); + PERFORM UpdateCommandEntity (v_command_id, v_command_type, v_root_command_id, v_job_id, v_step_id, v_action_parameters, v_action_parameters_class, v_status, v_executed, v_callback_enabled, v_return_value, v_return_value_class); END IF; END; $procedure$ LANGUAGE plpgsql; diff --git a/packaging/dbscripts/upgrade/03_05_0790_add_executed_to_command_entities.sql b/packaging/dbscripts/upgrade/03_05_0790_add_executed_to_command_entities.sql new file mode 100644 index 0000000..ecd689e --- /dev/null +++ b/packaging/dbscripts/upgrade/03_05_0790_add_executed_to_command_entities.sql @@ -0,0 +1 @@ +select fn_db_add_column('command_entities', 'executed', 'boolean default false'); -- To view, visit http://gerrit.ovirt.org/30694 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie36e7d8a0263d5dd90fabe914a76711d5c001e72 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Ravi Nori <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
