Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / datastore / CacheOnlyEntityCachingStrategy.java
blob7a590a879b8426b17c65141545e4f1ce6f594497
1 package com.google.appengine.api.datastore;
3 import static com.google.appengine.api.datastore.FutureHelper.quietGet;
5 import com.google.appengine.api.datastore.EntityCache.IdentifiableCacheValue;
6 import com.google.appengine.api.datastore.FutureHelper.FakeFuture;
7 import com.google.appengine.api.memcache.MemcacheService.SetPolicy;
8 import com.google.apphosting.datastore.EntityStorage.CacheValue;
9 import com.google.apphosting.datastore.EntityStorage.CacheValue.State;
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.collect.ImmutableSet;
13 import com.google.common.collect.Maps;
14 import com.google.common.collect.Sets;
15 import com.google.storage.onestore.v3.OnestoreEntity.EntityProto;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.concurrent.Future;
22 /**
23 * A cache-only entity caching strategy implementation. This class implements the policy specified
24 * by {@link EntityCachePolicy#CACHE_ONLY}.
27 final class CacheOnlyEntityCachingStrategy extends EntityCachingStrategy {
29 private final EntityCache cache;
30 private final DatastoreServiceConfig datastoreServiceConfig;
32 CacheOnlyEntityCachingStrategy(DatastoreServiceConfig datastoreServiceConfig) {
33 MemcacheServiceHelper memcacheServiceHelper = MemcacheServiceHelper.Builder.withDefaults();
34 double datastoreRpcDeadline = (datastoreServiceConfig.getDeadline() == null) ?
35 DEFAULT_DATASTORE_RPC_DEADLINE_SECS : datastoreServiceConfig.getDeadline();
36 cache = new EntityCache(memcacheServiceHelper, datastoreRpcDeadline);
37 this.datastoreServiceConfig = datastoreServiceConfig;
40 CacheOnlyEntityCachingStrategy(EntityCache cache, DatastoreServiceConfig datastoreServiceConfig) {
41 this.cache = cache;
42 this.datastoreServiceConfig = datastoreServiceConfig;
45 @Override
46 public PreGetCachingResult preGet(CurrentTransactionProvider currentTxnProvider,
47 List<Key> keysToGet, Map<Key, Entity> resultMap) {
48 List<Key> cacheableKeys = getCacheableKeys(datastoreServiceConfig, keysToGet);
49 Future<Map<Key, IdentifiableCacheValue>> cacheGetResults;
50 if (cacheableKeys.isEmpty()) {
51 cacheGetResults = new FakeFuture<Map<Key, IdentifiableCacheValue>>(
52 ImmutableMap.<Key, IdentifiableCacheValue>of());
53 } else {
54 cacheGetResults = cache.getIdentifiableAsync(cacheableKeys);
56 return new CacheOnlyPreGetCachingResult(Sets.newHashSet(cacheableKeys), cacheGetResults);
59 @Override
60 protected void postGet(PreGetCachingResult preGetResult, Map<Key, Entity> resultMap) {
61 CacheOnlyPreGetCachingResult preGetStrategyResult = (CacheOnlyPreGetCachingResult) preGetResult;
62 Map<Key, IdentifiableCacheValue> cacheResults =
63 quietGet(preGetStrategyResult.getCacheResults());
64 for (Map.Entry<Key, IdentifiableCacheValue> cacheEntry : cacheResults.entrySet()) {
65 CacheValue cacheValue = cacheEntry.getValue().getValue();
66 if ((cacheValue.getStateEnum() == State.ENTITY) && cacheValue.hasEntity()) {
67 resultMap.put(cacheEntry.getKey(),
68 EntityTranslator.createFromPb(cacheValue.getEntity().getV3Entity()));
73 @Override
74 public PreMutationCachingResult prePut(CurrentTransactionProvider currentTxnProvider,
75 List<Entity> entitiesToPut) {
76 if (currentTxnProvider.getCurrentTransaction(null) == null) {
77 return preCommit(entitiesToPut, ImmutableList.<Key>of());
78 } else {
79 PreMutationCachingResult preMutationResult =
80 new PreMutationCachingResult(ImmutableSet.<Key>of());
81 List<Entity> cacheableEntities = getCacheableEntities(datastoreServiceConfig, entitiesToPut);
82 Set<Key> mutationKeysToSkip = Sets.newHashSetWithExpectedSize(cacheableEntities.size());
83 for (Entity cacheableEntity : cacheableEntities) {
84 mutationKeysToSkip.add(cacheableEntity.getKey());
86 preMutationResult.setMutationKeysToSkip(mutationKeysToSkip);
87 return preMutationResult;
91 @Override
92 public PreMutationCachingResult preDelete(CurrentTransactionProvider currentTxnProvider,
93 List<Key> keysToDelete) {
94 if (currentTxnProvider.getCurrentTransaction(null) == null) {
95 return preCommit(ImmutableList.<Entity>of(), keysToDelete);
96 } else {
97 PreMutationCachingResult preMutationResult =
98 new PreMutationCachingResult(ImmutableSet.<Key>of());
99 List<Key> cacheableKeys = getCacheableKeys(datastoreServiceConfig, keysToDelete);
100 preMutationResult.setMutationKeysToSkip(Sets.newHashSet(cacheableKeys));
101 return preMutationResult;
105 @Override
106 public PreMutationCachingResult preCommit(List<Entity> entitiesToPut, List<Key> keysToDelete) {
107 List<Entity> cacheableEntitiesToPut =
108 getCacheableEntities(datastoreServiceConfig, entitiesToPut);
109 List<Key> cacheableKeysToDelete = getCacheableKeys(datastoreServiceConfig, keysToDelete);
110 Future<Set<Key>> keysPut = new FakeFuture<Set<Key>>(ImmutableSet.<Key>of());
111 Future<Set<Key>> keysEvicted = new FakeFuture<Set<Key>>(ImmutableSet.<Key>of());
112 if (!cacheableEntitiesToPut.isEmpty()) {
113 Set<Key> cacheableKeysToDeleteSet = Sets.newHashSet(cacheableKeysToDelete);
114 Map<Key, EntityProto> entityMap =
115 Maps.newHashMapWithExpectedSize(cacheableEntitiesToPut.size());
116 for (Entity entity : cacheableEntitiesToPut) {
117 Key entityKey = entity.getKey();
118 if (entityKey.isComplete() && !cacheableKeysToDeleteSet.contains(entityKey)) {
119 entityMap.put(entityKey, EntityTranslator.convertToPb(entity));
122 if (!entityMap.isEmpty()) {
123 keysPut = cache.putEntitiesAsync(entityMap, SetPolicy.SET_ALWAYS);
126 if (!cacheableKeysToDelete.isEmpty()) {
127 keysEvicted = cache.evictAsync(cacheableKeysToDelete);
129 Set<Key> mutationKeysToSkip = Sets.newHashSetWithExpectedSize(cacheableEntitiesToPut.size());
130 for (Entity cacheableEntity : cacheableEntitiesToPut) {
131 mutationKeysToSkip.add(cacheableEntity.getKey());
133 mutationKeysToSkip.addAll(cacheableKeysToDelete);
134 return new CacheOnlyPreMutationCachingResult(mutationKeysToSkip, keysPut, keysEvicted);
137 @Override
138 protected void postMutation(PreMutationCachingResult preMutationResult) {
139 CacheOnlyPreMutationCachingResult preMutationStrategyResult =
140 (CacheOnlyPreMutationCachingResult) preMutationResult;
141 quietGet(preMutationStrategyResult.getKeysPut());
142 quietGet(preMutationStrategyResult.getKeysEvicted());
145 static final class CacheOnlyPreGetCachingResult extends PreGetCachingResult {
146 private final Future<Map<Key, IdentifiableCacheValue>> cacheResults;
148 public CacheOnlyPreGetCachingResult(Set<Key> keysToSkipLoading,
149 Future<Map<Key, IdentifiableCacheValue>> cacheResults) {
150 super(keysToSkipLoading);
151 this.cacheResults = cacheResults;
154 public Future<Map<Key, IdentifiableCacheValue>> getCacheResults() {
155 return cacheResults;
159 static final class CacheOnlyPreMutationCachingResult extends PreMutationCachingResult {
160 private final Future<Set<Key>> keysPut;
161 private final Future<Set<Key>> keysEvicted;
163 public CacheOnlyPreMutationCachingResult(Set<Key> mutationKeysToSkip, Future<Set<Key>> keysPut,
164 Future<Set<Key>> keysEvicted) {
165 super(mutationKeysToSkip);
166 this.keysPut = keysPut;
167 this.keysEvicted = keysEvicted;
170 public Future<Set<Key>> getKeysPut() {
171 return keysPut;
174 public Future<Set<Key>> getKeysEvicted() {
175 return keysEvicted;