Bug 9117: allocator performance improvements

Fix for following optimization:
Make PodAllocator aware of host tags.

If the service offering has host_tag specified, PodAllocator can pick the pods having hosts with that tag. This would reduce the list of pods the allocator
has to iterate through to find a suitable pod.

Added a new PodAllocator 'HostTagBasedPodAllocator' that extends the 'UserConcentratedAllocator'.
This commit is contained in:
prachi 2011-03-24 16:57:54 -07:00 committed by Alex Huang
parent 3d558166a9
commit 0f3922f324
4 changed files with 109 additions and 8 deletions

View File

@ -30,6 +30,8 @@ public interface HostPodDao extends GenericDao<HostPodVO, Long> {
public HostPodVO findByName(String name, long dcId);
public HashMap<Long, List<Object>> getCurrentPodCidrSubnets(long zoneId, long podIdToSkip);
public HashMap<Long, List<Object>> getCurrentPodCidrSubnets(long zoneId, long podIdToSkip);
public List<HostPodVO> listPodsByHostTag(long dcId, String hostTag);
}

View File

@ -36,6 +36,7 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@Local(value={HostPodDao.class})
@ -43,7 +44,11 @@ public class HostPodDaoImpl extends GenericDaoBase<HostPodVO, Long> implements H
private static final Logger s_logger = Logger.getLogger(HostPodDaoImpl.class);
protected SearchBuilder<HostPodVO> DataCenterAndNameSearch;
protected SearchBuilder<HostPodVO> DataCenterIdSearch;
protected SearchBuilder<HostPodVO> DataCenterIdSearch;
private static final String PodsByHostTag = "SELECT DISTINCT host_pod_ref.* FROM (host_tags JOIN host ON host_tags.host_id = host.id AND host_tags.tag = ?) JOIN host_pod_ref " +
"ON host_pod_ref.id = host.pod_id WHERE host_pod_ref.data_center_id = ? ";
protected HostPodDaoImpl() {
DataCenterAndNameSearch = createSearchBuilder();
@ -96,7 +101,31 @@ public class HostPodDaoImpl extends GenericDaoBase<HostPodVO, Long> implements H
}
return currentPodCidrSubnets;
}
}
@Override
public List<HostPodVO> listPodsByHostTag(long dcId, String hostTag) {
StringBuilder sql = new StringBuilder(PodsByHostTag);
Transaction txn = Transaction.currentTxn();
PreparedStatement pstmt = s_initStmt;
try {
pstmt = txn.prepareAutoCloseStatement(sql.toString());
int i = 1;
pstmt.setString(i++, hostTag);
pstmt.setLong(i++, dcId);
ResultSet rs = pstmt.executeQuery();
List<HostPodVO> pods = new ArrayList<HostPodVO>();
while (rs.next()) {
pods.add(toEntityBean(rs, false));
}
return pods;
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e);
}
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {

View File

@ -0,0 +1,65 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.agent.manager.allocator.impl;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.manager.allocator.PodAllocator;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.service.ServiceOffering;
import com.cloud.utils.component.Inject;
/*
* Use this PodAllocator when the deployment is such that pod has homogeneous tags on hosts.
* If any pod can contain hosts with any tag, this optimization will not yield much benefit.
*/
@Local(value=PodAllocator.class)
public class HostTagBasedPodAllocator extends UserConcentratedAllocator {
private final static Logger s_logger = Logger.getLogger(HostTagBasedPodAllocator.class);
@Inject HostPodDao _podDao;
public HostTagBasedPodAllocator() {
}
@Override
protected List<HostPodVO> listPods(long zoneId, ServiceOffering offering){
List<HostPodVO> podsInZone = new ArrayList<HostPodVO>();
if(offering != null && offering.getHostTag() != null){
String hostTag = offering.getHostTag();
podsInZone = _podDao.listPodsByHostTag(zoneId, hostTag);
if(podsInZone.size() == 0){
if (s_logger.isInfoEnabled()) {
s_logger.info("No Pods found in Zone: '"+zoneId+"' having Hosts with host tag: '"+ hostTag +"'");
}
}else{
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found "+podsInZone.size() +" Pods in Zone: '"+zoneId+"' having Hosts with host tag: '"+ hostTag +"'");
}
}
}else{
podsInZone = super.listPods(zoneId, offering);
}
return podsInZone;
}
}

View File

@ -83,7 +83,7 @@ public class UserConcentratedAllocator implements PodAllocator {
@Override
public Pair<HostPodVO, Long> allocateTo(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO zone, long accountId, Set<Long> avoids) {
long zoneId = zone.getId();
List<HostPodVO> podsInZone = _podDao.listByDataCenterId(zoneId);
List<HostPodVO> podsInZone = listPods(zoneId, offering);
if (podsInZone.size() == 0) {
s_logger.debug("No pods found in zone " + zone.getName());
@ -100,10 +100,7 @@ public class UserConcentratedAllocator implements PodAllocator {
s_logger.debug("Checking Pod: " + podId);
}
if (template != null && !templateAvailableInPod(template.getId(), pod.getDataCenterId(), podId)) {
continue;
}
if (offering != null) {
// test for enough memory in the pod (make sure to check for enough memory for the service offering, plus some extra padding for xen overhead
long[] hostCandiates = new long[1];
@ -160,6 +157,14 @@ public class UserConcentratedAllocator implements PodAllocator {
return new Pair<HostPodVO, Long>(selectedPod, podHostCandidates.get(selectedPod.getId()));
}
}
protected List<HostPodVO> listPods(long zoneId, ServiceOffering offering){
List<HostPodVO> podsInZone = _podDao.listByDataCenterId(zoneId);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found "+podsInZone.size() +" Pods in Zone: "+zoneId);
}
return podsInZone;
}
private boolean dataCenterAndPodHasEnoughCapacity(long dataCenterId, long podId, long capacityNeeded, short capacityType, long[] hostCandidate) {
List<CapacityVO> capacities = null;