Fix to work with tests. Cleanup.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/edab900a Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/edab900a Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/edab900a Branch: refs/heads/master Commit: edab900abf7fc05d7ffc8e9fcb7b41d1b1647625 Parents: d6770ea Author: Andy Seaborne <[email protected]> Authored: Sun Dec 31 20:49:18 2017 +0000 Committer: Andy Seaborne <[email protected]> Committed: Tue Jan 2 15:58:30 2018 +0000 ---------------------------------------------------------------------- .../java/org/apache/jena/query/Dataset.java | 7 - .../java/org/apache/jena/query/TxnType.java | 21 +- .../jena/sparql/core/DatasetGraphMap.java | 18 +- .../jena/sparql/core/DatasetGraphMapLink.java | 17 +- .../jena/sparql/core/DatasetGraphOne.java | 18 +- .../jena/sparql/core/DatasetGraphSink.java | 5 +- .../jena/sparql/core/DatasetGraphWithLock.java | 3 + .../jena/sparql/core/DatasetGraphZero.java | 8 +- .../apache/jena/sparql/core/DatasetImpl.java | 36 +- .../apache/jena/sparql/core/Transactional.java | 4 +- .../jena/sparql/core/TransactionalLock.java | 72 +- .../jena/sparql/core/TransactionalMutex.java | 75 --- .../sparql/core/TransactionalNotSupported.java | 32 +- .../core/TransactionalNotSupportedMixin.java | 17 +- .../jena/sparql/core/TransactionalNull.java | 55 +- .../sparql/core/mem/DatasetGraphInMemory.java | 41 +- .../java/org/apache/jena/system/TxnCounter.java | 191 ++++-- .../org/apache/jena/sparql/core/TS_Core.java | 1 - .../sparql/core/TestDatasetGraphWithLock.java | 30 - .../core/mem/TestDatasetGraphInMemoryLock.java | 4 +- .../transaction/AbstractTestTransPromote.java | 51 +- .../AbstractTestTransactionLifecycle.java | 187 ++++- .../jena/sparql/transaction/TS_Transaction.java | 2 - .../TestTransactionDSGWithLockNoAbort.java | 41 -- .../TestTransactionDSGWithLockWithAbort.java | 38 -- .../transaction/TestTransactionSupport.java | 6 +- .../java/org/apache/jena/atlas/lib/Lib.java | 11 + .../jena/dboe/transaction/txn/Transaction.java | 5 +- .../transaction/txn/TransactionCoordinator.java | 28 +- .../dboe/transaction/txn/TransactionalBase.java | 23 +- .../transaction/TestTransactionLifecycle.java | 179 ++++- .../transaction/TestTransactionLifecycle2.java | 8 +- .../apache/jena/fuseki/servlets/HttpAction.java | 2 +- .../jena/rdfconnection/RDFConnectionLocal.java | 26 +- .../rdfconnection/RDFConnectionModular.java | 27 +- .../jena/rdfconnection/RDFConnectionRemote.java | 71 +- .../apache/jena/sdb/store/DatasetGraphSDB.java | 25 +- .../org/apache/jena/tdb/StoreConnection.java | 8 +- .../apache/jena/tdb/store/DatasetGraphTDB.java | 18 +- .../jena/tdb/transaction/BlockMgrJournal.java | 2 +- .../transaction/DatasetGraphTransaction.java | 52 +- .../jena/tdb/transaction/DatasetGraphTxn.java | 7 + .../jena/tdb/transaction/Transaction.java | 9 +- .../tdb/transaction/TransactionManager.java | 92 ++- .../jena/tdb/extra/T_TDBWriteTransaction.java | 151 ----- .../jena/tdb/extra/T_TimeoutTDBPattern.java | 112 --- .../apache/jena/tdb/extra/T_TransSystem.java | 674 ------------------- .../tdb/extra/T_TransSystemMultiDatasets.java | 553 --------------- .../jena/tdb/extra/T_TxnDeadlockTest.java | 141 ---- .../tdb/store/AbstractStoreConnections.java | 30 +- .../AbstractTestObjectFileTrans.java | 2 +- .../AbstractTestObjectFileTransComplex.java | 2 +- .../tdb/transaction/AbstractTestTransSeq.java | 6 - .../tdb/transaction/TestTransPromoteTDB.java | 5 +- .../tdb/transaction/TestTransactionTDB.java | 3 +- 55 files changed, 943 insertions(+), 2309 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/query/Dataset.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/query/Dataset.java b/jena-arq/src/main/java/org/apache/jena/query/Dataset.java index 38b1c22..6f8bc0e 100644 --- a/jena-arq/src/main/java/org/apache/jena/query/Dataset.java +++ b/jena-arq/src/main/java/org/apache/jena/query/Dataset.java @@ -32,13 +32,6 @@ import org.apache.jena.sparql.util.Context ; public interface Dataset extends Transactional { - // TEMP - - @Override - public default void begin(TxnType type) { throw new UnsupportedOperationException("Dataset.begin(TxnType)"); } - - - /** Get the default graph as a Jena Model */ public Model getDefaultModel() ; http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/query/TxnType.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/query/TxnType.java b/jena-arq/src/main/java/org/apache/jena/query/TxnType.java index 3679414..39d5dc8 100644 --- a/jena-arq/src/main/java/org/apache/jena/query/TxnType.java +++ b/jena-arq/src/main/java/org/apache/jena/query/TxnType.java @@ -18,6 +18,8 @@ package org.apache.jena.query; +import java.util.Objects; + import org.apache.jena.sparql.JenaTransactionException; public enum TxnType { @@ -46,7 +48,7 @@ public enum TxnType { */ READ, WRITE, READ_PROMOTE, READ_COMMITTED_PROMOTE ; - + /** Convert a {@link ReadWrite} mode to {@code TxnType} */ public static TxnType convert(ReadWrite rw) { switch(rw) { case READ: return READ; @@ -54,11 +56,22 @@ public enum TxnType { default: throw new NullPointerException(); } } - public static ReadWrite convert(TxnType mode) { - switch(mode) { + /** Convert a {@code TxnType} mode to {@link ReadWrite} : "promote" not supported. */ + public static ReadWrite convert(TxnType txnType) { + Objects.requireNonNull(txnType); + switch(txnType) { case READ: return ReadWrite.READ; case WRITE: return ReadWrite.WRITE; - default: throw new JenaTransactionException("Incompatible mode: "+mode); + default: throw new JenaTransactionException("Incompatible mode: "+txnType); } } + /** + * Translate a {@code TxnType} to it's initial {@link ReadWrite} mode. + * {@code WRITE -> WRITE}, {@code READ* -> READ} regardless of promotion setting. + */ + public static ReadWrite initial(TxnType txnType) { + Objects.requireNonNull(txnType); + return (txnType == TxnType.WRITE) ? ReadWrite.WRITE : ReadWrite.READ; + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java index 24d3e04..d25aad1 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java @@ -30,6 +30,7 @@ import org.apache.jena.graph.Graph ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; import org.apache.jena.query.ReadWrite ; +import org.apache.jena.query.TxnType; import org.apache.jena.sparql.ARQException ; import org.apache.jena.sparql.core.DatasetGraphFactory.GraphMaker ; import org.apache.jena.sparql.graph.GraphUnionRead ; @@ -69,13 +70,18 @@ public class DatasetGraphMap extends DatasetGraphTriplesQuads // ---- private final Transactional txn = TransactionalLock.createMRSW() ; - @Override public void begin(ReadWrite mode) { txn.begin(mode) ; } - @Override public void commit() { txn.commit() ; } - @Override public void abort() { txn.abort() ; } - @Override public boolean isInTransaction() { return txn.isInTransaction() ; } + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } + @Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } - @Override public boolean supportsTransactions() { return true ; } - @Override public boolean supportsTransactionAbort() { return false ; } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + @Override public boolean supportsTransactions() { return true; } + @Override public boolean supportsTransactionAbort() { return false; } // ---- @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMapLink.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMapLink.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMapLink.java index 605778a..f429192 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMapLink.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMapLink.java @@ -25,6 +25,7 @@ import java.util.Map ; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.Node ; import org.apache.jena.query.ReadWrite ; +import org.apache.jena.query.TxnType; import org.apache.jena.sparql.SystemARQ ; import org.apache.jena.sparql.core.DatasetGraphFactory.GraphMaker ; import org.apache.jena.sparql.graph.GraphUnionRead ; @@ -119,7 +120,6 @@ public class DatasetGraphMapLink extends DatasetGraphCollection // ---- private final Transactional txn = TransactionalLock.createMRSW() ; - @Override public void begin(ReadWrite mode) { txn.begin(mode) ; } @Override public void commit() { @@ -127,11 +127,18 @@ public class DatasetGraphMapLink extends DatasetGraphCollection txn.commit() ; } - @Override public void abort() { txn.abort() ; } - @Override public boolean isInTransaction() { return txn.isInTransaction() ; } + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } + //@Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } - @Override public boolean supportsTransactions() { return true ; } - @Override public boolean supportsTransactionAbort() { return false ; } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + @Override public boolean supportsTransactions() { return true; } + @Override public boolean supportsTransactionAbort() { return false; } // ---- @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java index 8c487be..601789e 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java @@ -28,6 +28,7 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.query.ReadWrite; +import org.apache.jena.query.TxnType; /** DatasetGraph of a single graph as default graph. * <p> @@ -72,14 +73,17 @@ public class DatasetGraphOne extends DatasetGraphBaseFind { supportsAbort = false; } - @Override public void begin(ReadWrite mode) { txn.begin(mode) ; } - @Override public void commit() { txn.commit() ; } - @Override public void abort() { txn.abort() ; } - @Override public boolean isInTransaction() { return txn.isInTransaction() ; } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } - @Override public boolean supportsTransactions() { return true ; } - @Override public boolean supportsTransactionAbort() { return supportsAbort ; } - + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + @Override public boolean supportsTransactions() { return true; } + // Because there are never any changes, abort() means "finish". + @Override public boolean supportsTransactionAbort() { return true; } @Override public boolean containsGraph(Node graphNode) { if ( isDefaultGraph(graphNode) ) http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphSink.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphSink.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphSink.java index 64735d0..b8852a1 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphSink.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphSink.java @@ -24,6 +24,7 @@ import org.apache.jena.atlas.iterator.Iter; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.query.ReadWrite; +import org.apache.jena.query.TxnType; import org.apache.jena.sparql.graph.GraphSink; @@ -41,13 +42,15 @@ public class DatasetGraphSink extends DatasetGraphBaseFind { public DatasetGraphSink() {} private TransactionalNull txn = TransactionalNull.create(); + @Override public void begin(TxnType txnType) { txn.begin(txnType); } @Override public void begin(ReadWrite mode) { txn.begin(mode); } @Override public void commit() { txn.commit(); } @Override public void abort() { txn.abort(); } @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } @Override public boolean supportsTransactions() { return true; } - // Because there are never any changes, abort() means "finish". @Override public boolean supportsTransactionAbort() { return true; } @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWithLock.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWithLock.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWithLock.java index 86ae484..815414e 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWithLock.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWithLock.java @@ -31,7 +31,10 @@ import org.apache.jena.sparql.util.Context ; * behaviour, that is the application see transaction but they are not durable. * Only provides multiple-reader OR single-writer, and no write-transaction * abort. + * @deprecated Will be removed. */ +// NOT USED +@Deprecated public class DatasetGraphWithLock extends DatasetGraphTrackActive implements Sync { private final ThreadLocal<Boolean> writeTxn = ThreadLocal.withInitial(()->false) ; private final DatasetGraph dsg ; http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphZero.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphZero.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphZero.java index a5a813b..4ada686 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphZero.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphZero.java @@ -24,6 +24,7 @@ import org.apache.jena.atlas.iterator.Iter; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.query.ReadWrite; +import org.apache.jena.query.TxnType; import org.apache.jena.sparql.graph.GraphZero; /** An always empty {@link DatasetGraph}. @@ -40,14 +41,19 @@ public class DatasetGraphZero extends DatasetGraphBaseFind { public DatasetGraphZero() {} private TransactionalNull txn = TransactionalNull.create(); + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } @Override public void commit() { txn.commit(); } @Override public void abort() { txn.abort(); } @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } @Override public boolean supportsTransactions() { return true; } - // Because there are never any changes, abort() means "finish". @Override public boolean supportsTransactionAbort() { return true; } + @Override public Iterator<Node> listGraphNodes() { http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetImpl.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetImpl.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetImpl.java index 00e419a..dfb8262 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetImpl.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetImpl.java @@ -25,6 +25,7 @@ import org.apache.jena.graph.Node ; import org.apache.jena.graph.NodeFactory ; import org.apache.jena.query.Dataset ; import org.apache.jena.query.ReadWrite ; +import org.apache.jena.query.TxnType; import org.apache.jena.rdf.model.Model ; import org.apache.jena.rdf.model.ModelFactory ; import org.apache.jena.shared.Lock ; @@ -96,13 +97,15 @@ public class DatasetImpl implements Dataset } @Override - public boolean supportsTransactions() { - return dsg.supportsTransactions() ; + public void begin() { + checkTransactional(); + transactional.begin(); } @Override - public boolean supportsTransactionAbort() { - return dsg.supportsTransactionAbort() ; + public void begin(TxnType txnType) { + checkTransactional(); + transactional.begin(txnType); } @Override @@ -110,6 +113,31 @@ public class DatasetImpl implements Dataset checkTransactional(); transactional.begin(mode); } + + @Override + public boolean promote() { + return transactional.promote(); + } + + @Override + public ReadWrite transactionMode() { + return transactional.transactionMode(); + } + + @Override + public TxnType transactionType() { + return transactional.transactionType(); + } + + @Override + public boolean supportsTransactions() { + return true; + } + + @Override + public boolean supportsTransactionAbort() { + return false; + } /** Say whether a transaction is active */ @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/Transactional.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/Transactional.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/Transactional.java index 8425a18..08bc230 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/Transactional.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/Transactional.java @@ -130,8 +130,8 @@ public interface Transactional public void end() ; /** Return the current mode of the transaction - "read" or "write" */ - //public ReadWrite transactionMode(); - public default ReadWrite transactionMode() { throw new JenaTransactionException("Not implemented"); } + public ReadWrite transactionMode(); + //public default ReadWrite transactionMode() { throw new JenaTransactionException("Not implemented"); } /** Return the transaction type used in {@code begin(TxnType)}. */ //public TxnMode transactionMode(); http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalLock.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalLock.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalLock.java index ad2ad3c..14d04b8 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalLock.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalLock.java @@ -18,8 +18,7 @@ package org.apache.jena.sparql.core; -import java.util.Objects ; - +import org.apache.jena.atlas.lib.Lib; import org.apache.jena.query.ReadWrite ; import org.apache.jena.query.TxnType; import org.apache.jena.shared.Lock ; @@ -35,29 +34,40 @@ import org.apache.jena.sparql.JenaTransactionException ; * <pre> * private final Transactional txn = TransactionalLock.createMRSW() ; * {@literal @}Override public void begin(TxnType txnType) { txn.begin(txnType) ; } - * {@literal @}Override public void begin(ReadWrite mode) { txn.begin(mode) ; } - * {@literal @}Override public boolean promote() { return txn.promote() ; } - * {@literal @}Override public void commit() { txn.commit() ; } - * {@literal @}Override public void abort() { txn.abort() ; } - * {@literal @}Override public boolean isInTransaction() { return txn.isInTransaction() ; } + * {@literal @}Override public void begin() { txn.begin(); } + * {@literal @}Override public void begin(TxnType txnType) { txn.begin(txnType); } + * {@literal @}Override public void begin(ReadWrite mode) { txn.begin(mode); } + * {@literal @}Override public boolean promote() { return txn.promote(); } + * {@literal @}Override public void commit() { txn.commit(); } + * {@literal @}Override public void abort() { txn.abort(); } + * {@literal @}Override public boolean isInTransaction() { return txn.isInTransaction(); } * {@literal @}Override public void end() { txn.end(); } - * {@literal @}Override public boolean supportsTransactions() { return true ; } - * {@literal @}Override public boolean supportsTransactionAbort() { return false ; } + * {@literal @}Override public ReadWrite transactionMode() { return txn.transactionMode(); } + * {@literal @}Override public TxnType transactionType() { return txn.transactionType(); } + * {@literal @}Override public boolean supportsTransactions() { return true; } + * {@literal @}Override public boolean supportsTransactionAbort() { return true; } * </pre> */ public class TransactionalLock implements Transactional { /* - private final Transactional txn = TransactionalLock.createMRSW() ; - @Override public void begin(ReadWrite mode) { txn.begin(mode) ; } - @Override public void commit() { txn.commit() ; } - @Override public void abort() { txn.abort() ; } - @Override public boolean isInTransaction() { return txn.isInTransaction() ; } - @Override public void end() { txn.end(); } - @Override public boolean supportsTransactions() { return true ; } - @Override public boolean supportsTransactionAbort() { return false ; } + private final Transactional txn = TransactionalLock.createMRSW() ; + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } + @Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } + @Override public void end() { txn.end(); } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + @Override public boolean supportsTransactions() { return true; } + @Override public boolean supportsTransactionAbort() { return false; } */ - private final ThreadLocal<ReadWrite> txnMode = ThreadLocal.withInitial( ()->null ) ; + private ThreadLocal<Boolean> inTransaction = ThreadLocal.withInitial(() -> Boolean.FALSE); + private ThreadLocal<TxnType> txnType = ThreadLocal.withInitial(() -> null); + private ThreadLocal<ReadWrite> txnMode = ThreadLocal.withInitial(() -> null); private final Lock lock ; /** Create a Transactional using the given lock */ @@ -101,16 +111,24 @@ public class TransactionalLock implements Transactional { } ReadWrite readWrite = TxnType.convert(txnType); boolean isRead = readWrite.equals(ReadWrite.READ) ; - lock.enterCriticalSection(isRead) ; - txnMode.set(readWrite) ; + lock.enterCriticalSection(isRead); + txnMode.set(readWrite); + } + + @Override public ReadWrite transactionMode() { + return Lib.readThreadLocal(txnMode) ; } + @Override public TxnType transactionType() { + return Lib.readThreadLocal(txnType) ; + } + // Lock propmotion required (Ok for mutex) -// @Override -// public boolean promote() { -// return ??; -// } + @Override + public boolean promote() { + return false; + } @Override public void commit() { @@ -130,11 +148,7 @@ public class TransactionalLock implements Transactional { } public boolean isTransactionType(ReadWrite mode) { - return Objects.equals(mode, txnMode.get()) ; - } - - private ReadWrite getTransactionType(ReadWrite mode) { - return txnMode.get() ; + return Lib.readThreadLocal(txnMode) == mode; } @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMutex.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMutex.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMutex.java deleted file mode 100644 index 4f722c7..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMutex.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.jena.sparql.core; - -import org.apache.jena.query.ReadWrite ; -import org.apache.jena.query.TxnType; -import org.apache.jena.shared.Lock ; - -/** Transactional by mutual exclusion. */ -public class TransactionalMutex implements Transactional -{ - private final Lock lock; - private ThreadLocal<Boolean> isInTransaction = ThreadLocal.withInitial(()->false) ; - - private TransactionalMutex(Lock lock) { - this.lock = lock ; - } - - @Override - public void begin(ReadWrite readWrite) { - begin(TxnType.convert(readWrite)); - } - - @Override - public void begin(TxnType txnType) { - lock.enterCriticalSection(false); // Always take a write lock - i.e. exclusive. - isInTransaction.set(true); - } - - @Override - public boolean promote() { - return true; - } - - @Override - public void commit() { - end() ; - } - - @Override - public void abort() { - end() ; - } - - @Override - public boolean isInTransaction() { - return isInTransaction == null ? false : isInTransaction.get() ; - } - - @Override - public void end() { - if ( isInTransaction() ) { - isInTransaction.set(false); - lock.leaveCriticalSection(); - } - isInTransaction.remove(); - isInTransaction = null; - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupported.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupported.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupported.java index 287aabd..f2ef1a0 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupported.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupported.java @@ -39,15 +39,21 @@ public class TransactionalNotSupported implements Transactional // As an included component. /* private final Transactional txn = new TransactionalNotSupported() ; - @Override public void begin(TxnType txnType) { txn.begin(type) ; } - @Override public void begin(ReadWrite mode) { txn.begin(mode) ; } - @Override public boolean promote() { returntxn.promote() ; } - @Override public void commit() { txn.commit() ; } - @Override public void abort() { txn.abort() ; } - @Override public boolean isInTransaction() { return txn.isInTransaction() ; } + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } + @Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } @Override public void end() { txn.end(); } - @Override public boolean supportsTransactions() { return true ; } - @Override public boolean supportsTransactionAbort() { return false ; } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + + For DatasetGraphs: + + @Override public boolean supportsTransactions() { return true; } + @Override public boolean supportsTransactionAbort() { return false; } */ @Override @@ -76,6 +82,13 @@ public class TransactionalNotSupported implements Transactional @Override public boolean isInTransaction() { return false ; } + + @Override public ReadWrite transactionMode() + { throw new UnsupportedOperationException("Transactional.transactionMode") ; } + + @Override public TxnType transactionType() + { throw new UnsupportedOperationException("Transactional.transactionType") ; } + @Override public void end() @@ -85,9 +98,6 @@ public class TransactionalNotSupported implements Transactional return false ; } - /** Declare whether {@link #abort} is supported. - * This goes along with clearing up after exceptions inside application transaction code. - */ public boolean supportsTransactionAbort() { return false; } http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupportedMixin.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupportedMixin.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupportedMixin.java index 4a98044..98fd2e9 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupportedMixin.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNotSupportedMixin.java @@ -20,11 +20,9 @@ package org.apache.jena.sparql.core; import org.apache.jena.query.ReadWrite ; import org.apache.jena.query.TxnType; -import org.apache.jena.shared.LockMutex ; /** Mixin interface for the "un-Transactional" interface. - * Use with {@link LockMutex}. - * @see TransactionalNotSupportedMixin + * @see TransactionalNotSupported */ public interface TransactionalNotSupportedMixin extends Transactional { @@ -52,12 +50,19 @@ public interface TransactionalNotSupportedMixin extends Transactional { throw new UnsupportedOperationException("Transactional.abort") ; } @Override + public default void end() + { throw new UnsupportedOperationException("Transactional.end") ; } + + @Override public default boolean isInTransaction() { return false ; } + + @Override default public ReadWrite transactionMode() + { throw new UnsupportedOperationException("Transactional.transactionMode") ; } + + @Override default public TxnType transactionType() + { throw new UnsupportedOperationException("Transactional.transactionType") ; } - @Override - public default void end() - { throw new UnsupportedOperationException("Transactional.end") ; } public default boolean supportsTransactions() { return false ; } http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNull.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNull.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNull.java index 822b77d..4b5ecf8 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNull.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalNull.java @@ -28,25 +28,56 @@ import org.apache.jena.sparql.JenaTransactionException; * It does provide "abort". */ public class TransactionalNull implements Transactional { + /* + @Override public void begin() { txn.begin(); } + @Override public void begin(TxnType txnType) { txn.begin(txnType); } + @Override public void begin(ReadWrite mode) { txn.begin(mode); } + @Override public boolean promote() { return txn.promote(); } + @Override public void commit() { txn.commit(); } + @Override public void abort() { txn.abort(); } + @Override public boolean isInTransaction() { return txn.isInTransaction(); } + @Override public void end() { txn.end(); } + @Override public ReadWrite transactionMode() { return txn.transactionMode(); } + @Override public TxnType transactionType() { return txn.transactionType(); } + + For DatasetGraphs: + + @Override public boolean supportsTransactions() { return true; } + @Override public boolean supportsTransactionAbort() { return false; } + */ + public static TransactionalNull create() { return new TransactionalNull(); } private ThreadLocal<Boolean> inTransaction = ThreadLocal.withInitial(() -> Boolean.FALSE); + private ThreadLocal<TxnType> txnType = ThreadLocal.withInitial(() -> null); + private ThreadLocal<ReadWrite> txnMode = ThreadLocal.withInitial(() -> null); + @Override + public ReadWrite transactionMode() { + return txnMode.get(); + } + + @Override + public void begin(ReadWrite readWrite) { + begin(TxnType.convert(readWrite)); + } @Override public void begin(TxnType type) { if ( inTransaction.get() ) throw new JenaTransactionException("Already in transaction"); inTransaction.set(true); + txnType.set(type); + txnMode.set(TxnType.initial(type)); } @Override - public void begin(ReadWrite readWrite) { - begin(TxnType.convert(readWrite)); + public boolean promote() { + if ( ! inTransaction.get() ) + throw new JenaTransactionException("Not in transaction"); + txnMode.set(ReadWrite.WRITE); + return true; } - - @Override - public boolean promote() { return true; } @Override public void commit() { @@ -69,14 +100,16 @@ public class TransactionalNull implements Transactional { @Override public void end() { - inTransaction.set(false); + clearup(); } -// @Override -// public boolean promote() { -// return true; -// } - + private void clearup() { + inTransaction.set(false); + inTransaction.remove(); + txnType.set(null); + txnType.remove(); + } + public void remove() { inTransaction.remove(); } http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java index 1905d05..44dd8db 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java @@ -101,7 +101,7 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr return transactionType.get(); } - private void transactionType(final ReadWrite readWrite) { + private void transactionMode(final ReadWrite readWrite) { transactionMode.set(readWrite); } @@ -139,24 +139,21 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr public boolean supportsTransactionAbort() { return true; } @Override + public void begin(final ReadWrite readWrite) { + begin(TxnType.convert(readWrite)); + } + + @Override public void begin(TxnType txnType) { if (isInTransaction()) throw new JenaTransactionException("Transactions cannot be nested!"); transactionType.set(txnType); - ReadWrite initial = txnType.equals(TxnType.WRITE) ? WRITE : READ; - _begin(initial); + _begin(txnType, TxnType.initial(txnType)); } - @Override - public void begin(final ReadWrite readWrite) { - if (isInTransaction()) - throw new JenaTransactionException("Transactions cannot be nested!"); - transactionType.set(TxnType.convert(readWrite)); - _begin(readWrite) ; - } - - private void _begin(ReadWrite readWrite) { - startTransaction(readWrite); + private void _begin(TxnType txnType, ReadWrite readWrite) { + // Takes transactionLock + startTransaction(txnType, readWrite); withLock(systemLock, () ->{ quadsIndex().begin(readWrite); defaultGraph().begin(readWrite); @@ -165,9 +162,10 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr } /** Called transaction start code at most once per transaction. */ - private void startTransaction(ReadWrite mode) { + private void startTransaction(TxnType txnType, ReadWrite mode) { transactionLock.enterCriticalSection(mode.equals(ReadWrite.READ)); // get the dataset write lock, if needed. - transactionType(mode); + transactionType.set(txnType); + transactionMode(mode); isInTransaction(true); } @@ -193,7 +191,7 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr case WRITE : return true; case READ : - return false ; + throw new JenaTransactionException("Tried to promote READ transaction"); case READ_COMMITTED_PROMOTE : readCommitted = true; case READ_PROMOTE : @@ -204,9 +202,6 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr throw new NullPointerException(); } - // XXX Check "mutate". - mutate(null, null); - try { _promote(readCommitted); return true; @@ -215,10 +210,6 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr } } - /*private*/public/*for development*/ static boolean promotion = false ; - - /*private*/public/*for development*/ static boolean readCommittedPromotion = true ; - private void _promote(boolean readCommited) { //System.err.printf("Promote: version=%d generation=%d\n", version.get() , generation.get()) ; @@ -240,8 +231,8 @@ public class DatasetGraphInMemory extends DatasetGraphTriplesQuads implements Tr throw new JenaTransactionException("Concurrent writer changed the dataset : can't promote") ; } // We have the lock and we have promoted! - transactionType(WRITE); - _begin(WRITE) ; + transactionMode(WRITE); + _begin(transactionType(), ReadWrite.WRITE) ; } @Override http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java b/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java index 6e93dcd..e641d55 100644 --- a/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java +++ b/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java @@ -18,15 +18,14 @@ package org.apache.jena.system; -import static org.apache.jena.query.ReadWrite.WRITE ; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.Semaphore ; -import java.util.concurrent.atomic.AtomicLong ; - -import org.apache.jena.atlas.lib.Lib ; -import org.apache.jena.query.ReadWrite ; -import org.apache.jena.sparql.JenaTransactionException ; -import org.apache.jena.sparql.core.Transactional ; +import org.apache.jena.atlas.lib.Lib; +import org.apache.jena.query.ReadWrite; +import org.apache.jena.query.TxnType; +import org.apache.jena.sparql.JenaTransactionException; +import org.apache.jena.sparql.core.Transactional; /** A MR+SW transactional Counter */ public class TxnCounter implements Transactional { @@ -35,148 +34,198 @@ public class TxnCounter implements Transactional { // Semaphore to implement "Single Active Writer" - independent of readers // This is not reentrant. - private Semaphore writersWaiting = new Semaphore(1, true) ; + private Semaphore writersWaiting = new Semaphore(1, true); private void releaseWriterLock() { - int x = writersWaiting.availablePermits() ; + int x = writersWaiting.availablePermits(); if ( x != 0 ) - throw new JenaTransactionException("TransactionCoordinator: Probably mismatch of enable/disableWriter calls") ; - writersWaiting.release() ; + throw new JenaTransactionException("TransactionCoordinator: Probably mismatch of enable/disableWriter calls"); + writersWaiting.release(); } private boolean acquireWriterLock(boolean canBlock) { if ( ! canBlock ) - return writersWaiting.tryAcquire() ; + return writersWaiting.tryAcquire(); try { - writersWaiting.acquire() ; + writersWaiting.acquire(); return true; - } catch (InterruptedException e) { throw new JenaTransactionException(e) ; } + } catch (InterruptedException e) { throw new JenaTransactionException(e); } } // ---- TransactionCoordinator. // Transaction state. static class IntegerState { - long txnValue ; - public IntegerState(long v) { this.txnValue = v ; } + long txnValue; + public IntegerState(long v) { this.txnValue = v; } } // Global state - the exterally visible value and the starting point for any // transaction. This is set to a new value when a write transaction commits. - private final AtomicLong value = new AtomicLong(-1712) ; + private final AtomicLong value = new AtomicLong(-1712); + private final AtomicLong epoch = new AtomicLong(1); // ---- Transaction state. // The per-transaction state (inside a transaction). Null outside a transaction // cleared by commit or abort in a write transaction. - private ThreadLocal<IntegerState> txnValue = ThreadLocal.withInitial(()->null) ; + private ThreadLocal<IntegerState> transactionValue = ThreadLocal.withInitial(()->null); // The kind of transaction. - private ThreadLocal<ReadWrite> txnMode = ThreadLocal.withInitial(()->null) ; + private ThreadLocal<ReadWrite> transactionMode = ThreadLocal.withInitial(()->null); + private ThreadLocal<TxnType> transactionType = ThreadLocal.withInitial(()->null); + private ThreadLocal<Long> transactionEpoch = ThreadLocal.withInitial(()->null); - // Syncrhonization for making changes. - private Object txnLifecycleLock = new Object() ; + // Synchronization for making changes. + private Object txnLifecycleLock = new Object(); public TxnCounter(long x) { - value.set(x) ; + value.set(x); } @Override public void begin(ReadWrite readWrite) { - begin(readWrite, true) ; + begin(TxnType.convert(readWrite)); + } + + @Override + public void begin(TxnType txnType) { + begin(txnType, true); } - public void begin(ReadWrite readWrite, boolean canBlock) { + public void begin(TxnType txnType, boolean canBlock) { // Ensure a single writer. // (Readers never block at this point.) - if ( readWrite == WRITE ) { + if ( txnType == TxnType.WRITE ) { // Writers take a WRITE permit from the semaphore to ensure there // is at most one active writer, else the attempt to start the // transaction blocks. // Released by in commit/abort. - acquireWriterLock(canBlock) ; + acquireWriterLock(canBlock); } // at this point, // One writer or one of many readers. synchronized(txnLifecycleLock) { - if ( txnMode.get() != null ) - throw new JenaTransactionException("Already in a transaction") ; - IntegerState state = new IntegerState(value.get()) ; - txnValue.set(state) ; - txnMode.set(readWrite); + if ( transactionMode.get() != null ) + throw new JenaTransactionException("Already in a transaction"); + long thisEpoch = epoch.incrementAndGet(); + transactionEpoch.set(thisEpoch) ; + IntegerState state = new IntegerState(value.get()); + transactionValue.set(state); + transactionMode.set(TxnType.initial(txnType)); + transactionType.set(txnType); } } @Override + public boolean promote() { + checkTxn(); + if ( transactionMode.get() == ReadWrite.WRITE ) + return true; + TxnType txnType = transactionType.get(); + if ( txnType == TxnType.READ ) + throw new JenaTransactionException("Attempt to promote a READ transsction"); + if ( txnType == TxnType.READ_COMMITTED_PROMOTE ) { + acquireWriterLock(true); + transactionMode.set(ReadWrite.WRITE); + IntegerState state = new IntegerState(value.get()); + transactionValue.set(state); + return true; + } + // READ no committed. + acquireWriterLock(true); + synchronized(txnLifecycleLock) { + long nowEpoch = epoch.get(); + if ( transactionEpoch.get() != nowEpoch ) { + // Can't. + releaseWriterLock(); + return false; + } + // Can. + transactionMode.set(ReadWrite.WRITE); + } + return true; + } + + + @Override public void commit() { checkTxn(); if ( isWriteTxn() ) { // Set global. - value.set(getDataState().txnValue) ; - txnValue.set(null); + value.set(getDataState().txnValue); + transactionValue.set(null); releaseWriterLock(); } - endOnce() ; + endOnce(); } @Override public void abort() { checkTxn(); if ( isWriteTxn() ) { - txnValue.set(null); + transactionValue.set(null); releaseWriterLock(); } - endOnce() ; + endOnce(); } @Override public boolean isInTransaction() { - ReadWrite mode = txnMode.get() ; - if ( mode == null ) - // Remove it - avoid holding the memory. - txnMode.remove(); - return mode != null ; + return Lib.readThreadLocal(transactionMode) != null; + } + + @Override + public ReadWrite transactionMode() { + return Lib.readThreadLocal(transactionMode); + } + + @Override + public TxnType transactionType() { + return Lib.readThreadLocal(transactionType); } @Override public void end() { if ( ! isInTransaction() ) - return ; - if ( isWriteTxn() && txnValue.get() != null ) - throw new JenaTransactionException("No commit or abort before end for a write transaction") ; - endOnce() ; + return; + if ( isWriteTxn() && transactionValue.get() != null ) + throw new JenaTransactionException("No commit or abort before end for a write transaction"); + endOnce(); } private void endOnce() { if ( isActiveTxn() ) { synchronized(txnLifecycleLock) { - txnValue.remove(); - txnMode.remove(); + transactionValue.remove(); + transactionType.remove(); + transactionMode.remove(); + transactionEpoch.remove(); } } } /** Increment the value inside a write transaction */ public void inc() { - checkWriteTxn() ; - IntegerState ts = getDataState() ; - ts.txnValue++ ; + checkWriteTxn(); + IntegerState ts = getDataState(); + ts.txnValue++; } /** Decrement the value inside a write transaction */ public void dec() { - checkWriteTxn() ; - IntegerState ts = getDataState() ; - ts.txnValue-- ; + checkWriteTxn(); + IntegerState ts = getDataState(); + ts.txnValue--; } /** Set the value inside a write transaction, return the old value*/ public long set(long x) { - checkWriteTxn() ; - IntegerState ts = getDataState() ; - long v = ts.txnValue ; - ts.txnValue = x ; - return v ; + checkWriteTxn(); + IntegerState ts = getDataState(); + long v = ts.txnValue; + ts.txnValue = x; + return v; } @@ -186,7 +235,7 @@ public class TxnCounter implements Transactional { */ public long read() { checkTxn(); - return getDataState().txnValue ; + return getDataState().txnValue; } /** Return the current value. @@ -197,14 +246,14 @@ public class TxnCounter implements Transactional { */ public long get() { if ( isActiveTxn() ) - return getDataState().txnValue ; + return getDataState().txnValue; else - return value.get() ; + return value.get(); } /** Read the current global state (that is, the last committed value) outside a transaction. */ public long value() { - return value.get() ; + return value.get(); } // These two operations not clear the thread local if we are not in a transaction. @@ -213,28 +262,28 @@ public class TxnCounter implements Transactional { /** Is this a write transaction? Should be called inside a transaction. */ private boolean isWriteTxn() { - ReadWrite rw = txnMode.get() ; + ReadWrite rw = transactionMode.get(); if ( rw == null ) - throw new JenaTransactionException(Lib.classShortName(this.getClass())+".isWriteTxn called outside a transaction") ; - return txnMode.get() == ReadWrite.WRITE ; + throw new JenaTransactionException(Lib.classShortName(this.getClass())+".isWriteTxn called outside a transaction"); + return transactionMode.get() == ReadWrite.WRITE; } private boolean isActiveTxn() { - ReadWrite rw = txnMode.get() ; - return rw != null ; + ReadWrite rw = transactionMode.get(); + return rw != null; } private IntegerState getDataState() { - return txnValue.get() ; + return transactionValue.get(); } private void checkWriteTxn() { if ( ! isWriteTxn() ) - throw new JenaTransactionException("Not in a write transaction") ; + throw new JenaTransactionException("Not in a write transaction"); } private void checkTxn() { if ( ! isActiveTxn() ) - throw new JenaTransactionException("Not in a transaction") ; + throw new JenaTransactionException("Not in a transaction"); } } http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java index c851ee8..800e428 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java @@ -34,7 +34,6 @@ import org.junit.runners.Suite ; , TestDatasetGraphViewGraphs.class , TestGraphView.class , TestDatasetMonitor.class - , TestDatasetGraphWithLock.class , TestDatasetGraphBaseFind_General.class , TestDatasetGraphBaseFind_General.class http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java deleted file mode 100644 index 0a3b0a6..0000000 --- a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.jena.sparql.core; - -import org.apache.jena.query.Dataset ; -import org.apache.jena.query.DatasetFactory ; - -/** Non-transaction part of DatasetGraphWithLock testing */ -public class TestDatasetGraphWithLock extends AbstractTestDataset { - @Override - protected Dataset createDataset() { - return DatasetFactory.wrap(new DatasetGraphWithLock(DatasetGraphFactory.create())); - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryLock.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryLock.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryLock.java index 27daed4..721dbb9 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryLock.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryLock.java @@ -20,9 +20,9 @@ package org.apache.jena.sparql.core.mem; import org.apache.jena.query.Dataset ; import org.apache.jena.query.DatasetFactory ; -import org.apache.jena.sparql.core.TestDatasetGraphWithLock ; +import org.apache.jena.sparql.core.AbstractTestDataset; -public class TestDatasetGraphInMemoryLock extends TestDatasetGraphWithLock { +public class TestDatasetGraphInMemoryLock extends AbstractTestDataset { @Override protected Dataset createDataset() { return DatasetFactory.createTxnMem(); http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java index 3378a87..9134668 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java @@ -18,7 +18,7 @@ package org.apache.jena.sparql.transaction ; -import static org.junit.Assert.assertEquals ; +import static org.junit.Assert.* ; import static org.junit.Assert.fail ; import java.util.concurrent.* ; @@ -172,7 +172,7 @@ public abstract class AbstractTestTransPromote { assertCount(0, dsg) ; } - // XXX LOCK UP + // LOCK UP //@Test public void promote_snapshot_06() { run_06(TxnMode.READ_PROMOTE) ; } //@Test public void promote_readCommitted_06() { run_06(TxnMode.READ_COMMITTED_PROMOTE) ; } @@ -387,4 +387,51 @@ public abstract class AbstractTestTransPromote { throw e ; } catch (InterruptedException | ExecutionException e1) { throw new RuntimeException(e1) ; } } + + // This would locks up because of a WRITE-WRITE deadly embrace. + // @Test(expected=JenaTransactionException.class) + // public void promote11() { test2(TxnMode.WRITE); } + + @Test + public void promote_thread_writer_1() { test_thread_writer(TxnType.READ_COMMITTED_PROMOTE); } + + @Test(expected=JenaTransactionException.class) + public void promote_thread_writer_2() { test_thread_writer(TxnType.READ_PROMOTE); } + + private void test_thread_writer(TxnType txnType) { + DatasetGraph dsg = create(); + ThreadAction a = ThreadTxn.threadTxnWrite(dsg, ()->dsg.add(q1)); + dsg.begin(txnType); + assertEquals(txnType, dsg.transactionType()); + a.run(); + dsg.add(q2); + // TDB1 does not keep the the original TxnType. + assertEquals(txnType, dsg.transactionType()); + assertEquals(ReadWrite.WRITE, dsg.transactionMode()); + dsg.commit(); + dsg.end(); + } + + // With explicit "promote()" + private void test_promote_thread_writer(TxnType txnType) { + DatasetGraph dsg = create(); + ThreadAction a = ThreadTxn.threadTxnWrite(dsg, ()->dsg.add(q1)); + dsg.begin(txnType); + assertEquals(txnType, dsg.transactionType()); + a.run(); + + boolean b = dsg.promote(); + + if ( txnType == TxnType.READ_PROMOTE ) + assertFalse(b); + if ( txnType == TxnType.READ_COMMITTED_PROMOTE ) + assertTrue(b); + + dsg.add(q2); + assertEquals(txnType, dsg.transactionType()); + assertEquals(ReadWrite.WRITE, dsg.transactionMode()); + dsg.commit(); + dsg.end(); + } + } http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java index 32b8ca3..c1043b8 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java @@ -18,8 +18,9 @@ package org.apache.jena.sparql.transaction; -import static org.apache.jena.query.ReadWrite.READ ; -import static org.apache.jena.query.ReadWrite.WRITE ; +import static org.apache.jena.query.TxnType.READ ; +import static org.apache.jena.query.TxnType.WRITE ; +import static org.junit.Assume.assumeTrue; import java.util.ArrayList ; import java.util.List ; @@ -30,15 +31,20 @@ import org.apache.jena.atlas.junit.BaseTest ; import org.apache.jena.atlas.lib.Lib ; import org.apache.jena.query.Dataset ; import org.apache.jena.query.ReadWrite ; +import org.apache.jena.query.TxnType; +import org.apache.jena.shared.JenaException; import org.apache.jena.sparql.JenaTransactionException ; -import static org.junit.Assume.* ; import org.junit.Test ; +/** + * Dataset transaction lifecycle. + */ public abstract class AbstractTestTransactionLifecycle extends BaseTest { protected abstract Dataset create() ; - protected boolean supportsAbort() { return true ; } + protected boolean supportsAbort() { return true ; } + protected boolean supportsPromote() { return true ; } @Test public void transaction_00() { @@ -49,7 +55,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest @Test public void transaction_r01() { Dataset ds = create() ; - ds.begin(ReadWrite.READ) ; + ds.begin(TxnType.READ) ; assertTrue(ds.isInTransaction()) ; ds.end() ; assertFalse(ds.isInTransaction()) ; @@ -58,7 +64,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest @Test public void transaction_r02() { Dataset ds = create() ; - ds.begin(ReadWrite.READ) ; + ds.begin(TxnType.READ) ; assertTrue(ds.isInTransaction()) ; ds.commit() ; assertFalse(ds.isInTransaction()) ; @@ -69,7 +75,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest @Test public void transaction_r03() { Dataset ds = create() ; - ds.begin(ReadWrite.READ) ; + ds.begin(TxnType.READ) ; assertTrue(ds.isInTransaction()) ; ds.abort() ; assertFalse(ds.isInTransaction()) ; @@ -78,8 +84,26 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest } @Test + public void transaction_r04() { + Dataset ds = create() ; + ds.begin(ReadWrite.READ) ; + assertTrue(ds.isInTransaction()) ; + ds.end() ; + assertFalse(ds.isInTransaction()) ; + } + + @Test public void transaction_w01() { Dataset ds = create() ; + ds.begin(TxnType.WRITE) ; + assertTrue(ds.isInTransaction()) ; + ds.commit() ; + assertFalse(ds.isInTransaction()) ; + } + + @Test + public void transaction_w02() { + Dataset ds = create() ; ds.begin(ReadWrite.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.commit() ; @@ -87,19 +111,19 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest } @Test - public void transaction_w02() { + public void transaction_w03() { assumeTrue(supportsAbort()) ; Dataset ds = create() ; - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.abort() ; assertFalse(ds.isInTransaction()) ; } @Test - public void transaction_w03() { + public void transaction_w04() { Dataset ds = create() ; - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.commit() ; assertFalse(ds.isInTransaction()) ; @@ -108,10 +132,10 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest } @Test - public void transaction_w04() { + public void transaction_w05() { assumeTrue(supportsAbort()) ; Dataset ds = create() ; - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.abort() ; assertFalse(ds.isInTransaction()) ; @@ -120,21 +144,110 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest } @Test - public void transaction_w05() { + public void transaction_w06() { assumeTrue(supportsAbort()) ; // .end is not necessary Dataset ds = create() ; - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.abort() ; assertFalse(ds.isInTransaction()) ; - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.abort() ; assertFalse(ds.isInTransaction()) ; } +// TxnType.READ_PROMOTE +// TxnType.READ_COMMITTED_PROMOTE + + @Test + public void transaction_p01() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ_PROMOTE) ; + assertEquals(TxnType.READ_PROMOTE, ds.transactionType()); + assertTrue(ds.isInTransaction()) ; + assertEquals(ReadWrite.READ, ds.transactionMode()); + ds.promote(); + assertEquals(ReadWrite.WRITE, ds.transactionMode()); + ds.commit(); + ds.end(); + } + + @Test + public void transaction_p02() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ_COMMITTED_PROMOTE) ; + assertEquals(TxnType.READ_COMMITTED_PROMOTE, ds.transactionType()); + assertTrue(ds.isInTransaction()) ; + assertEquals(ReadWrite.READ, ds.transactionMode()); + boolean b = ds.promote(); + assertTrue(b) ; + assertEquals(ReadWrite.WRITE, ds.transactionMode()); + ds.commit(); + ds.end(); + } + + @Test + public void transaction_p03() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ_PROMOTE) ; + assertTrue(ds.isInTransaction()) ; + assertEquals(ReadWrite.READ, ds.transactionMode()); + boolean b = ds.promote(); + assertTrue(b) ; + assertEquals(ReadWrite.WRITE, ds.transactionMode()); + ds.abort(); + ds.end(); + assertFalse(ds.isInTransaction()) ; + } + + @Test + public void transaction_p04() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ_COMMITTED_PROMOTE) ; + assertTrue(ds.isInTransaction()) ; + assertEquals(ReadWrite.READ, ds.transactionMode()); + boolean b = ds.promote(); + assertTrue(b) ; + assertEquals(ReadWrite.WRITE, ds.transactionMode()); + ds.abort(); + ds.end(); + assertFalse(ds.isInTransaction()) ; + } + + @Test + public void transaction_p05() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ_COMMITTED_PROMOTE) ; + assertTrue(ds.isInTransaction()) ; + boolean b1 = ds.promote(); + assertTrue(b1) ; + boolean b2 = ds.promote(); + assertTrue(b2) ; + ds.commit(); + ds.end(); + } + + @Test(expected=JenaException.class) + public void transaction_err_read_promote() { + assumeTrue(supportsPromote()) ; + Dataset ds = create() ; + ds.begin(TxnType.READ) ; + boolean b = ds.promote(); // Illgeal. + assertFalse(b) ; + ds.commit(); + ds.end(); + } + + // XXX READ_PROMOTE -> update -> fail promote/boolean. + // Patterns. @Test public void transaction_pattern_01() { @@ -253,7 +366,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest public void transaction_err_12() { testAbortCommit(WRITE) ; } private void read1(Dataset ds) { - ds.begin(ReadWrite.READ) ; + ds.begin(TxnType.READ) ; assertTrue(ds.isInTransaction()) ; ds.commit() ; assertFalse(ds.isInTransaction()) ; @@ -261,14 +374,14 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest } private void read2(Dataset ds) { - ds.begin(ReadWrite.READ) ; + ds.begin(TxnType.READ) ; assertTrue(ds.isInTransaction()) ; ds.end() ; assertFalse(ds.isInTransaction()) ; } private void write(Dataset ds) { - ds.begin(ReadWrite.WRITE) ; + ds.begin(TxnType.WRITE) ; assertTrue(ds.isInTransaction()) ; ds.commit() ; assertFalse(ds.isInTransaction()) ; @@ -281,67 +394,67 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest // Error conditions that should be detected. - private void testBeginBegin(ReadWrite mode1, ReadWrite mode2) { + private void testBeginBegin(TxnType txnType1, TxnType txnType2) { Dataset ds = create() ; - ds.begin(mode1) ; + ds.begin(txnType1) ; try { - ds.begin(mode2) ; - fail("Expected transaction exception - begin-begin (" + mode1 + ", " + mode2 + ")") ; + ds.begin(txnType2) ; + fail("Expected transaction exception - begin-begin (" + txnType1 + ", " + txnType2 + ")") ; } catch (JenaTransactionException ex) { safeEnd(ds) ; } } - private void testCommitCommit(ReadWrite mode) { + private void testCommitCommit(TxnType txnType) { Dataset ds = create() ; - ds.begin(mode) ; + ds.begin(txnType) ; ds.commit() ; try { ds.commit() ; - fail("Expected transaction exception - commit-commit(" + mode + ")") ; + fail("Expected transaction exception - commit-commit(" + txnType + ")") ; } catch (JenaTransactionException ex) { safeEnd(ds) ; } } - private void testCommitAbort(ReadWrite mode) { + private void testCommitAbort(TxnType txnType) { assumeTrue(supportsAbort()) ; Dataset ds = create() ; - ds.begin(mode) ; + ds.begin(txnType) ; ds.commit() ; try { ds.abort() ; - fail("Expected transaction exception - commit-abort(" + mode + ")") ; + fail("Expected transaction exception - commit-abort(" + txnType + ")") ; } catch (JenaTransactionException ex) { safeEnd(ds) ; } } - private void testAbortAbort(ReadWrite mode) { + private void testAbortAbort(TxnType txnType) { assumeTrue(supportsAbort()) ; Dataset ds = create() ; - ds.begin(mode) ; + ds.begin(txnType) ; ds.abort() ; try { ds.abort() ; - fail("Expected transaction exception - abort-abort(" + mode + ")") ; + fail("Expected transaction exception - abort-abort(" + txnType + ")") ; } catch (JenaTransactionException ex) { ds.end() ; } } - private void testAbortCommit(ReadWrite mode) { + private void testAbortCommit(TxnType txnType) { assumeTrue(supportsAbort()) ; Dataset ds = create() ; - ds.begin(mode) ; + ds.begin(txnType) ; ds.abort() ; try { ds.commit() ; - fail("Expected transaction exception - abort-commit(" + mode + ")") ; + fail("Expected transaction exception - abort-commit(" + txnType + ")") ; } catch (JenaTransactionException ex) { safeEnd(ds) ; @@ -360,7 +473,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest @Override public Boolean call() { - ds.begin(ReadWrite.WRITE); + ds.begin(TxnType.WRITE); long x = counter.incrementAndGet() ; // Hold the lock for a short while. // The W threads will take the sleep serially. @@ -394,7 +507,7 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest Callable<Boolean> callable = new Callable<Boolean>() { @Override public Boolean call() { - ds.begin(ReadWrite.READ); + ds.begin(TxnType.READ); long x = counter.incrementAndGet() ; // Hold the lock for a few seconds - these should be in parallel. Lib.sleep(1000) ; http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java index 7fbbe62..7cc1879 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java @@ -25,8 +25,6 @@ import org.junit.runners.Suite.SuiteClasses ; @RunWith(Suite.class) @SuiteClasses( { TestTransactionSupport.class - , TestTransactionDSGWithLockNoAbort.class - , TestTransactionDSGWithLockWithAbort.class }) public class TS_Transaction http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockNoAbort.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockNoAbort.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockNoAbort.java deleted file mode 100644 index 98617d0..0000000 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockNoAbort.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.jena.sparql.transaction; - -import org.apache.jena.query.Dataset ; -import org.apache.jena.query.DatasetFactory ; -import org.apache.jena.sparql.core.DatasetGraph ; -import org.apache.jena.sparql.core.DatasetGraphFactory ; -import org.apache.jena.sparql.core.DatasetGraphWithLock ; - -/** Version with abortImplemented == false (the default). */ -public class TestTransactionDSGWithLockNoAbort extends AbstractTestTransactionLifecycle -{ - @Override - protected boolean supportsAbort() { return false ; } - - @Override - protected Dataset create() - { - DatasetGraph dsg = DatasetGraphFactory.create() ; - DatasetGraphWithLock dsgl = new DatasetGraphWithLock(dsg, false) ; - return DatasetFactory.wrap(dsgl) ; - } - } - http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java deleted file mode 100644 index 9e0fbd6..0000000 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 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.jena.sparql.transaction; - -import org.apache.jena.query.Dataset ; -import org.apache.jena.query.DatasetFactory ; -import org.apache.jena.sparql.core.DatasetGraph ; -import org.apache.jena.sparql.core.DatasetGraphFactory ; -import org.apache.jena.sparql.core.DatasetGraphWithLock ; - -/** Version with abortImplemented == true */ -public class TestTransactionDSGWithLockWithAbort extends AbstractTestTransactionLifecycle -{ - @Override - protected Dataset create() { - // The tests don't actually add/delete data. - DatasetGraph dsg = DatasetGraphFactory.createTxnMem() ; - DatasetGraphWithLock dsgl = new DatasetGraphWithLock(dsg, true) ; - return DatasetFactory.wrap(dsgl) ; - } - } - http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionSupport.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionSupport.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionSupport.java index 4eb1cac..46c955a 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionSupport.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionSupport.java @@ -24,6 +24,7 @@ import java.util.List ; import org.apache.jena.atlas.lib.Creator ; import org.apache.jena.sparql.core.DatasetGraph ; import org.apache.jena.sparql.core.DatasetGraphFactory ; +import org.apache.jena.sparql.core.DatasetGraphZero; import org.apache.jena.sparql.graph.GraphFactory ; import org.junit.Assert ; import org.junit.Test ; @@ -50,7 +51,10 @@ public class TestTransactionSupport { x.add(new Object[] {"createOneGraph" , (Creator<DatasetGraph>)()-> DatasetGraphFactory.createOneGraph(GraphFactory.createDefaultGraph()), - true, false}) ; + true, true}) ; + x.add(new Object[] {"createZeroGraph" , + (Creator<DatasetGraph>)()->new DatasetGraphZero(), + true, true}) ; x.add(new Object[] {"create(Graph)", (Creator<DatasetGraph>)()-> DatasetGraphFactory.create(GraphFactory.createDefaultGraph()), http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java index 27db959..19b6ac0 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java @@ -101,6 +101,17 @@ public class Lib } /** + * Read thread local, assuming that "null" means it does not exist for this thread. + * If null is read, the thread local is removed. + */ + public static <X> X readThreadLocal(ThreadLocal<X> threadLocal) { + X x = threadLocal.get(); + if ( x == null ) + threadLocal.remove(); + return x ; + } + + /** * @see CRC32 */ public static long crc32(byte[] bytes) http://git-wip-us.apache.org/repos/asf/jena/blob/edab900a/jena-db/jena-dboe-transaction/src/main/java/org/apache/jena/dboe/transaction/txn/Transaction.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-dboe-transaction/src/main/java/org/apache/jena/dboe/transaction/txn/Transaction.java b/jena-db/jena-dboe-transaction/src/main/java/org/apache/jena/dboe/transaction/txn/Transaction.java index d523e74..6bac45c 100644 --- a/jena-db/jena-dboe-transaction/src/main/java/org/apache/jena/dboe/transaction/txn/Transaction.java +++ b/jena-db/jena-dboe-transaction/src/main/java/org/apache/jena/dboe/transaction/txn/Transaction.java @@ -181,10 +181,11 @@ public class Transaction implements TransactionInfo { public void end() { txnMgr.notifyEndStart(this) ; if ( isWriteTxn() && getState() == ACTIVE ) { - throw new TransactionException("Write transaction with no commit or abort") ; //Log.warn(this, "Write transaction with no commit() or abort() before end()"); // Just the abort process. - //abort$() ; + abort$() ; + endInternal() ; + throw new TransactionException("Write transaction with no commit() or abort() before end() - forced abort") ; } endInternal() ; txnMgr.notifyEndFinish(this) ;
