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
;
20 import java
.util
.concurrent
.Future
;
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
) {
42 this.datastoreServiceConfig
= datastoreServiceConfig
;
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());
54 cacheGetResults
= cache
.getIdentifiableAsync(cacheableKeys
);
56 return new CacheOnlyPreGetCachingResult(Sets
.newHashSet(cacheableKeys
), cacheGetResults
);
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()));
74 public PreMutationCachingResult
prePut(CurrentTransactionProvider currentTxnProvider
,
75 List
<Entity
> entitiesToPut
) {
76 if (currentTxnProvider
.getCurrentTransaction(null) == null) {
77 return preCommit(entitiesToPut
, ImmutableList
.<Key
>of());
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
;
92 public PreMutationCachingResult
preDelete(CurrentTransactionProvider currentTxnProvider
,
93 List
<Key
> keysToDelete
) {
94 if (currentTxnProvider
.getCurrentTransaction(null) == null) {
95 return preCommit(ImmutableList
.<Entity
>of(), keysToDelete
);
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
;
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
);
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() {
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() {
174 public Future
<Set
<Key
>> getKeysEvicted() {