Skip to content

Commit 523ebff

Browse files
committed
wip - use cache for finding resource by id during vm deploy
1 parent c253d56 commit 523ebff

17 files changed

Lines changed: 303 additions & 166 deletions

File tree

api/src/main/java/org/apache/cloudstack/context/CallContext.java

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

19+
import java.time.Duration;
1920
import java.util.HashMap;
2021
import java.util.Map;
2122
import java.util.Stack;
@@ -65,6 +66,7 @@ protected Stack<CallContext> initialValue() {
6566
private final Map<Object, Object> context = new HashMap<Object, Object>();
6667
private Project project;
6768
private String apiName;
69+
private final RequestEntityCache requestEntityCache = new RequestEntityCache(Duration.ofSeconds(60));
6870

6971
static EntityManager s_entityMgr;
7072

@@ -423,4 +425,8 @@ public String toString() {
423425
.append("]")
424426
.toString();
425427
}
428+
429+
public RequestEntityCache getRequestEntityCache() {
430+
return requestEntityCache;
431+
}
426432
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.context;
19+
20+
import java.time.Duration;
21+
import java.util.concurrent.ConcurrentHashMap;
22+
import java.util.function.Supplier;
23+
24+
public final class RequestEntityCache {
25+
private static final class Key {
26+
final Class<?> type;
27+
final long id;
28+
Key(Class<?> type, long id) { this.type = type; this.id = id; }
29+
@Override public boolean equals(Object o) {
30+
if (this == o) return true;
31+
if (!(o instanceof Key)) return false;
32+
Key k = (Key) o; return id == k.id && type.equals(k.type);
33+
}
34+
@Override public int hashCode() { return 31 * type.hashCode() + Long.hashCode(id); }
35+
}
36+
private static final class Entry {
37+
final Object value; final long expireAtNanos; // 0 = never expires
38+
Entry(Object v, long exp) { value = v; expireAtNanos = exp; }
39+
}
40+
41+
private final ConcurrentHashMap<Key, Entry> map = new ConcurrentHashMap<>();
42+
private final long ttlNanos; // 0 = no TTL
43+
44+
public RequestEntityCache(Duration ttl) { this.ttlNanos = ttl == null ? 0 : ttl.toNanos(); }
45+
46+
@SuppressWarnings("unchecked")
47+
public <T> T get(Class<T> type, long id, Supplier<T> loader) {
48+
final long now = System.nanoTime();
49+
final Key key = new Key(type, id);
50+
Entry e = map.get(key);
51+
if (e != null && (e.expireAtNanos == 0 || now < e.expireAtNanos)) {
52+
return (T) e.value;
53+
}
54+
T loaded = loader.get();
55+
long exp = ttlNanos == 0 ? 0 : now + ttlNanos;
56+
if (loaded != null) map.put(key, new Entry(loaded, exp));
57+
return loaded;
58+
}
59+
60+
public void clear() { map.clear(); }
61+
}

engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import javax.inject.Inject;
2727

2828
import com.cloud.network.Network;
29+
30+
import org.apache.cloudstack.context.CallContext;
2931
import org.apache.commons.collections.MapUtils;
3032
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3133

@@ -215,7 +217,8 @@ private static void publishUsageEvent(String usageEventType, Long accountId, Lon
215217
}
216218

217219
Account account = s_accountDao.findById(accountId);
218-
DataCenterVO dc = s_dcDao.findById(zoneId);
220+
DataCenterVO dc = CallContext.current().getRequestEntityCache().get(DataCenterVO.class, zoneId,
221+
() -> s_dcDao.findById(zoneId));
219222

220223
// if account has been deleted, this might be called during cleanup of resources and results in null pointer
221224
if (account == null)

engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
import com.cloud.resource.ResourceState;
4646
import org.apache.cloudstack.ca.CAManager;
47+
import org.apache.cloudstack.context.CallContext;
4748
import org.apache.cloudstack.framework.config.ConfigDepot;
4849
import org.apache.cloudstack.framework.config.ConfigKey;
4950
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -573,7 +574,8 @@ public SocketChannel connectToPeer(final long hostId, final SocketChannel prevCh
573574
@Override
574575
protected AgentAttache getAttache(final Long hostId) throws AgentUnavailableException {
575576
assert hostId != null : "Who didn't check their id value?";
576-
final HostVO host = _hostDao.findById(hostId);
577+
final HostVO host = CallContext.current().getRequestEntityCache()
578+
.get(HostVO.class, hostId, () -> _hostDao.findById(hostId));
577579
if (host == null) {
578580
throw new AgentUnavailableException("Can't find the host ", hostId);
579581
}

engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import javax.inject.Inject;
2626

27+
import org.apache.cloudstack.context.CallContext;
2728
import org.apache.cloudstack.framework.config.ConfigKey;
2829
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
2930
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
@@ -197,7 +198,8 @@ private String getCpuMemoryOvercommitRatio(String name) {
197198

198199
@Override
199200
public Pair<Scope, Long> getParentScope(long id) {
200-
Cluster cluster = clusterDao.findById(id);
201+
Cluster cluster = CallContext.current().getRequestEntityCache().get(ClusterVO.class, id,
202+
() -> clusterDao.findById(id));
201203
if (cluster == null) {
202204
return null;
203205
}

engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,62 +16,61 @@
1616
// under the License.
1717
package org.apache.cloudstack.storage.allocator;
1818

19-
import com.cloud.api.query.dao.StoragePoolJoinDao;
20-
import com.cloud.dc.dao.HostPodDao;
21-
import com.cloud.exception.StorageUnavailableException;
22-
import com.cloud.host.HostVO;
23-
import com.cloud.host.dao.HostDao;
24-
import com.cloud.storage.ScopeType;
25-
import com.cloud.storage.StoragePoolStatus;
26-
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
27-
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
28-
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
29-
import org.apache.commons.lang3.StringUtils;
30-
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
31-
import org.apache.commons.collections.CollectionUtils;
19+
import java.math.BigDecimal;
20+
import java.security.SecureRandom;
21+
import java.text.DecimalFormat;
22+
import java.util.ArrayList;
23+
import java.util.Arrays;
24+
import java.util.Collections;
25+
import java.util.Comparator;
26+
import java.util.HashMap;
27+
import java.util.LinkedHashMap;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.stream.Collectors;
3231

33-
import com.cloud.utils.Pair;
32+
import javax.inject.Inject;
33+
import javax.naming.ConfigurationException;
34+
35+
import org.apache.cloudstack.context.CallContext;
36+
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
3437
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
3538
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
3639
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3740
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
41+
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
42+
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
43+
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
44+
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
45+
import org.apache.commons.collections.CollectionUtils;
46+
import org.apache.commons.lang3.StringUtils;
3847

48+
import com.cloud.api.query.dao.StoragePoolJoinDao;
3949
import com.cloud.capacity.Capacity;
4050
import com.cloud.capacity.dao.CapacityDao;
4151
import com.cloud.dc.ClusterVO;
4252
import com.cloud.dc.dao.ClusterDao;
4353
import com.cloud.deploy.DeploymentPlan;
4454
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
55+
import com.cloud.exception.StorageUnavailableException;
56+
import com.cloud.host.HostVO;
57+
import com.cloud.host.dao.HostDao;
4558
import com.cloud.hypervisor.Hypervisor.HypervisorType;
59+
import com.cloud.storage.ScopeType;
4660
import com.cloud.storage.Storage;
4761
import com.cloud.storage.StorageManager;
4862
import com.cloud.storage.StoragePool;
63+
import com.cloud.storage.StoragePoolStatus;
4964
import com.cloud.storage.StorageUtil;
5065
import com.cloud.storage.Volume;
5166
import com.cloud.storage.dao.VolumeDao;
5267
import com.cloud.user.Account;
5368
import com.cloud.utils.NumbersUtil;
69+
import com.cloud.utils.Pair;
5470
import com.cloud.utils.component.AdapterBase;
5571
import com.cloud.vm.DiskProfile;
5672
import com.cloud.vm.VirtualMachineProfile;
5773

58-
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
59-
60-
import javax.inject.Inject;
61-
import javax.naming.ConfigurationException;
62-
import java.math.BigDecimal;
63-
import java.security.SecureRandom;
64-
import java.text.DecimalFormat;
65-
import java.util.ArrayList;
66-
import java.util.Arrays;
67-
import java.util.Collections;
68-
import java.util.Comparator;
69-
import java.util.HashMap;
70-
import java.util.LinkedHashMap;
71-
import java.util.List;
72-
import java.util.Map;
73-
import java.util.stream.Collectors;
74-
7574
public abstract class AbstractStoragePoolAllocator extends AdapterBase implements StoragePoolAllocator {
7675

7776
protected BigDecimal storageOverprovisioningFactor = new BigDecimal(1);
@@ -88,8 +87,6 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
8887
@Inject private StoragePoolDetailsDao storagePoolDetailsDao;
8988
@Inject
9089
protected HostDao hostDao;
91-
@Inject
92-
protected HostPodDao podDao;
9390

9491
/**
9592
* make sure shuffled lists of Pools are really shuffled
@@ -329,7 +326,8 @@ protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh,
329326
}
330327

331328
if (plan.getHostId() != null) {
332-
HostVO plannedHost = hostDao.findById(plan.getHostId());
329+
HostVO plannedHost = CallContext.current().getRequestEntityCache()
330+
.get(HostVO.class, plan.getHostId(), () -> hostDao.findById(plan.getHostId()));
333331
if (!storageMgr.checkIfHostAndStoragePoolHasCommonStorageAccessGroups(plannedHost, pool)) {
334332
if (logger.isDebugEnabled()) {
335333
logger.debug(String.format("StoragePool %s and host %s does not have matching storage access groups", pool, plannedHost));

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,77 +16,77 @@
1616
// under the License.
1717
package org.apache.cloudstack.storage.volume;
1818

19+
import java.util.Arrays;
1920
import java.util.Date;
21+
import java.util.HashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.Set;
25+
import java.util.function.Function;
2026

2127
import javax.inject.Inject;
2228

23-
import com.cloud.configuration.Resource.ResourceType;
24-
import com.cloud.dc.VsphereStoragePolicyVO;
25-
import com.cloud.dc.dao.VsphereStoragePolicyDao;
26-
import com.cloud.storage.StorageManager;
27-
import com.cloud.utils.Pair;
28-
import com.cloud.utils.db.Transaction;
29-
import com.cloud.utils.db.TransactionCallbackNoReturn;
30-
import com.cloud.utils.db.TransactionStatus;
31-
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
32-
import org.apache.cloudstack.secret.dao.PassphraseDao;
33-
import org.apache.cloudstack.secret.PassphraseVO;
34-
import com.cloud.service.dao.ServiceOfferingDetailsDao;
35-
import com.cloud.storage.MigrationOptions;
36-
import com.cloud.storage.VMTemplateVO;
37-
import com.cloud.storage.VolumeDetailVO;
38-
import com.cloud.storage.dao.VMTemplateDao;
39-
import com.cloud.storage.dao.VolumeDetailsDao;
40-
import com.cloud.user.ResourceLimitService;
41-
import com.cloud.vm.VmDetailConstants;
42-
43-
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
4429
import org.apache.cloudstack.api.ApiConstants;
30+
import org.apache.cloudstack.context.CallContext;
31+
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
4532
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
4633
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
4734
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
4835
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
36+
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
37+
import org.apache.cloudstack.secret.PassphraseVO;
38+
import org.apache.cloudstack.secret.dao.PassphraseDao;
4939
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
5040
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
5141
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
5242
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
5343
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
5444
import org.apache.cloudstack.storage.to.VolumeObjectTO;
45+
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
5546
import org.apache.commons.lang3.StringUtils;
56-
import org.apache.logging.log4j.Logger;
5747
import org.apache.logging.log4j.LogManager;
48+
import org.apache.logging.log4j.Logger;
5849

5950
import com.cloud.agent.api.Answer;
6051
import com.cloud.agent.api.storage.DownloadAnswer;
6152
import com.cloud.agent.api.to.DataObjectType;
6253
import com.cloud.agent.api.to.DataTO;
54+
import com.cloud.configuration.Resource.ResourceType;
55+
import com.cloud.dc.VsphereStoragePolicyVO;
56+
import com.cloud.dc.dao.VsphereStoragePolicyDao;
6357
import com.cloud.exception.ConcurrentOperationException;
6458
import com.cloud.hypervisor.Hypervisor.HypervisorType;
6559
import com.cloud.offering.DiskOffering.DiskCacheMode;
60+
import com.cloud.service.dao.ServiceOfferingDetailsDao;
6661
import com.cloud.storage.DataStoreRole;
6762
import com.cloud.storage.DiskOfferingVO;
63+
import com.cloud.storage.MigrationOptions;
6864
import com.cloud.storage.Storage;
6965
import com.cloud.storage.Storage.ImageFormat;
7066
import com.cloud.storage.Storage.ProvisioningType;
67+
import com.cloud.storage.StorageManager;
68+
import com.cloud.storage.VMTemplateVO;
7169
import com.cloud.storage.Volume;
70+
import com.cloud.storage.VolumeDetailVO;
7271
import com.cloud.storage.VolumeVO;
7372
import com.cloud.storage.dao.DiskOfferingDao;
73+
import com.cloud.storage.dao.VMTemplateDao;
7474
import com.cloud.storage.dao.VolumeDao;
75+
import com.cloud.storage.dao.VolumeDetailsDao;
76+
import com.cloud.user.ResourceLimitService;
77+
import com.cloud.utils.Pair;
7578
import com.cloud.utils.component.ComponentContext;
79+
import com.cloud.utils.db.Transaction;
80+
import com.cloud.utils.db.TransactionCallbackNoReturn;
81+
import com.cloud.utils.db.TransactionStatus;
7682
import com.cloud.utils.exception.CloudRuntimeException;
7783
import com.cloud.utils.fsm.NoTransitionException;
7884
import com.cloud.utils.fsm.StateMachine2;
7985
import com.cloud.utils.storage.encoding.EncodingType;
8086
import com.cloud.vm.VMInstanceVO;
8187
import com.cloud.vm.VirtualMachine;
88+
import com.cloud.vm.VmDetailConstants;
8289
import com.cloud.vm.dao.VMInstanceDao;
83-
import java.util.Arrays;
84-
import java.util.HashMap;
85-
import java.util.List;
86-
import java.util.Map;
87-
import java.util.Set;
88-
import java.util.function.Function;
89-
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
9090

9191
public class VolumeObject implements VolumeInfo {
9292
protected Logger logger = LogManager.getLogger(getClass());
@@ -255,7 +255,8 @@ public boolean stateTransit(Volume.Event event) {
255255

256256
protected DiskOfferingVO getDiskOfferingVO() {
257257
Long diskOfferingId = getDiskOfferingId();
258-
return diskOfferingId == null ? null : diskOfferingDao.findById(diskOfferingId);
258+
return diskOfferingId == null ? null : CallContext.current().getRequestEntityCache()
259+
.get(DiskOfferingVO.class, diskOfferingId, () -> diskOfferingDao.findById(diskOfferingId));
259260
}
260261

261262
@Override

0 commit comments

Comments
 (0)