/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
- /**********************************************************************
- Copyright (c) 2009 Google Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- **********************************************************************/
- package com.google.appengine.datanucleus;
- import com.google.appengine.api.datastore.DatastoreService;
- import com.google.appengine.api.datastore.DatastoreServiceConfig;
- import org.datanucleus.ExecutionContext;
- import org.datanucleus.PersistenceConfiguration;
- import org.datanucleus.Transaction;
- import org.datanucleus.store.StoreManager;
- import org.datanucleus.store.connection.AbstractConnectionFactory;
- import org.datanucleus.store.connection.ManagedConnection;
- import org.datanucleus.store.connection.ManagedConnectionResourceListener;
- import org.datanucleus.util.NucleusLogger;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import javax.transaction.xa.XAResource;
- /**
- * Factory for connections to the datastore. There are two connection factories for a DatastoreManager.
- * <ul>
- * <li>Transactional : a connection (DatastoreService) is obtained at the start of the transaction and we
- * call "beginTransaction" on it. It is closed at the end of the transaction after we call "commit"/"rollback".</li>
- * <li>Nontransactional : a connection (DatastoreService) is obtained on the first operation, and is retained
- * until PM/EM.close(). All operations are atomic, since we don't call "beginTransaction", hence no need to call
- * "commit"/"rollback"</li>
- * </ul>
- *
- * <p>
- * By default, when the user invokes transaction.begin() in user-space this will start a DatastoreTransaction.
- * If they have the persistence property <i>datanucleus.appengine.autoCreateDatastoreTxns</i> set to false
- * then this means it will NOT start a transaction. Why anyone would want to do this is unknown to me
- * but anyway it's there.
- * </p>
- *
- * @author Max Ross <maxr@google.com>
- */
- public class DatastoreConnectionFactoryImpl extends AbstractConnectionFactory {
- public static final String AUTO_CREATE_TXNS_PROPERTY =
- "datanucleus.appengine.autoCreateDatastoreTxns";
- private final boolean isAutoCreateTransaction;
- /**
- * Constructs a connection factory for the datastore.
- * Provides ManagedConnections to communicate with the datastore.
- *
- * @param storeMgr The store manager
- * @param resourceType Name of the resource ("appengine", "appengine-nontx")
- */
- public DatastoreConnectionFactoryImpl(StoreManager storeMgr, String resourceType) {
- super(storeMgr, resourceType);
- PersistenceConfiguration conf = storeMgr.getNucleusContext().getPersistenceConfiguration();
- if (conf.getProperty(DatastoreConnectionFactoryImpl.AUTO_CREATE_TXNS_PROPERTY) == null) {
- // User hasn't configured the "auto-create" property, so set it
- conf.setProperty(DatastoreConnectionFactoryImpl.AUTO_CREATE_TXNS_PROPERTY, Boolean.TRUE.toString());
- }
- this.isAutoCreateTransaction = conf.getBooleanProperty(AUTO_CREATE_TXNS_PROPERTY);
- }
- public void close() {}
- /**
- * {@inheritDoc}
- */
- public ManagedConnection getConnection(ExecutionContext ec, Transaction txn, Map options) {
- return storeMgr.getConnectionManager().allocateConnection(this, ec, txn, options);
- }
- /**
- * {@inheritDoc}
- */
- public ManagedConnection createManagedConnection(ExecutionContext ec, Map transactionOptions) {
- return new DatastoreManagedConnection(storeMgr, isAutoCreateTransaction());
- }
- boolean isAutoCreateTransaction() {
- return isAutoCreateTransaction;
- }
- // TODO Change this to extend AbstractManagedConnection
- static class DatastoreManagedConnection implements ManagedConnection {
- private boolean managed = false;
- private boolean locked = false;
- private final List<ManagedConnectionResourceListener> listeners =
- new ArrayList<ManagedConnectionResourceListener>();
- private final XAResource datastoreXAResource;
- DatastoreManagedConnection(StoreManager storeMgr, boolean autoCreateTransaction) {
- DatastoreManager datastoreManager = (DatastoreManager) storeMgr;
- DatastoreServiceConfig config = datastoreManager.getDefaultDatastoreServiceConfigForWrites();
- DatastoreService datastoreService = DatastoreServiceFactoryInternal.getDatastoreService(config);
- if (NucleusLogger.CONNECTION.isDebugEnabled()) {
- if (datastoreService instanceof WrappedDatastoreService) {
- NucleusLogger.CONNECTION.debug("Created ManagedConnection using DatastoreService = " +
- ((WrappedDatastoreService)datastoreService).getDelegate());
- } else {
- NucleusLogger.CONNECTION.debug("Created ManagedConnection using DatastoreService = " + datastoreService);
- }
- }
- if (autoCreateTransaction) {
- datastoreXAResource = new DatastoreXAResource(
- datastoreService, datastoreManager.getDefaultDatastoreTransactionOptions());
- } else {
- datastoreXAResource = new EmulatedXAResource(datastoreService);
- }
- }
- /* (non-Javadoc)
- * @see org.datanucleus.store.connection.ManagedConnection#closeAfterTransactionEnd()
- */
- @Override
- public boolean closeAfterTransactionEnd() {
- return true;
- }
- /* (non-Javadoc)
- * @see org.datanucleus.store.connection.ManagedConnection#closeOnRelease()
- */
- @Override
- public boolean closeOnRelease() {
- return false;
- }
- /* (non-Javadoc)
- * @see org.datanucleus.store.connection.ManagedConnection#commitOnRelease()
- */
- @Override
- public boolean commitOnRelease() {
- return false;
- }
- /* (non-Javadoc)
- * @see org.datanucleus.store.connection.ManagedConnection#setCloseOnRelease(boolean)
- */
- @Override
- public void setCloseOnRelease(boolean flag) {
- }
- /* (non-Javadoc)
- * @see org.datanucleus.store.connection.ManagedConnection#setCommitOnRelease(boolean)
- */
- @Override
- public void setCommitOnRelease(boolean flag) {
- }
- public Object getConnection() {
- // Return the DatastoreService
- return ((EmulatedXAResource)datastoreXAResource).getDatastoreService();
- }
- public XAResource getXAResource() {
- return datastoreXAResource;
- }
- public void release() {
- if (!managed) {
- close();
- }
- }
- public void close() {
- // Take copy since listeners can de-register themselves at close
- List<ManagedConnectionResourceListener> resourceListeners = new ArrayList(listeners);
- for (ManagedConnectionResourceListener listener : resourceListeners) {
- listener.managedConnectionPreClose();
- }
- // nothing to actually close
- for (ManagedConnectionResourceListener listener : resourceListeners) {
- listener.managedConnectionPostClose();
- }
- }
- public void setManagedResource() {
- managed = true;
- }
- public boolean isLocked() {
- return locked;
- }
- public void lock() {
- locked = true;
- }
- public void unlock() {
- locked = false;
- }
- public void transactionFlushed() {
- for (ManagedConnectionResourceListener listener : listeners) {
- listener.transactionFlushed();
- }
- }
- public void transactionPreClose() {
- for (ManagedConnectionResourceListener listener : listeners) {
- listener.transactionPreClose();
- }
- }
- public void addListener(ManagedConnectionResourceListener listener) {
- listeners.add(listener);
- }
- public void removeListener(ManagedConnectionResourceListener listener) {
- listeners.remove(listener);
- }
- }
- }