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

Reply via email to