/src/com/google/appengine/datanucleus/DatastoreConnectionFactoryImpl.java

http://datanucleus-appengine.googlecode.com/ · Java · 230 lines · 130 code · 33 blank · 67 comment · 12 complexity · 32051aa6143ecce74a67aac689f0ddc7 MD5 · raw file

  1. /**********************************************************************
  2. Copyright (c) 2009 Google Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. **********************************************************************/
  13. package com.google.appengine.datanucleus;
  14. import com.google.appengine.api.datastore.DatastoreService;
  15. import com.google.appengine.api.datastore.DatastoreServiceConfig;
  16. import org.datanucleus.ExecutionContext;
  17. import org.datanucleus.PersistenceConfiguration;
  18. import org.datanucleus.Transaction;
  19. import org.datanucleus.store.StoreManager;
  20. import org.datanucleus.store.connection.AbstractConnectionFactory;
  21. import org.datanucleus.store.connection.ManagedConnection;
  22. import org.datanucleus.store.connection.ManagedConnectionResourceListener;
  23. import org.datanucleus.util.NucleusLogger;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import java.util.Map;
  27. import javax.transaction.xa.XAResource;
  28. /**
  29. * Factory for connections to the datastore. There are two connection factories for a DatastoreManager.
  30. * <ul>
  31. * <li>Transactional : a connection (DatastoreService) is obtained at the start of the transaction and we
  32. * call "beginTransaction" on it. It is closed at the end of the transaction after we call "commit"/"rollback".</li>
  33. * <li>Nontransactional : a connection (DatastoreService) is obtained on the first operation, and is retained
  34. * until PM/EM.close(). All operations are atomic, since we don't call "beginTransaction", hence no need to call
  35. * "commit"/"rollback"</li>
  36. * </ul>
  37. *
  38. * <p>
  39. * By default, when the user invokes transaction.begin() in user-space this will start a DatastoreTransaction.
  40. * If they have the persistence property <i>datanucleus.appengine.autoCreateDatastoreTxns</i> set to false
  41. * then this means it will NOT start a transaction. Why anyone would want to do this is unknown to me
  42. * but anyway it's there.
  43. * </p>
  44. *
  45. * @author Max Ross <maxr@google.com>
  46. */
  47. public class DatastoreConnectionFactoryImpl extends AbstractConnectionFactory {
  48. public static final String AUTO_CREATE_TXNS_PROPERTY =
  49. "datanucleus.appengine.autoCreateDatastoreTxns";
  50. private final boolean isAutoCreateTransaction;
  51. /**
  52. * Constructs a connection factory for the datastore.
  53. * Provides ManagedConnections to communicate with the datastore.
  54. *
  55. * @param storeMgr The store manager
  56. * @param resourceType Name of the resource ("appengine", "appengine-nontx")
  57. */
  58. public DatastoreConnectionFactoryImpl(StoreManager storeMgr, String resourceType) {
  59. super(storeMgr, resourceType);
  60. PersistenceConfiguration conf = storeMgr.getNucleusContext().getPersistenceConfiguration();
  61. if (conf.getProperty(DatastoreConnectionFactoryImpl.AUTO_CREATE_TXNS_PROPERTY) == null) {
  62. // User hasn't configured the "auto-create" property, so set it
  63. conf.setProperty(DatastoreConnectionFactoryImpl.AUTO_CREATE_TXNS_PROPERTY, Boolean.TRUE.toString());
  64. }
  65. this.isAutoCreateTransaction = conf.getBooleanProperty(AUTO_CREATE_TXNS_PROPERTY);
  66. }
  67. public void close() {}
  68. /**
  69. * {@inheritDoc}
  70. */
  71. public ManagedConnection getConnection(ExecutionContext ec, Transaction txn, Map options) {
  72. return storeMgr.getConnectionManager().allocateConnection(this, ec, txn, options);
  73. }
  74. /**
  75. * {@inheritDoc}
  76. */
  77. public ManagedConnection createManagedConnection(ExecutionContext ec, Map transactionOptions) {
  78. return new DatastoreManagedConnection(storeMgr, isAutoCreateTransaction());
  79. }
  80. boolean isAutoCreateTransaction() {
  81. return isAutoCreateTransaction;
  82. }
  83. // TODO Change this to extend AbstractManagedConnection
  84. static class DatastoreManagedConnection implements ManagedConnection {
  85. private boolean managed = false;
  86. private boolean locked = false;
  87. private final List<ManagedConnectionResourceListener> listeners =
  88. new ArrayList<ManagedConnectionResourceListener>();
  89. private final XAResource datastoreXAResource;
  90. DatastoreManagedConnection(StoreManager storeMgr, boolean autoCreateTransaction) {
  91. DatastoreManager datastoreManager = (DatastoreManager) storeMgr;
  92. DatastoreServiceConfig config = datastoreManager.getDefaultDatastoreServiceConfigForWrites();
  93. DatastoreService datastoreService = DatastoreServiceFactoryInternal.getDatastoreService(config);
  94. if (NucleusLogger.CONNECTION.isDebugEnabled()) {
  95. if (datastoreService instanceof WrappedDatastoreService) {
  96. NucleusLogger.CONNECTION.debug("Created ManagedConnection using DatastoreService = " +
  97. ((WrappedDatastoreService)datastoreService).getDelegate());
  98. } else {
  99. NucleusLogger.CONNECTION.debug("Created ManagedConnection using DatastoreService = " + datastoreService);
  100. }
  101. }
  102. if (autoCreateTransaction) {
  103. datastoreXAResource = new DatastoreXAResource(
  104. datastoreService, datastoreManager.getDefaultDatastoreTransactionOptions());
  105. } else {
  106. datastoreXAResource = new EmulatedXAResource(datastoreService);
  107. }
  108. }
  109. /* (non-Javadoc)
  110. * @see org.datanucleus.store.connection.ManagedConnection#closeAfterTransactionEnd()
  111. */
  112. @Override
  113. public boolean closeAfterTransactionEnd() {
  114. return true;
  115. }
  116. /* (non-Javadoc)
  117. * @see org.datanucleus.store.connection.ManagedConnection#closeOnRelease()
  118. */
  119. @Override
  120. public boolean closeOnRelease() {
  121. return false;
  122. }
  123. /* (non-Javadoc)
  124. * @see org.datanucleus.store.connection.ManagedConnection#commitOnRelease()
  125. */
  126. @Override
  127. public boolean commitOnRelease() {
  128. return false;
  129. }
  130. /* (non-Javadoc)
  131. * @see org.datanucleus.store.connection.ManagedConnection#setCloseOnRelease(boolean)
  132. */
  133. @Override
  134. public void setCloseOnRelease(boolean flag) {
  135. }
  136. /* (non-Javadoc)
  137. * @see org.datanucleus.store.connection.ManagedConnection#setCommitOnRelease(boolean)
  138. */
  139. @Override
  140. public void setCommitOnRelease(boolean flag) {
  141. }
  142. public Object getConnection() {
  143. // Return the DatastoreService
  144. return ((EmulatedXAResource)datastoreXAResource).getDatastoreService();
  145. }
  146. public XAResource getXAResource() {
  147. return datastoreXAResource;
  148. }
  149. public void release() {
  150. if (!managed) {
  151. close();
  152. }
  153. }
  154. public void close() {
  155. // Take copy since listeners can de-register themselves at close
  156. List<ManagedConnectionResourceListener> resourceListeners = new ArrayList(listeners);
  157. for (ManagedConnectionResourceListener listener : resourceListeners) {
  158. listener.managedConnectionPreClose();
  159. }
  160. // nothing to actually close
  161. for (ManagedConnectionResourceListener listener : resourceListeners) {
  162. listener.managedConnectionPostClose();
  163. }
  164. }
  165. public void setManagedResource() {
  166. managed = true;
  167. }
  168. public boolean isLocked() {
  169. return locked;
  170. }
  171. public void lock() {
  172. locked = true;
  173. }
  174. public void unlock() {
  175. locked = false;
  176. }
  177. public void transactionFlushed() {
  178. for (ManagedConnectionResourceListener listener : listeners) {
  179. listener.transactionFlushed();
  180. }
  181. }
  182. public void transactionPreClose() {
  183. for (ManagedConnectionResourceListener listener : listeners) {
  184. listener.transactionPreClose();
  185. }
  186. }
  187. public void addListener(ManagedConnectionResourceListener listener) {
  188. listeners.add(listener);
  189. }
  190. public void removeListener(ManagedConnectionResourceListener listener) {
  191. listeners.remove(listener);
  192. }
  193. }
  194. }