Skip to content

Commit daeb4ab

Browse files
committed
Create DB views for AsyncJobResponse to speed up listAsyncJobsCmd.
Signed-off-by: Min Chen <min.chen@citrix.com>
1 parent ff8fdbd commit daeb4ab

14 files changed

Lines changed: 808 additions & 149 deletions

File tree

api/src/com/cloud/server/ManagementService.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@
2525
import com.cloud.alert.Alert;
2626
import org.apache.cloudstack.api.ServerApiException;
2727
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
28-
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
2928
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
3029
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
3130
import org.apache.cloudstack.api.command.admin.resource.ListAlertsCmd;
3231
import org.apache.cloudstack.api.command.admin.resource.ListCapacityCmd;
33-
import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
3432
import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
3533
import org.apache.cloudstack.api.command.admin.storagepool.ListStoragePoolsCmd;
3634
import org.apache.cloudstack.api.command.admin.systemvm.*;
3735
import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd;
3836
import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd;
3937
import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd;
4038
import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd;
41-
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
4239
import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
4340
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
4441
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
@@ -48,12 +45,10 @@
4845
import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
4946
import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
5047
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
51-
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
5248
import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd;
5349
import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
5450
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
5551
import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd;
56-
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
5752
import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
5853
import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd;
5954
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
@@ -63,7 +58,6 @@
6358
import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd;
6459
import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd;
6560

66-
import com.cloud.async.AsyncJob;
6761
import com.cloud.capacity.Capacity;
6862
import com.cloud.configuration.Configuration;
6963
import com.cloud.dc.DataCenter;
@@ -328,15 +322,6 @@ public interface ManagementService {
328322
*/
329323
Pair<List<? extends Vlan>, Integer> searchForVlans(ListVlanIpRangesCmd cmd);
330324

331-
/**
332-
* Search for async jobs by account and/or startDate
333-
*
334-
* @param cmd
335-
* the command specifying the account and start date parameters
336-
* @return the list of async jobs that match the criteria
337-
*/
338-
Pair<List<? extends AsyncJob>, Integer> searchForAsyncJobs(ListAsyncJobsCmd cmd);
339-
340325
/**
341326
* Generates a random password that will be used (initially) by newly created and started virtual machines
342327
*

api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.cloudstack.api.ApiConstants;
2525
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
2626
import org.apache.cloudstack.api.Parameter;
27+
import org.apache.cloudstack.api.response.AccountResponse;
2728
import org.apache.cloudstack.api.response.AsyncJobResponse;
2829
import org.apache.cloudstack.api.response.ListResponse;
2930
import com.cloud.async.AsyncJob;
@@ -59,15 +60,10 @@ public String getCommandName() {
5960

6061
@Override
6162
public void execute(){
62-
Pair<List<? extends AsyncJob>, Integer> result = _mgr.searchForAsyncJobs(this);
63-
ListResponse<AsyncJobResponse> response = new ListResponse<AsyncJobResponse>();
64-
List<AsyncJobResponse> jobResponses = new ArrayList<AsyncJobResponse>();
65-
for (AsyncJob job : result.first()) {
66-
jobResponses.add(_responseGenerator.createAsyncJobResponse(job));
67-
}
6863

69-
response.setResponses(jobResponses, result.second());
64+
ListResponse<AsyncJobResponse> response = _queryService.searchForAsyncJobs(this);
7065
response.setResponseName(getCommandName());
7166
this.setResponseObject(response);
67+
7268
}
7369
}

api/src/org/apache/cloudstack/query/QueryService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
// under the License.
1717
package org.apache.cloudstack.query;
1818

19+
import java.util.List;
20+
1921
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
2022
import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
2123
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
2224
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
2325
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
2426
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
27+
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
2528
import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
2629
import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
2730
import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@@ -30,6 +33,7 @@
3033
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
3134
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
3235
import org.apache.cloudstack.api.response.AccountResponse;
36+
import org.apache.cloudstack.api.response.AsyncJobResponse;
3337
import org.apache.cloudstack.api.response.DomainRouterResponse;
3438
import org.apache.cloudstack.api.response.EventResponse;
3539
import org.apache.cloudstack.api.response.HostResponse;
@@ -46,7 +50,9 @@
4650

4751

4852

53+
import com.cloud.async.AsyncJob;
4954
import com.cloud.exception.PermissionDeniedException;
55+
import com.cloud.utils.Pair;
5056

5157
/**
5258
* Service used for list api query.
@@ -80,4 +86,6 @@ public interface QueryService {
8086
public ListResponse<VolumeResponse> searchForVolumes(ListVolumesCmd cmd);
8187

8288
public ListResponse<AccountResponse> searchForAccounts(ListAccountsCmd cmd);
89+
90+
public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd);
8391
}

server/src/com/cloud/api/ApiDBUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.cloudstack.api.ApiConstants.HostDetails;
2626
import org.apache.cloudstack.api.ApiConstants.VMDetails;
2727
import org.apache.cloudstack.api.response.AccountResponse;
28+
import org.apache.cloudstack.api.response.AsyncJobResponse;
2829
import org.apache.cloudstack.api.response.DomainRouterResponse;
2930
import org.apache.cloudstack.api.response.EventResponse;
3031
import org.apache.cloudstack.api.response.HostResponse;
@@ -39,6 +40,7 @@
3940
import org.apache.cloudstack.api.response.VolumeResponse;
4041

4142
import com.cloud.api.query.dao.AccountJoinDao;
43+
import com.cloud.api.query.dao.AsyncJobJoinDao;
4244
import com.cloud.api.query.dao.DomainRouterJoinDao;
4345
import com.cloud.api.query.dao.HostJoinDao;
4446
import com.cloud.api.query.dao.InstanceGroupJoinDao;
@@ -51,6 +53,7 @@
5153
import com.cloud.api.query.dao.UserVmJoinDao;
5254
import com.cloud.api.query.dao.VolumeJoinDao;
5355
import com.cloud.api.query.vo.AccountJoinVO;
56+
import com.cloud.api.query.vo.AsyncJobJoinVO;
5457
import com.cloud.api.query.vo.DomainRouterJoinVO;
5558
import com.cloud.api.query.vo.EventJoinVO;
5659
import com.cloud.api.query.vo.HostJoinVO;
@@ -322,6 +325,7 @@ public class ApiDBUtils {
322325
private static HostJoinDao _hostJoinDao;
323326
private static VolumeJoinDao _volJoinDao;
324327
private static AccountJoinDao _accountJoinDao;
328+
private static AsyncJobJoinDao _jobJoinDao;
325329

326330
private static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
327331
private static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@@ -411,6 +415,7 @@ public class ApiDBUtils {
411415
_hostJoinDao = locator.getDao(HostJoinDao.class);
412416
_volJoinDao = locator.getDao(VolumeJoinDao.class);
413417
_accountJoinDao = locator.getDao(AccountJoinDao.class);
418+
_jobJoinDao = locator.getDao(AsyncJobJoinDao.class);
414419

415420
_physicalNetworkTrafficTypeDao = locator.getDao(PhysicalNetworkTrafficTypeDao.class);
416421
_physicalNetworkServiceProviderDao = locator.getDao(PhysicalNetworkServiceProviderDao.class);
@@ -1364,4 +1369,12 @@ public static AccountJoinVO newAccountView(Account e){
13641369
public static AccountJoinVO findAccountViewById(Long accountId) {
13651370
return _accountJoinDao.findByIdIncludingRemoved(accountId);
13661371
}
1372+
1373+
public static AsyncJobResponse newAsyncJobResponse(AsyncJobJoinVO ve) {
1374+
return _jobJoinDao.newAsyncJobResponse(ve);
1375+
}
1376+
1377+
public static AsyncJobJoinVO newAsyncJobView(AsyncJob e){
1378+
return _jobJoinDao.newAsyncJobView(e);
1379+
}
13671380
}

server/src/com/cloud/api/ApiResponseHelper.java

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
import com.cloud.api.query.ViewResponseHelper;
4848
import com.cloud.api.query.vo.AccountJoinVO;
49+
import com.cloud.api.query.vo.AsyncJobJoinVO;
4950
import com.cloud.api.query.vo.ControlledViewEntity;
5051
import com.cloud.api.query.vo.DomainRouterJoinVO;
5152
import com.cloud.api.query.vo.EventJoinVO;
@@ -1803,49 +1804,8 @@ public String toSerializedString(CreateCmdResponse response, String responseType
18031804

18041805
@Override
18051806
public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
1806-
AsyncJobResponse jobResponse = new AsyncJobResponse();
1807-
Account account = ApiDBUtils.findAccountById(job.getAccountId());
1808-
if (account != null) {
1809-
jobResponse.setAccountId(account.getUuid());
1810-
}
1811-
User user = ApiDBUtils.findUserById(job.getUserId());
1812-
if (user != null) {
1813-
jobResponse.setUserId(user.getUuid());
1814-
}
1815-
jobResponse.setCmd(job.getCmd());
1816-
jobResponse.setCreated(job.getCreated());
1817-
jobResponse.setJobId(job.getUuid());
1818-
jobResponse.setJobStatus(job.getStatus());
1819-
jobResponse.setJobProcStatus(job.getProcessStatus());
1820-
1821-
if (job.getInstanceType() != null && job.getInstanceId() != null) {
1822-
jobResponse.setJobInstanceType(job.getInstanceType().toString());
1823-
String jobInstanceId = ApiDBUtils.findJobInstanceUuid(job);
1824-
1825-
if (jobInstanceId != null) {
1826-
jobResponse.setJobInstanceId(jobInstanceId);
1827-
}
1828-
}
1829-
jobResponse.setJobResultCode(job.getResultCode());
1830-
1831-
boolean savedValue = SerializationContext.current().getUuidTranslation();
1832-
SerializationContext.current().setUuidTranslation(false);
1833-
1834-
Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
1835-
jobResponse.setJobResult((ResponseObject) resultObject);
1836-
SerializationContext.current().setUuidTranslation(savedValue);
1837-
1838-
if (resultObject != null) {
1839-
Class<?> clz = resultObject.getClass();
1840-
if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
1841-
jobResponse.setJobResultType("text");
1842-
} else {
1843-
jobResponse.setJobResultType("object");
1844-
}
1845-
}
1846-
1847-
jobResponse.setObjectName("asyncjobs");
1848-
return jobResponse;
1807+
AsyncJobJoinVO vJob = ApiDBUtils.newAsyncJobView(job);
1808+
return ApiDBUtils.newAsyncJobResponse(vJob);
18491809
}
18501810

18511811
@Override

server/src/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
3535
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
3636
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
37+
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
3738
import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
3839
import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
3940
import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@@ -42,6 +43,7 @@
4243
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
4344
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
4445
import org.apache.cloudstack.api.response.AccountResponse;
46+
import org.apache.cloudstack.api.response.AsyncJobResponse;
4547
import org.apache.cloudstack.api.response.DomainRouterResponse;
4648
import org.apache.cloudstack.api.response.EventResponse;
4749
import org.apache.cloudstack.api.response.HostResponse;
@@ -62,6 +64,7 @@
6264
import com.cloud.api.ApiDBUtils;
6365
import com.cloud.api.ApiResponseHelper;
6466
import com.cloud.api.query.dao.AccountJoinDao;
67+
import com.cloud.api.query.dao.AsyncJobJoinDao;
6568
import com.cloud.api.query.dao.DomainRouterJoinDao;
6669
import com.cloud.api.query.dao.HostJoinDao;
6770
import com.cloud.api.query.dao.InstanceGroupJoinDao;
@@ -74,6 +77,7 @@
7477
import com.cloud.api.query.dao.UserVmJoinDao;
7578
import com.cloud.api.query.dao.VolumeJoinDao;
7679
import com.cloud.api.query.vo.AccountJoinVO;
80+
import com.cloud.api.query.vo.AsyncJobJoinVO;
7781
import com.cloud.api.query.vo.DomainRouterJoinVO;
7882
import com.cloud.api.query.vo.EventJoinVO;
7983
import com.cloud.api.query.vo.HostJoinVO;
@@ -87,6 +91,7 @@
8791
import com.cloud.api.query.vo.UserVmJoinVO;
8892
import com.cloud.api.query.vo.VolumeJoinVO;
8993
import com.cloud.async.AsyncJob;
94+
import com.cloud.async.AsyncJobVO;
9095
import com.cloud.domain.Domain;
9196
import com.cloud.domain.DomainVO;
9297
import com.cloud.domain.dao.DomainDao;
@@ -216,6 +221,9 @@ public class QueryManagerImpl implements QueryService, Manager {
216221
@Inject
217222
private AccountJoinDao _accountJoinDao;
218223

224+
@Inject
225+
private AsyncJobJoinDao _jobJoinDao;
226+
219227
@Inject
220228
private HighAvailabilityManager _haMgr;
221229

@@ -1727,10 +1735,86 @@ public Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccounts
17271735
}
17281736
}
17291737

1730-
Pair<List<AccountJoinVO>, Integer> result = _accountJoinDao.searchAndCount(sc, searchFilter);
1731-
return new Pair<List<AccountJoinVO>, Integer>(result.first(), result.second());
1738+
return _accountJoinDao.searchAndCount(sc, searchFilter);
1739+
}
1740+
1741+
@Override
1742+
public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd) {
1743+
Pair<List<AsyncJobJoinVO>, Integer> result = searchForAsyncJobsInternal(cmd);
1744+
ListResponse<AsyncJobResponse> response = new ListResponse<AsyncJobResponse>();
1745+
List<AsyncJobResponse> jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()]));
1746+
response.setResponses(jobResponses, result.second());
1747+
return response;
17321748
}
17331749

17341750

1751+
public Pair<List<AsyncJobJoinVO>, Integer> searchForAsyncJobsInternal(ListAsyncJobsCmd cmd) {
1752+
1753+
Account caller = UserContext.current().getCaller();
1754+
1755+
List<Long> permittedAccounts = new ArrayList<Long>();
1756+
1757+
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
1758+
cmd.getDomainId(), cmd.isRecursive(), null);
1759+
_accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject,
1760+
cmd.listAll(), false);
1761+
Long domainId = domainIdRecursiveListProject.first();
1762+
Boolean isRecursive = domainIdRecursiveListProject.second();
1763+
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
1764+
1765+
Filter searchFilter = new Filter(AsyncJobJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
1766+
SearchBuilder<AsyncJobJoinVO> sb = _jobJoinDao.createSearchBuilder();
1767+
sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
1768+
SearchBuilder<AccountVO> accountSearch = null;
1769+
boolean accountJoinIsDone = false;
1770+
if (permittedAccounts.isEmpty() && domainId != null) {
1771+
sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
1772+
sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
1773+
accountJoinIsDone = true;
1774+
}
1775+
1776+
if (listProjectResourcesCriteria != null) {
1777+
1778+
if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) {
1779+
sb.and("type", sb.entity().getAccountType(), SearchCriteria.Op.EQ);
1780+
} else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) {
1781+
sb.and("type", sb.entity().getAccountType(), SearchCriteria.Op.NEQ);
1782+
}
1783+
1784+
if (!accountJoinIsDone) {
1785+
sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
1786+
sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
1787+
}
1788+
}
1789+
1790+
Object keyword = cmd.getKeyword();
1791+
Object startDate = cmd.getStartDate();
1792+
1793+
SearchCriteria<AsyncJobJoinVO> sc = sb.create();
1794+
if (listProjectResourcesCriteria != null) {
1795+
sc.setParameters("type", Account.ACCOUNT_TYPE_PROJECT);
1796+
}
1797+
1798+
if (!permittedAccounts.isEmpty()) {
1799+
sc.setParameters("accountIdIN", permittedAccounts.toArray());
1800+
} else if (domainId != null) {
1801+
DomainVO domain = _domainDao.findById(domainId);
1802+
if (isRecursive) {
1803+
sc.setParameters("path", domain.getPath() + "%");
1804+
} else {
1805+
sc.setParameters("domainId", domainId);
1806+
}
1807+
}
1808+
1809+
if (keyword != null) {
1810+
sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
1811+
}
1812+
1813+
if (startDate != null) {
1814+
sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
1815+
}
1816+
1817+
return _jobJoinDao.searchAndCount(sc, searchFilter);
1818+
}
17351819

17361820
}

0 commit comments

Comments
 (0)