Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/SliceStoreManager.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/SliceStoreManager.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/SliceStoreManager.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/SliceStoreManager.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.openjpa.slice.jdbc; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.DataSource; +import javax.sql.XAConnection; +import javax.sql.XADataSource; + +import org.apache.openjpa.jdbc.kernel.JDBCStoreManager; +import org.apache.openjpa.lib.jdbc.DelegatingDataSource; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.slice.Slice; +import org.apache.openjpa.util.InternalException; + +/** + * A specialized JDBCStoreManager for XA-complaint DataSource. + * If the configured DataSource is not XA-complaint, behaves as the super + * implementation. + * + * @author Pinaki Poddar + * + */ +public class SliceStoreManager extends JDBCStoreManager { + private final Slice _slice; + private Boolean isXAEnabled; + private XAConnection xcon; + + private static final Localizer _loc = + Localizer.forPackage(SliceStoreManager.class); + + /** + * Construct with immutable logical name of the slice. + */ + public SliceStoreManager(Slice slice) { + _slice = slice; + } + + /** + * Gets the slice for which this receiver is working. + */ + public Slice getSlice() { + return _slice; + } + + public String getName() { + return _slice.getName(); + } + + /** + * Gets the connection via XAConnection if the datasource is XA-complaint. + * Otherwise, behaves exactly as the super implementation. + */ + @Override + protected RefCountConnection connectInternal() throws SQLException { + if (!isXAEnabled) + return super.connectInternal(); + XADataSource xds = getXADataSource(); + xcon = xds.getXAConnection(); + Connection con = xcon.getConnection(); + return new RefCountConnection(con); + } + + /** + * Gets the XAConnection if connected and XA-complaint. Otherwise null. + */ + public XAConnection getXAConnection() { + return xcon; + } + + private XADataSource getXADataSource() { + if (!isXAEnabled()) + throw new InternalException(_loc.get("slice-not-xa", this)); + return (XADataSource)getInnerDataSource(); + } + + /** + * Affirms if the configured DataSource is XA-complaint. + * Can return null if the context has not been set yet. + */ + public boolean isXAEnabled() { + if (isXAEnabled == null) { + isXAEnabled = getInnerDataSource() instanceof XADataSource; + } + return isXAEnabled.booleanValue(); + } + + private DataSource getInnerDataSource() { + DataSource parent = super.getDataSource(); + DataSource real = (parent instanceof DelegatingDataSource) ? + ((DelegatingDataSource)parent).getInnermostDelegate() + : parent; + return real; + } +}
Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/UniqueResultObjectProvider.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/UniqueResultObjectProvider.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/UniqueResultObjectProvider.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/UniqueResultObjectProvider.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,148 @@ +package org.apache.openjpa.slice.jdbc; + +import org.apache.openjpa.kernel.StoreQuery; +import org.apache.openjpa.kernel.exps.QueryExpressions; +import org.apache.openjpa.kernel.exps.Value; +import org.apache.openjpa.lib.rop.ResultObjectProvider; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.util.InternalException; +import org.apache.openjpa.util.UserException; + +/** + * Aggregates individual single query results from different databases. + * + * @author Pinaki Poddar + * + */ +public class UniqueResultObjectProvider implements ResultObjectProvider { + private final ResultObjectProvider[] _rops; + private final StoreQuery _query; + private final QueryExpressions[] _exps; + private Object _single; + private boolean _opened; + + private static final String COUNT = "Count"; + private static final String MAX = "Max"; + private static final String MIN = "Min"; + private static final String SUM = "Sum"; + + private static final Localizer _loc = + Localizer.forPackage(UniqueResultObjectProvider.class); + + public UniqueResultObjectProvider(ResultObjectProvider[] rops, + StoreQuery q, QueryExpressions[] exps) { + _rops = rops; + _query = q; + _exps = exps; + } + + public boolean absolute(int pos) throws Exception { + return false; + } + + public void close() throws Exception { + _opened = false; + for (ResultObjectProvider rop:_rops) + rop.close(); + } + + public Object getResultObject() throws Exception { + if (!_opened) + throw new InternalException(_loc.get("not-open")); + return _single; + } + + public void handleCheckedException(Exception e) { + _rops[0].handleCheckedException(e); + } + + public boolean next() throws Exception { + if (!_opened) { + open(); + } + + if (_single != null) + return false; + + Value[] values = _exps[0].projections; + Object[] single = new Object[values.length]; + for (int i=0; i<values.length; i++) { + Value v = values[i]; + boolean isAggregate = v.isAggregate(); + String op = v.getClass().getSimpleName(); + for (ResultObjectProvider rop:_rops) { + rop.next(); + Object[] row = (Object[]) rop.getResultObject(); + if (isAggregate) { + if (COUNT.equals(op)) { + single[i] = count(single[i], row[i]); + } else if (MAX.equals(op)) { + single[i] = max(single[i], row[i]); + } else if (MIN.equals(op)) { + single[i] = min(single[i], row[i]); + } else if (SUM.equals(op)) { + single[i] = sum(single[i], row[i]); + } else { + throw new UnsupportedOperationException + (_loc.get("aggregate-unsupported", op).toString()); + } + } else { + single[i] = row[i]; + } + } + } + _single = single; + return true; + } + + Object count(Object current, Object other) { + if (current == null) + return other; + return ((Number)current).longValue() + ((Number)other).longValue(); + } + + Object max(Object current, Object other) { + if (current == null) + return other; + + return Math.max(((Number)current).doubleValue(), + ((Number)other).doubleValue()); + } + + Object min(Object current, Object other) { + if (current == null) + return other; + return Math.min(((Number)current).doubleValue(), + ((Number)other).doubleValue()); + } + + Object sum(Object current, Object other) { + if (current == null) + return other; + return (((Number)current).doubleValue() + + ((Number)other).doubleValue()); + } + + + + public void open() throws Exception { + for (ResultObjectProvider rop:_rops) + rop.open(); + _opened = true; + } + + public void reset() throws Exception { + _single = null; + for (ResultObjectProvider rop : _rops) { + rop.reset(); + } + } + + public int size() throws Exception { + return 1; + } + + public boolean supportsRandomAccess() { + return false; + } +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/package.html URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/package.html?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/package.html (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/package.html Wed Feb 6 12:26:14 2008 @@ -0,0 +1,11 @@ +<HTML> +<BODY> +Implements Distributed version of JDBCStoreManager and JDBCStoreQuery. + +This package contains implementaions of OpenJPA interfaces using a distribution +template pattern. Distribution template pattern for <code>T</code> is +defined as a type <code>T'</code> +such that <code>T' extends T implements Iterable<T></code> i.e.<code>T'</code> +is a special <code>T</code> that also contains many <code>T</code>. +</BODY> +</HTML> \ No newline at end of file Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/package.html URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/package.html?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/package.html (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/package.html Wed Feb 6 12:26:14 2008 @@ -0,0 +1,8 @@ +<HTML> +<BODY> +Extended OpenJPA Interfaces for distributed databases. + +This package contains interface definitions for distribution policy and +distributed configuration. +</BODY> +</HTML> \ No newline at end of file Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedNaiveTransaction.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedNaiveTransaction.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedNaiveTransaction.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedNaiveTransaction.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,75 @@ +package org.apache.openjpa.slice.transaction; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.RollbackException; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; +import javax.transaction.xa.XAResource; + +import org.apache.openjpa.slice.jdbc.SliceStoreManager; + +public class DistributedNaiveTransaction implements Transaction { + private Set<SliceStoreManager> _slices = new HashSet<SliceStoreManager>(); + private Set<Synchronization> _syncs = new HashSet<Synchronization>(); + private final TransactionManager _tm; + private int _status; + private boolean _rollbackOnly; + + DistributedNaiveTransaction(TransactionManager tm) { + _tm = tm; + } + + public void commit() throws HeuristicMixedException, + HeuristicRollbackException, RollbackException, SecurityException, + SystemException { + throw new UnsupportedOperationException(); + } + + public boolean delistResource(XAResource arg0, int arg1) + throws IllegalStateException, SystemException { + return _slices.remove(arg0); + } + + public boolean enlistResource(XAResource arg0) + throws IllegalStateException, RollbackException, SystemException { + throw new UnsupportedOperationException(); + } + + public boolean enlistResource(SliceStoreManager arg0) + throws IllegalStateException, RollbackException, SystemException { + return _slices.add(arg0); + } + + public int getStatus() throws SystemException { + return _status; + } + + public void registerSynchronization(Synchronization arg0) + throws IllegalStateException, RollbackException, SystemException { + _syncs.add(arg0); + } + + public void rollback() throws IllegalStateException, SystemException { + _tm.rollback(); + } + + public void setRollbackOnly() throws IllegalStateException, SystemException { + _rollbackOnly = true; + } + + public boolean isRollbackOnly() { + return _rollbackOnly; + } + + Set<SliceStoreManager> getEnlistedResources() { + return Collections.unmodifiableSet(_slices); + } + +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedTransactionManager.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedTransactionManager.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedTransactionManager.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedTransactionManager.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.openjpa.slice.transaction; + +import static javax.transaction.xa.XAResource.TMJOIN; +import static javax.transaction.xa.XAResource.TMNOFLAGS; +import static javax.transaction.xa.XAResource.TMSUCCESS; + +import java.util.Set; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.InvalidTransactionException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; + +import org.apache.openjpa.lib.util.Localizer; + +/** + * A simple (naive?) implementation for distributed transaction across + * XA-complaint data sources. + * Assumes begin() and commit() being called on the same thread. + * + * @author Pinaki Poddar + * + */ +public class DistributedTransactionManager implements TransactionManager { + private final ThreadLocal<DistributedXATransaction> txns = + new ThreadLocal<DistributedXATransaction>(); + private static final Localizer _loc = + Localizer.forPackage(DistributedTransactionManager.class); + + public void begin() throws NotSupportedException, SystemException { + DistributedXATransaction txn = getTransaction(false); + int i = 1; + Set<XAResource> resources = txn.getEnlistedResources(); + for (XAResource resource : resources) { + try { + XAResource existing = isSame(resource, resources); + XID branch = txn.getXID().branch(i++); + int flag = (existing == null) ? TMNOFLAGS : TMJOIN; + resource.start(branch, flag); + } catch (Exception e) { + throw new SystemException(e.toString()); + } + } + } + + public void commit() throws HeuristicMixedException, + HeuristicRollbackException, IllegalStateException, + RollbackException, SecurityException, SystemException { + DistributedXATransaction txn = getTransaction(true); + Set<XAResource> resources = txn.getEnlistedResources(); + int branchId = 1; + boolean nextPhase = true; + for (XAResource resource : resources) { + XID branch = txn.getXID().branch(branchId++); + try { + resource.end(branch, TMSUCCESS); + resource.prepare(branch); + } catch (XAException e) { + nextPhase = false; + } + } + + branchId = 1; // reset + if (!nextPhase) { + for (XAResource resource : resources) { + try { + XID branch = txn.getXID().branch(branchId++); + resource.forget(branch); + } catch (XAException e) { + // ignore + } + throw new SystemException(_loc.get("prepare-failed") + .getMessage()); + } + } + + branchId = 1; // reset + for (XAResource resource : resources) { + XID branch = txn.getXID().branch(branchId++); + try { + resource.commit(branch, false); + } catch (XAException e) { + throw new SystemException(e.getMessage()); + } + } + } + + public int getStatus() throws SystemException { + return getTransaction().getStatus(); + } + + public Transaction getTransaction() throws SystemException { + return getTransaction(false); + } + + public void resume(Transaction arg0) throws IllegalStateException, + InvalidTransactionException, SystemException { + throw new UnsupportedOperationException(); + } + + public void rollback() throws IllegalStateException, SecurityException, + SystemException { + DistributedXATransaction txn = getTransaction(true); + Set<XAResource> slices = txn.getEnlistedResources(); + int branchId = 1; + for (XAResource slice : slices) { + XID branch = txn.getXID().branch(branchId++); + try { + slice.end(branch, XAResource.TMFAIL); + slice.rollback(branch); + } catch (XAException e) { + } + } + } + + public void setRollbackOnly() throws IllegalStateException, SystemException { + getTransaction().setRollbackOnly(); + } + + public void setTransactionTimeout(int arg0) throws SystemException { + throw new UnsupportedOperationException(); + } + + public Transaction suspend() throws SystemException { + throw new UnsupportedOperationException(); + } + + XAResource isSame(XAResource rm, Set<XAResource> others) { + for (XAResource other : others) + try { + if (rm != other && other.isSameRM(rm)) + return other; + } catch (XAException e) { + e.printStackTrace(); + } + return null; + } + + String toString(Object o) { + return o.getClass().getSimpleName() + "@" + + Long.toHexString(System.identityHashCode(o)); + } + + /** + * Gets the transaction associated with the current thread. + * + * @param mustExist if true, a transaction must be associated with the + * current thread a priori. If false, the current thread has no associated + * transaction, a new transaction is created with a global identifier + * and associated with the current thread. + */ + DistributedXATransaction getTransaction(boolean mustExist) { + DistributedXATransaction txn = txns.get(); + if (txn == null) { + if (mustExist) + throw new IllegalStateException(_loc.get("no-txn-on-thread", + Thread.currentThread().getName()).getMessage()); + byte[] global = + Long.toHexString(System.currentTimeMillis()).getBytes(); + XID xid = new XID(0, global, new byte[] { 0x1 }); + txn = new DistributedXATransaction(xid, this); + txns.set(txn); + } + return txn; + } + +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedXATransaction.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedXATransaction.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedXATransaction.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/DistributedXATransaction.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,82 @@ +package org.apache.openjpa.slice.transaction; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.RollbackException; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; +import javax.transaction.xa.XAResource; + +/** + * Internal implementation of a Transaction with an internal global transaction + * identifier scheme. + * + * @author Pinaki Poddar + * + */ +class DistributedXATransaction implements Transaction { + private static ThreadLocal<Transaction> _trans = new ThreadLocal<Transaction>(); + private Set<XAResource> _slices = new HashSet<XAResource>(); + private Set<Synchronization> _syncs = new HashSet<Synchronization>(); + private final TransactionManager _tm; + private final XID xid; + private int _status; + private boolean _rollbackOnly; + + /** + * Construct with + * @param xid + * @param tm + */ + DistributedXATransaction(XID xid, TransactionManager tm) { + this.xid = xid; + this._tm = tm; + } + + public XID getXID() { + return xid; + } + + public void commit() throws HeuristicMixedException, + HeuristicRollbackException, RollbackException, SecurityException, + SystemException { + _tm.commit(); + } + + public boolean delistResource(XAResource arg0, int arg1) + throws IllegalStateException, SystemException { + return _slices.remove(arg0); + } + + public boolean enlistResource(XAResource arg0) + throws IllegalStateException, RollbackException, SystemException { + return _slices.add(arg0); + } + + public int getStatus() throws SystemException { + return _status; + } + + public void registerSynchronization(Synchronization arg0) + throws IllegalStateException, RollbackException, SystemException { + _syncs.add(arg0); + } + + public void rollback() throws IllegalStateException, SystemException { + _tm.rollback(); + } + + public void setRollbackOnly() throws IllegalStateException, SystemException { + _rollbackOnly = true; + } + + Set<XAResource> getEnlistedResources() { + return Collections.unmodifiableSet(_slices); + } +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/NaiveTransactionManager.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/NaiveTransactionManager.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/NaiveTransactionManager.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/NaiveTransactionManager.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,96 @@ +package org.apache.openjpa.slice.transaction; + +import java.util.Set; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.InvalidTransactionException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.slice.jdbc.SliceStoreManager; + +/** + * A fake transaction manager which runs a serial commit or rollback across + * the enlisted non-XA resources without any two-phase commit protocol. + * + * @author Pinaki Poddar + * + */ +public class NaiveTransactionManager implements TransactionManager { + private final ThreadLocal<DistributedNaiveTransaction> _txns = + new ThreadLocal<DistributedNaiveTransaction>(); + private static final Localizer _loc = + Localizer.forPackage(NaiveTransactionManager.class); + + public void begin() throws NotSupportedException, SystemException { + DistributedNaiveTransaction txn = getTransaction(false); + Set<SliceStoreManager> slices = txn.getEnlistedResources(); + for (SliceStoreManager slice : slices) { + slice.getConnection(); + slice.begin(); + } + } + + public void commit() throws HeuristicMixedException, + HeuristicRollbackException, IllegalStateException, + RollbackException, SecurityException, SystemException { + DistributedNaiveTransaction txn = getTransaction(false); + Set<SliceStoreManager> slices = txn.getEnlistedResources(); + for (SliceStoreManager slice : slices) { + slice.commit(); + } + } + + public int getStatus() throws SystemException { + return getTransaction().getStatus(); + } + + public Transaction getTransaction() throws SystemException { + return getTransaction(false); + } + + public void resume(Transaction arg0) throws IllegalStateException, + InvalidTransactionException, SystemException { + throw new UnsupportedOperationException(); + } + + public void rollback() throws IllegalStateException, SecurityException, + SystemException { + DistributedNaiveTransaction txn = getTransaction(false); + Set<SliceStoreManager> slices = txn.getEnlistedResources(); + for (SliceStoreManager slice : slices) { + slice.commit(); + } + } + + public void setRollbackOnly() throws IllegalStateException, SystemException { + getTransaction().setRollbackOnly(); + } + + public void setTransactionTimeout(int arg0) throws SystemException { + throw new UnsupportedOperationException(); + } + + public Transaction suspend() throws SystemException { + throw new UnsupportedOperationException(); + } + + DistributedNaiveTransaction getTransaction(boolean mustExist) { + DistributedNaiveTransaction txn = _txns.get(); + if (txn == null) { + if (mustExist) + throw new IllegalStateException(_loc.get("no-txn-on-thread", + Thread.currentThread().getName()).getMessage()); + txn = new DistributedNaiveTransaction(this); + _txns.set(txn); + } + return txn; + } + + +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/XID.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/XID.java?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/XID.java (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/XID.java Wed Feb 6 12:26:14 2008 @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.openjpa.slice.transaction; + +import javax.transaction.xa.Xid; + +/** + * Internally used Global Transaction Identifier for two-phase distributed + * commit protocol. + * + * @author Pinaki Poddar + * + */ +class XID implements Xid { + private final int format; + private final byte[] global; + private final byte[] branch; + + public XID(int format, byte[] global, byte[] branch) { + super(); + this.format = format; + this.global = global; + this.branch = branch; + } + + public byte[] getBranchQualifier() { + return branch; + } + + public int getFormatId() { + return format; + } + + public byte[] getGlobalTransactionId() { + return global; + } + + XID branch(Number number) { + return branch((number == null) ? "null" : number.toString()); + } + + XID branch(String branch) { + return new XID(format, global, branch.getBytes()); + } + + public String toString() { + return new String(global) + ":" + new String(branch); + } + + public boolean equals(Object other) { + if (other instanceof XID) { + XID that = (XID) other; + return format == that.format && equals(global, that.global) + && equals(branch, that.branch); + } + return false; + } + + boolean equals(byte[] a, byte[] b) { + if (a == null && b == null) + return true; + if (a == null || b == null) + return false; + return new String(a).equals(new String(b)); + } + +} Added: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/package.html URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/package.html?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/package.html (added) +++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/transaction/package.html Wed Feb 6 12:26:14 2008 @@ -0,0 +1,10 @@ +<HTML> +<BODY> +Implements TransactionManager to manage transactions across the database +slices. This package provides two flavors of TransactionManager: one provides +two-phase commit protocol when all underlying database slices is XA-complaint; +while the other runs commit/rollback simply looping across all database slices +when one or more underlying database slices is not XA-complaint and hence does +not guarantee atomic nature of transaction. +</BODY> +</HTML> \ No newline at end of file Added: openjpa/trunk/openjpa-slice/src/main/resources/META-INF/services/org.apache.openjpa.lib.conf.ProductDerivation URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/resources/META-INF/services/org.apache.openjpa.lib.conf.ProductDerivation?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/resources/META-INF/services/org.apache.openjpa.lib.conf.ProductDerivation (added) +++ openjpa/trunk/openjpa-slice/src/main/resources/META-INF/services/org.apache.openjpa.lib.conf.ProductDerivation Wed Feb 6 12:26:14 2008 @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +org.apache.openjpa.slice.ProductDerivation \ No newline at end of file Added: openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/jdbc/localizer.properties URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/jdbc/localizer.properties?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/jdbc/localizer.properties (added) +++ openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/jdbc/localizer.properties Wed Feb 6 12:26:14 2008 @@ -0,0 +1,49 @@ +slice-not-found: No slice named "{0}" can be found. Available slices are "{1}" +slice-no-url: Slice "{0}" has no database URL. Specify a valid database URL \ + as the value of "slice.{0}.ConnectionURL" property. ConnectionURL is the \ + only mandatory property of a slice. If any other slice property \ + is not specified, then the corresponding openjpa.* property value is used \ + as default. +slice-none-configured: No slice has been configured. Specify slice.XYZ as \ + property name to register a slice named XYZ. +slice-configuration: Slice "{0}" configured with "{1}" +slice-available: Detected slices "{0}" in configuration. +no-url: No ConnectionURL property has been specified. +wrong-url: URL "{0}" is invalid as database URL. +wrong-slice: Wrong slice "{0}" for "{1}" +slice-connect: Connecting to slice "{0}" at URL "{1}" +slice-connect-warn: Failed to connect to slice "{0}". Slice "{0}" will be \ + ignored as configuration is set as lenient. +slice-connect-known-warn: Failed to connect to due to "{2}. \ + Slice "{0}" will be ignored as configuration is set as lenient. +slice-connect-error: Failed to connect to URL "{1}" +slice-connect-known-error: Failed to connect to URL "{1} due to {2} +bad-policy-slice:Distribution policy "{0}" has returned invalid slice \ + "{1}" for "{2}". The valid slices are {3}. This error may happen \ + when one or more of the originally configured slices are unavailable \ + and Lenient property is set to true. +slice-xa-enabled: All slices "{0}" is XA-complaint and hence store transaction \ + will use a two-phase commit protocol even if the persistent unit is \ + configured for non-JTA transaction. +slice-xa-disabled: Not all active slices "{0}" is XA-complaint and hence store \ + transaction will not use a two-phase commit protocol. If persistent unit \ + is configured for JTA transaction then the slices will participate in \ + global transaction but otherwise the atomic nature of commit across all \ + slices is not guaranteed. +two-phase: "{3}".{0}"(xid=[{4}]] Connection={1} XAConnection={2} +factory-init: Starting {0} +config-init: Configuring Slice {0} +no-slice-names: Slice identifiers are not listed in [slice.Names] property. \ + The configuration will be scanned to determine slice identifiers. +no-master-slice: No master slice has been configured explicitly in \ + [slice.Master] property. The first slice "{0}" in the list of configured \ + slices will be used as master. +resource-xa-tm-not-2pc: All slices is using XA-complaint driver but the \ + configured "{0}" transaction manager is not capable of enlisting XA-aware \ + resources. See slice.TransactionManager property documentation to \ + configure XA-aware Transaction Manager capable for two-phase commit. +resource-not-xa-tm-2pc: One or more slices is not using XA-complaint driver \ + but the configured "{0}" transaction manager can only enlist XA-aware \ + resource. +not-open: The underlying result sets are not open. +aggregate-unsupported: The query uses unsupported aggregate operation "{0}". Added: openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/localizer.properties URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/localizer.properties?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/localizer.properties (added) +++ openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/localizer.properties Wed Feb 6 12:26:14 2008 @@ -0,0 +1,4 @@ +bad-policy-slice:Distribution policy "{0}" has returned invalid slice \ + "{1}" for "{2}". The valid slices are {3}. This error may happen \ + when one or more of the originally configured slices are unavailable \ + and Lenient property is set to true. \ No newline at end of file Added: openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/transaction/localizer.properties URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/transaction/localizer.properties?rev=619145&view=auto ============================================================================== --- openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/transaction/localizer.properties (added) +++ openjpa/trunk/openjpa-slice/src/main/resources/org/apache/openjpa/slice/transaction/localizer.properties Wed Feb 6 12:26:14 2008 @@ -0,0 +1,3 @@ +no-txn-on-thread: No transaction is associated with current thread "{0}" +prepare-failed: one or more XA-complaint resources have failed to prepare for \ + commit during the first phase of a two-phase commit protocol. \ No newline at end of file Modified: openjpa/trunk/pom.xml URL: http://svn.apache.org/viewvc/openjpa/trunk/pom.xml?rev=619145&r1=619144&r2=619145&view=diff ============================================================================== --- openjpa/trunk/pom.xml (original) +++ openjpa/trunk/pom.xml Wed Feb 6 12:26:14 2008 @@ -84,7 +84,8 @@ <module>openjpa-lib</module> <module>openjpa-kernel</module> <module>openjpa-jdbc</module> - <module>openjpa-xmlstore</module> + <module>openjpa-xmlstore</module> + <module>openjpa-slice</module> <module>openjpa-all</module> <module>openjpa-project</module> <module>openjpa-integration</module> @@ -100,7 +101,8 @@ <module>openjpa-persistence</module> <module>openjpa-persistence-jdbc</module> <module>openjpa-kernel-5</module> - <module>openjpa-jdbc-5</module> + <module>openjpa-jdbc-5</module> + <module>openjpa-slice</module> <module>openjpa-examples</module> </modules> </profile>
