CLOUDSTACK-8423: [Xenserver] Improved the performance for processing of 
ClusterVMMetaDataSync command which can cause slowness in DB if there are huge 
number of VMs
this closes #204

Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/866cc411
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/866cc411
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/866cc411

Branch: refs/heads/master
Commit: 866cc41145bd8ccbf5f883a24ec3ef4763ebdb22
Parents: f46ed59
Author: Anshul Gangwar <anshul.gang...@citrix.com>
Authored: Tue Apr 28 13:37:56 2015 +0530
Committer: Rajesh Battala <rajesh.batt...@citrix.com>
Committed: Thu Apr 30 14:44:36 2015 +0530

----------------------------------------------------------------------
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 62 +++++++++++++-------
 .../schema/src/com/cloud/vm/dao/UserVmDao.java  |  4 ++
 .../src/com/cloud/vm/dao/UserVmDaoImpl.java     | 42 +++++++++++++
 .../xenserver/resource/CitrixResourceBase.java  |  4 ++
 4 files changed, 90 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java 
b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 527b623..a48db61 100644
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -2558,40 +2558,58 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
         if (vmMetadatum == null || vmMetadatum.isEmpty()) {
             return;
         }
+        List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> 
vmDetails = _userVmDao.getVmsDetailByNames(vmMetadatum.keySet(), "platform");
         for (final Map.Entry<String, String> entry : vmMetadatum.entrySet()) {
             final String name = entry.getKey();
             final String platform = entry.getValue();
             if (platform == null || platform.isEmpty()) {
                 continue;
             }
-            final VMInstanceVO vm = _vmDao.findVMByInstanceName(name);
-            if (vm != null && vm.getType() == VirtualMachine.Type.User) {
-                boolean changed = false;
-                final UserVmVO userVm = _userVmDao.findById(vm.getId());
-                _userVmDao.loadDetails(userVm);
-                if ( userVm.details.containsKey("timeoffset")) {
-                    userVm.details.remove("timeoffset");
-                    changed = true;
-                }
-                if (!userVm.details.containsKey("platform") || 
!userVm.details.get("platform").equals(platform)) {
-                    userVm.setDetail("platform",  platform);
-                    changed = true;
-                }
-                String pvdriver = "xenserver56";
-                if ( platform.contains("device_id")) {
-                    pvdriver = "xenserver61";
-                }
-                if (!userVm.details.containsKey("hypervisortoolsversion") || 
!userVm.details.get("hypervisortoolsversion").equals(pvdriver)) {
-                    userVm.setDetail("hypervisortoolsversion", pvdriver);
-                    changed = true;
+
+            boolean found = false;
+            for(Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>> 
vmDetail : vmDetails ) {
+                Pair<String, VirtualMachine.Type> vmNameTypePair = 
vmDetail.first();
+                if(vmNameTypePair.first().equals(name)) {
+                    found = true;
+                    if(vmNameTypePair.second() == VirtualMachine.Type.User) {
+                        Pair<Long, String> detailPair = vmDetail.second();
+                        String platformDetail = detailPair.second();
+
+                        if (platformDetail != null && 
platformDetail.equals(platform)) {
+                            break;
+                        }
+                        updateVmMetaData(detailPair.first(), platform);
+                    }
+                    break;
                 }
-                if ( changed ) {
-                    _userVmDao.saveDetails(userVm);
+            }
+
+            if(!found) {
+                VMInstanceVO vm = _vmDao.findVMByInstanceName(name);
+                if(vm.getType() == VirtualMachine.Type.User) {
+                    updateVmMetaData(vm.getId(), platform);
                 }
             }
         }
     }
 
+    // this is XenServer specific
+    private void updateVmMetaData(Long vmId, String platform) {
+        UserVmVO userVm = _userVmDao.findById(vmId);
+        _userVmDao.loadDetails(userVm);
+        if ( userVm.details.containsKey("timeoffset")) {
+            userVm.details.remove("timeoffset");
+        }
+        userVm.setDetail("platform",  platform);
+        String pvdriver = "xenserver56";
+        if ( platform.contains("device_id")) {
+            pvdriver = "xenserver61";
+        }
+        if (!userVm.details.containsKey("hypervisortoolsversion") || 
!userVm.details.get("hypervisortoolsversion").equals(pvdriver)) {
+            userVm.setDetail("hypervisortoolsversion", pvdriver);
+        }
+        _userVmDao.saveDetails(userVm);
+    }
 
     private void ensureVmRunningContext(final long hostId, VMInstanceVO vm, 
final Event cause) throws OperationTimedoutException, 
ResourceUnavailableException,
     NoTransitionException, InsufficientAddressCapacityException {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java 
b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
index dfafdeb..dfcc7f7 100644
--- a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
@@ -19,9 +19,12 @@ package com.cloud.vm.dao;
 import java.util.Date;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Set;
 
+import com.cloud.utils.Pair;
 import com.cloud.utils.db.GenericDao;
 import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.State;
 
 public interface UserVmDao extends GenericDao<UserVmVO, Long> {
@@ -80,4 +83,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> 
{
 
     List<UserVmVO> listByIsoId(Long isoId);
 
+    List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> 
getVmsDetailByNames(Set<String> vmNames, String detail);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java 
b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
index ef762e1..5fa3b06 100644
--- a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
@@ -24,11 +24,13 @@ import java.util.Date;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.annotation.PostConstruct;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import com.cloud.utils.Pair;
 import org.apache.log4j.Logger;
 
 import com.cloud.server.ResourceTag.ResourceObjectType;
@@ -102,6 +104,11 @@ public class UserVmDaoImpl extends 
GenericDaoBase<UserVmVO, Long> implements Use
             + "left join security_group on 
security_group_vm_map.security_group_id=security_group.id " + "left join nics 
on vm_instance.id=nics.instance_id "
             + "left join networks on nics.network_id=networks.id " + "left 
join user_ip_address on user_ip_address.vm_id=vm_instance.id " + "where 
vm_instance.id in (";
 
+    private static final String VMS_DETAIL_BY_NAME = "select 
vm_instance.instance_name, vm_instance.vm_type, vm_instance.id , 
user_vm_details.value, user_vm_details.name from vm_instance "
+            + "left join user_vm_details on vm_instance.id = 
user_vm_details.vm_id where (user_vm_details.name is null or 
user_vm_details.name = '";
+
+    private static final String VMS_DETAIL_BY_NAME2 = "') and 
vm_instance.instance_name in (";
+
     private static final int VM_DETAILS_BATCH_SIZE = 100;
 
     @Inject
@@ -631,4 +638,39 @@ public class UserVmDaoImpl extends 
GenericDaoBase<UserVmVO, Long> implements Use
         return result;
     }
 
+    @Override
+    public List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> 
getVmsDetailByNames(Set<String> vmNames, String detail) {
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+        List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> 
vmsDetailByNames = new ArrayList<Pair<Pair<String, VirtualMachine.Type>, 
Pair<Long, String>>>();
+
+        PreparedStatement pstmt = null;
+        try {
+            pstmt = txn.prepareStatement(VMS_DETAIL_BY_NAME + detail + 
VMS_DETAIL_BY_NAME2 + getQueryBatchAppender(vmNames.size()));
+            int i = 1;
+            for(String name : vmNames) {
+                pstmt.setString(i, name);
+                i++;
+            }
+            try {
+                ResultSet rs = pstmt.executeQuery();
+                while (rs.next()) {
+                    vmsDetailByNames.add(new Pair<Pair<String, 
VirtualMachine.Type>, Pair<Long, String>>(new Pair<String, VirtualMachine.Type>(
+                            rs.getString("vm_instance.instance_name"), 
VirtualMachine.Type.valueOf(rs.getString("vm_type"))),
+                            new Pair<Long, 
String>(rs.getLong("vm_instance.id"), rs.getString("user_vm_details.value"))));
+                }
+                rs.close();
+            } catch (Exception e) {
+                s_logger.error("GetVmsDetailsByNames: Exception: " + 
e.getMessage());
+                throw new CloudRuntimeException("GetVmsDetailsByNames: 
Exception: " + e.getMessage());
+            }
+            if(pstmt != null) {
+                pstmt.close();
+            }
+        } catch (Exception e) {
+            s_logger.error("GetVmsDetailsByNames: Exception in sql: " + 
e.getMessage());
+            throw new CloudRuntimeException("GetVmsDetailsByNames: Exception: 
" + e.getMessage());
+        }
+
+        return vmsDetailByNames;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
 
b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
index ff9f61d..2b3035c 100644
--- 
a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ 
b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -717,6 +717,10 @@ public abstract class CitrixResourceBase implements 
ServerResource, HypervisorRe
                     if (record.isControlDomain || record.isASnapshot || 
record.isATemplate) {
                         continue; // Skip DOM0
                     }
+                    String platform = StringUtils.mapToString(record.platform);
+                    if (platform.isEmpty()) {
+                        continue; //Skip if platform is null
+                    }
                     vmMetaDatum.put(record.nameLabel, 
StringUtils.mapToString(record.platform));
                 }
             }

Reply via email to