Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / datastore / BaseDatastoreServiceImpl.java
blob8332e0d057dde2559bb25a2bc854d97db3aa1b11
1 // Copyright 2010 Google Inc. All Rights Reserved.
3 package com.google.appengine.api.datastore;
5 import static com.google.common.base.Preconditions.checkArgument;
7 import com.google.appengine.api.datastore.EntityCachingStrategy.NoOpEntityCachingStrategy;
8 import com.google.apphosting.api.ApiProxy;
9 import com.google.apphosting.datastore.DatastoreV3Pb;
11 import java.util.concurrent.Future;
12 import java.util.logging.Logger;
14 /**
15 * State and behavior that is common to both synchronous and asynchronous
16 * Datastore API implementations.
19 abstract class BaseDatastoreServiceImpl {
20 /**
21 * It doesn't actually matter what this value is, the back end will set its
22 * own deadline. All that matters is that we set a value.
24 static final long ARBITRARY_FAILOVER_READ_MS = -1;
26 /**
27 * User-provided config options.
29 protected final DatastoreServiceConfig datastoreServiceConfig;
31 /**
32 * Config that we'll pass to all api calls.
34 final ApiProxy.ApiConfig apiConfig;
36 /**
37 * Knows which transaction to use when the user does not explicitly provide
38 * one.
40 final TransactionStack defaultTxnProvider;
42 EntityCachingStrategy entityCachingStrategy;
44 final Logger logger = Logger.getLogger(getClass().getName());
46 BaseDatastoreServiceImpl(DatastoreServiceConfig datastoreServiceConfig,
47 TransactionStack defaultTxnProvider) {
48 this.datastoreServiceConfig = datastoreServiceConfig;
49 this.apiConfig = createApiConfig(datastoreServiceConfig);
50 this.defaultTxnProvider = defaultTxnProvider;
51 if (datastoreServiceConfig.getEntityCacheConfig() == null) {
52 entityCachingStrategy = NoOpEntityCachingStrategy.INSTANCE;
53 } else {
54 entityCachingStrategy = EntityCachingStrategy.createStrategy(datastoreServiceConfig);
58 private ApiProxy.ApiConfig createApiConfig(DatastoreServiceConfig config) {
59 ApiProxy.ApiConfig apiConfig = new ApiProxy.ApiConfig();
60 apiConfig.setDeadlineInSeconds(config.getDeadline());
61 return apiConfig;
64 @SuppressWarnings("deprecation")
65 static void validateQuery(Query query) {
66 checkArgument(query.getFilterPredicates().isEmpty() || query.getFilter() == null,
67 "A query cannot have both a filter and filter predicates set.");
68 checkArgument(query.getProjections().isEmpty() || !query.isKeysOnly(),
69 "A query cannot have both projections and keys-only set.");
72 /**
73 * Return the current transaction if one already exists, otherwise create
74 * a new transaction or throw an exception according to the
75 * {@link ImplicitTransactionManagementPolicy}.
77 GetOrCreateTransactionResult getOrCreateTransaction() {
78 Transaction currentTxn = getCurrentTransaction(null);
79 if (currentTxn != null) {
80 return new GetOrCreateTransactionResult(false, currentTxn);
83 switch(datastoreServiceConfig.getImplicitTransactionManagementPolicy()) {
84 case NONE:
85 return new GetOrCreateTransactionResult(false, null);
86 case AUTO:
87 return new GetOrCreateTransactionResult(true, beginTransactionInternal(
88 TransactionOptions.Builder.withDefaults(), false));
89 default:
90 final String msg = "Unexpected Transaction Creation Policy: " +
91 datastoreServiceConfig.getImplicitTransactionManagementPolicy();
92 logger.severe(msg);
93 throw new IllegalArgumentException(msg);
97 static DatastoreV3Pb.Transaction localTxnToRemoteTxn(Transaction local) {
98 DatastoreV3Pb.Transaction remote = new DatastoreV3Pb.Transaction();
99 remote.setApp(local.getApp());
100 remote.setHandle(Long.parseLong(local.getId()));
101 return remote;
104 Transaction beginTransactionInternal(TransactionOptions options, boolean isExplicit) {
105 DatastoreV3Pb.Transaction remoteTxn = new DatastoreV3Pb.Transaction();
106 DatastoreV3Pb.BeginTransactionRequest request = new DatastoreV3Pb.BeginTransactionRequest();
107 request.setApp(datastoreServiceConfig.getAppIdNamespace().getAppId());
108 request.setAllowMultipleEg(options.isXG());
110 Future<DatastoreV3Pb.Transaction> future =
111 DatastoreApiHelper.makeAsyncCall(apiConfig, "BeginTransaction", request, remoteTxn);
113 Transaction localTxn = new TransactionImpl(apiConfig, request.getApp(), future,
114 defaultTxnProvider, datastoreServiceConfig.getDatastoreCallbacks(), entityCachingStrategy,
115 isExplicit);
117 if (isExplicit) {
118 defaultTxnProvider.push(localTxn);
120 return localTxn;
123 public Transaction getCurrentTransaction() {
124 return defaultTxnProvider.peek();
127 public Transaction getCurrentTransaction(Transaction returnedIfNoTxn) {
128 return defaultTxnProvider.peek(returnedIfNoTxn);
131 DatastoreServiceConfig getDatastoreServiceConfig() {
132 return datastoreServiceConfig;