Yair Zaslavsky has uploaded a new change for review.

Change subject: [WIP] core: Prevent dead lock on vm device (#852451)
......................................................................

[WIP] core: Prevent dead lock on vm device (#852451)

https://bugzilla.redhat.com/852451

This patch is initial draft as it presents some ideas, and
should be tested more!

The following patch solved a dead lock on vm device:
Both VdsUpdateRuntimeInfo and HotPlugDisk update a collection of VmDevices.
The devices are un oredered, so a dead lock may occur.

This patch solves the issue the following way:
a. Presents ascending ordering of vm devices (both at stored procedure and
at code , where needed)
b. Changes HotplugDisk to perform update for both plugged flag and boot order
in the same area of code
c. Changes hotplugDisk to update only boot order and plugged fields of vm device
d. Changes VdsUpdateRuntime info to update only the alias and address fields

c and d are performed in order to avoid data races between the two concurrent 
flows

We have discussed about using an optimistic lock mechanism at first, but using 
c and d ,
lets us have a KISS apporach to the solution

Change-Id: If316259f9760777c5f85db0880a157021c61a6ba
Signed-off-by: Yair Zaslavsky <yzasl...@redhat.com>
---
M backend/manager/dbscripts/vm_device_sp.sql
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsDao.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsGenericDaoDbFacade.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAO.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAODbFacadeImpl.java
M 
backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmDeviceDAOTest.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
12 files changed, 225 insertions(+), 33 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/41/7641/1

diff --git a/backend/manager/dbscripts/vm_device_sp.sql 
b/backend/manager/dbscripts/vm_device_sp.sql
index 594582b..0cfaf90 100644
--- a/backend/manager/dbscripts/vm_device_sp.sql
+++ b/backend/manager/dbscripts/vm_device_sp.sql
@@ -74,6 +74,43 @@
 END; $procedure$
 LANGUAGE plpgsql;
 
+Create or replace FUNCTION UpdateVmDeviceRuntimeInfo(
+    v_device_id UUID,
+    v_vm_id UUID,
+    v_address varchar(255),
+    v_alias varchar(255))
+RETURNS VOID
+AS $procedure$
+BEGIN
+    UPDATE vm_device
+    SET
+           address = v_address,
+           alias = v_alias,
+           _update_date = current_timestamp
+    WHERE  device_id = v_device_id and vm_id = v_vm_id;
+END; $procedure$
+LANGUAGE plpgsql;
+
+
+Create or replace FUNCTION UpdateVmDeviceForHotPlugDisk(
+    v_device_id UUID,
+    v_vm_id UUID,
+    v_boot_order int,
+    v_is_plugged boolean)
+RETURNS VOID
+AS $procedure$
+BEGIN
+    UPDATE vm_device
+    SET
+           boot_order = v_boot_order,
+           is_plugged = v_is_plugged,
+           _update_date = current_timestamp
+    WHERE  device_id = v_device_id and vm_id = v_vm_id;
+END; $procedure$
+LANGUAGE plpgsql;
+
+
+
 Create or replace FUNCTION DeleteVmDevice(v_device_id UUID, v_vm_id UUID)
 RETURNS VOID
 AS $procedure$
@@ -113,7 +150,7 @@
     RETURN QUERY
     SELECT *
     FROM   vm_device_view
-    WHERE  vm_id = v_vm_id;
+    WHERE  vm_id = v_vm_id order by device_id;
 END; $procedure$
 LANGUAGE plpgsql;
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
index 2548377..0938efd 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
@@ -129,7 +129,7 @@
     }
 
     protected void updateBootOrderInVmDevice() {
-        VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData());
+        
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
     }
 
     private void updateDiskVmSnapshotId() {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
index 7a527c8..07f80ea 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
@@ -77,7 +77,7 @@
         // update cached image
         VmHandler.updateDisksFromDb(getVm());
         // update vm device boot order
-        VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData());
+        
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
         setSucceeded(true);
     }
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
index 64cf251..63fc7c9 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
@@ -1,5 +1,7 @@
 package org.ovirt.engine.core.bll;
 
+import java.util.List;
+
 import org.ovirt.engine.core.bll.utils.VmDeviceUtils;
 import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.action.HotPlugDiskToVmParameters;
@@ -68,15 +70,22 @@
         if (getVm().getstatus() == VMStatus.Up) {
             performPlugCommnad(getPlugAction(), disk, oldVmDevice);
         }
-        oldVmDevice.setIsPlugged(!oldVmDevice.getIsPlugged());
+
+        //Update boot order and
+        final List<VmDevice> devices = 
VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData());
+        for (VmDevice device:devices) {
+            if (device.getDeviceId().equals(oldVmDevice.getDeviceId())) {
+                device.setIsPlugged(!oldVmDevice.getIsPlugged());
+                break;
+            }
+        }
+
         TransactionSupport.executeInNewTransaction(new 
TransactionMethod<Void>() {
             @Override
             public Void runInTransaction() {
-                getVmDeviceDao().update(oldVmDevice);
-                // update cached image
+
+                
getVmDeviceDao().updateAll("UpdateVmDeviceForHotPlugDisk",devices);
                 VmHandler.updateDisksFromDb(getVm());
-                // update vm device boot order
-                
VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData());
                 return null;
             }
         });
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
index 74de729..906a1fd 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
@@ -242,7 +242,7 @@
                 // update cached image
                 VmHandler.updateDisksFromDb(getVm());
                 // update vm device boot order
-                
VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData());
+                
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
 
                 setSucceeded(UpdateVmInSpm(getVm().getstorage_pool_id(),
                         Arrays.asList(getVm())));
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
index b491421..d26d165 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
@@ -44,7 +44,6 @@
     private final static int SLOTS_PER_CONTROLLER = 6;
     private final static int COMPANION_USB_CONTROLLERS = 3;
 
-
     /**
      * Update the vm devices according to changes made in vm static for 
existing VM
      */
@@ -54,7 +53,7 @@
             updateCdInVmDevice(oldVmBase, entity);
             if (oldVmBase.getdefault_boot_sequence() != entity
                     .getdefault_boot_sequence()) {
-                updateBootOrderInVmDevice(entity);
+                updateBootOrderInVmDeviceAndStoreToDB(entity);
             }
 
             // if the console type has changed, recreate Video devices
@@ -98,7 +97,7 @@
     public static <T extends VmBase> void updateVmDevices(T entity, Guid 
newId) {
         if (entity != null) {
             updateCdInVmDevice(entity);
-            updateBootOrderInVmDevice(entity);
+            updateBootOrderInVmDeviceAndStoreToDB(entity);
             updateNumOfMonitorsInVmDevice(null, entity);
             updateUSBSlots(null, entity);
             updateMemoryBalloon(null, entity, true);
@@ -190,7 +189,7 @@
 
         if (isVm) {
             //  update devices boot order
-            updateBootOrderInVmDevice(vmBase);
+            updateBootOrderInVmDeviceAndStoreToDB(vmBase);
 
             // create sound card for a desktop VM if not exists
             if (vmBase.getvm_type() == VmType.Desktop) {
@@ -277,7 +276,7 @@
         if (type.equals(VmDeviceType.DISK) || 
type.equals(VmDeviceType.INTERFACE )) {
             // recalculate boot sequence
             VmBase vmBase = 
DbFacade.getInstance().getVmStaticDAO().get(id.getVmId());
-            updateBootOrderInVmDevice(vmBase);
+            updateBootOrderInVmDeviceAndStoreToDB(vmBase);
         }
         return managedDevice;
     }
@@ -314,10 +313,24 @@
 
     /**
      * Updates VM boot order in vm device according to the BootSequence enum 
value.
+     * Stores the updated devices in DB
      * @param vmBase
      */
-    public static void updateBootOrderInVmDevice(VmBase vmBase) {
+    public static void updateBootOrderInVmDeviceAndStoreToDB(VmBase vmBase) {
+        List<VmDevice> devices = updateBootOrderInVmDevice(vmBase);
+        for (VmDevice device : devices) {
+           dao.update(device);
+        }
+    }
+
+    /**
+     * Updates boot order in vm device according to the BootSequence enum 
value.
+     * @param vmBase
+     * @return the updated VmDevice list
+     */
+    public static List<VmDevice> updateBootOrderInVmDevice(VmBase vmBase) {
         if (vmBase instanceof VmStatic) {
+            //Returns the devices sorted in ascending manner
             List<VmDevice> devices = dao.getVmDeviceByVmId(vmBase.getId());
             // reset current boot order
             for (VmDevice device: devices) {
@@ -327,11 +340,9 @@
             VmHandler.updateDisksForVm(vm, 
DbFacade.getInstance().getDiskDao().getAllForVm(vm.getId()));
             boolean isOldCluster = 
VmDeviceCommonUtils.isOldClusterVersion(vm.getvds_group_compatibility_version());
             VmDeviceCommonUtils.updateVmDevicesBootOrder(vm, devices, 
isOldCluster);
-            // update boot order in vm device
-            for (VmDevice device : devices) {
-                dao.update(device);
-            }
+            return devices;
         }
+        return Collections.emptyList();
     }
 
     /**
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsDao.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsDao.java
index 3825d3b..79359da 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsDao.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsDao.java
@@ -14,10 +14,19 @@
 
     /**
      * Updates the given entities using a more efficient method to update all 
of them at once, rather than each at a
-     * time.
+     * time. The procedure name to be used is "UpdateEntityName> where 
EntityName stands for the name of the entity
      *
      * @param entities
      *            The entities to update.
      */
     void updateAll(Collection<T> entities);
+
+
+    /**
+     * Updates the given entities using a more efficient method to update all 
of them at once, rather than each at a
+     * time.
+     * @param procedureName procedure name for update
+     * @param entities
+     */
+    void updateAll(String procedureName, Collection<T> entities);
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsGenericDaoDbFacade.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsGenericDaoDbFacade.java
index 197c361..14feafb 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsGenericDaoDbFacade.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/MassOperationsGenericDaoDbFacade.java
@@ -24,9 +24,21 @@
 
     @Override
     public void updateAll(Collection<T> entities) {
+        updateAll(getProcedureNameForUpdate(),entities);
         for (T entity : entities) {
             getCallsHandler().executeModification(getProcedureNameForUpdate(),
                     createFullParametersMapper(entity));
         }
     }
+
+    @Override
+    public void updateAll(String procedureName, Collection<T> entities) {
+        if (procedureName == null) {
+            procedureName = getProcedureNameForUpdate();
+        }
+        for (T entity : entities) {
+            getCallsHandler().executeModification(procedureName,
+                    createFullParametersMapper(entity));
+        }
+    }
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAO.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAO.java
index 36963e0..e056b28 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAO.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAO.java
@@ -41,4 +41,19 @@
      * @param device
      */
     void clearDeviceAddress(Guid deviceId);
+
+    /**
+     * Runs an update for the device according to fields that were updated 
during
+     * VdsUpdateRuntimeInfo periodic call
+     * @param vmDevice
+     */
+    void updateRuntimeInfo(VmDevice vmDevice);
+
+    /**
+     * Runs an update for the device according to fields that were updated 
during
+     * HotPlugDisk
+     * @param vmDevice
+     */
+    void updateHotPlugDisk(VmDevice vmDevice);
+
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAODbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAODbFacadeImpl.java
index b84488a..d325adf 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAODbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDeviceDAODbFacadeImpl.java
@@ -175,4 +175,31 @@
         getCallsHandler().executeModification("clearVmDeviceAddress", 
parameterSource);
 
     }
+
+    @Override
+    public void updateRuntimeInfo(VmDevice vmDevice) {
+        MapSqlParameterSource paramsForUpdate = 
createParameterSourceForUpdate(vmDevice)
+                .addValue("address", vmDevice.getAddress())
+                .addValue("alias",vmDevice.getAlias());
+
+        getCallsHandler().executeModification("UpdateVmDeviceRuntimeInfo", 
paramsForUpdate);
+    }
+
+    private MapSqlParameterSource createParameterSourceForUpdate(VmDevice 
vmDevice) {
+        MapSqlParameterSource parameterSource = 
getCustomMapSqlParameterSource()
+                .addValue("vm_id", vmDevice.getVmId())
+                .addValue("device_id",vmDevice.getDeviceId());
+        return parameterSource;
+    }
+
+
+    @Override
+    public void updateHotPlugDisk(VmDevice vmDevice) {
+        MapSqlParameterSource paramsForUpdate = 
createParameterSourceForUpdate(vmDevice)
+            .addValue("boot_order",vmDevice.getBootOrder())
+            .addValue("is_plugged",vmDevice.getIsPlugged());
+        getCallsHandler().executeModification("UpdateVmDeviceForHotPlugDisk" , 
paramsForUpdate);
+
+    }
+
 }
diff --git 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmDeviceDAOTest.java
 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmDeviceDAOTest.java
index a203aca..f7763de 100644
--- 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmDeviceDAOTest.java
+++ 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmDeviceDAOTest.java
@@ -146,4 +146,33 @@
         
Assert.assertTrue(StringUtils.isBlank(dao.get(getExistingEntityId()).getAddress()));
 
     }
+
+    @Test
+    public void testUpdateDeviceRuntimeInfo() {
+        VmDevice vmDevice = dao.get(getExistingEntityId());
+        Assert.assertTrue(StringUtils.isNotBlank(vmDevice.getAddress()));
+        String newAddressValue = "newaddr";
+        vmDevice.setAddress(newAddressValue);
+        String newAlias = "newalias";
+        vmDevice.setAlias(newAlias);
+        dao.updateRuntimeInfo(vmDevice);
+        dao.get(getExistingEntityId());
+        assertEquals(vmDevice.getAddress(), newAddressValue);
+        assertEquals(vmDevice.getAlias(), newAlias);
+    }
+
+    @Test
+    public void testUpdateHotPlugDisk() {
+        VmDevice vmDevice = dao.get(getExistingEntityId());
+        boolean newPluggedValue = !vmDevice.getIsPlugged();
+        int newBootOrderValue = vmDevice.getBootOrder() + 1;
+        Assert.assertTrue(StringUtils.isNotBlank(vmDevice.getAddress()));
+        vmDevice.setBootOrder(newBootOrderValue);
+        vmDevice.setIsPlugged(newPluggedValue);
+        dao.updateHotPlugDisk(vmDevice);
+        dao.get(getExistingEntityId());
+        assertEquals(vmDevice.getIsPlugged(), newPluggedValue);
+        assertEquals(vmDevice.getBootOrder(),newBootOrderValue);
+    }
+
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
index b1a4f92..6371236 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
@@ -3,6 +3,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -56,6 +57,7 @@
 import org.ovirt.engine.core.utils.NetworkUtils;
 import org.ovirt.engine.core.utils.ObjectIdentityChecker;
 import org.ovirt.engine.core.utils.Pair;
+import org.ovirt.engine.core.utils.comparator.NGuidComparator;
 import org.ovirt.engine.core.utils.log.Log;
 import org.ovirt.engine.core.utils.log.LogFactory;
 import org.ovirt.engine.core.utils.transaction.TransactionMethod;
@@ -108,6 +110,20 @@
     private static Map<Guid, Long> hostDownTimes = new HashMap<Guid, Long>();
     private int runningVmsInTransition = 0;
 
+    private static final Comparator<VmDevice> vmDeviceComparator = new 
Comparator<VmDevice>() {
+
+        @Override
+        public int compare(VmDevice o1, VmDevice o2) {
+            //As primary key at db for Vm device is defined both using
+            //vm device Id and vm Id, these two values are used for comparison
+            NGuidComparator comparator = new NGuidComparator();
+            int vmIdComparison = comparator.compare(o1.getVmId(),o2.getVmId());
+            return (vmIdComparison == 0)?0:
+                comparator.compare(o1.getDeviceId(), o2.getDeviceId());
+        }
+    };
+
+
     public VM GetVmFromDictionary(Guid id) {
         VM vm = null;
         vm = _vmDict.get(id);
@@ -156,9 +172,16 @@
         saveVmDevicesToDb();
     }
 
-    private void saveVmDevicesToDb() {
+    private void sortVmDeviceList(List<VmDevice> vmDevices) {
+        Collections.sort(vmDevices,vmDeviceComparator);
+    }
 
-        updateAllInTransaction(vmDeviceToSave.values(), 
getDbFacade().getVmDeviceDAO());
+    private void saveVmDevicesToDb() {
+        //Sort VM devices in ascending order
+        List<VmDevice> sortedVmDevices = new ArrayList<VmDevice>();
+        sortedVmDevices.addAll(vmDeviceToSave.values());
+        sortVmDeviceList(sortedVmDevices);
+        updateAllInTransaction(sortedVmDevices, 
getDbFacade().getVmDeviceDAO());
 
         if (!removedDeviceIds.isEmpty()) {
             TransactionSupport.executeInScope(TransactionScopeOption.Required,
@@ -197,20 +220,40 @@
      */
     private static <T extends BusinessEntity<?>> void updateAllInTransaction
             (final Collection<T> entities, final MassOperationsDao<T> dao) {
-        if (!entities.isEmpty()) {
-            TransactionSupport.executeInScope(TransactionScopeOption.Required,
-                    new TransactionMethod<Void>() {
-
-                        @Override
-                        public Void runInTransaction() {
-                            dao.updateAll(entities);
-                            return null;
-                        }
-                    });
-        }
+        updateAllInTransaction(null, entities,dao);
     }
 
     /**
+     * Update all the given entities in a transaction, so that a new 
connection/transaction won't be opened for each
+     * entity update.
+     *
+     * @param <T>
+     *            The type of entity.
+     * @param procieudreName
+     *            The name of stored procedure to use for update
+     * @param entities
+     *            The entities to update.
+     * @param dao
+     *            The DAO used for updating.
+     */
+
+    private static <T extends BusinessEntity<?>> void updateAllInTransaction
+        (final String procedureName, final Collection<T> entities, final 
MassOperationsDao<T> dao) {
+    if (!entities.isEmpty()) {
+        TransactionSupport.executeInScope(TransactionScopeOption.Required,
+            new TransactionMethod<Void>() {
+
+                @Override
+                public Void runInTransaction() {
+                    dao.updateAll(procedureName,entities);
+                    return null;
+                }
+            });
+    }
+}
+
+
+    /**
      * check if value is less than configurable threshold , if yes , generated 
event log message
      *
      * @param stat


--
To view, visit http://gerrit.ovirt.org/7641
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If316259f9760777c5f85db0880a157021c61a6ba
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Yair Zaslavsky <yzasl...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to