You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2016/07/12 18:16:28 UTC
[1/6] jena git commit: JENA-1090 : Txn - a java8-centric transaction
API
Repository: jena
Updated Branches:
refs/heads/master 3bbe2d8d7 -> e42090549
JENA-1090 : Txn - a java8-centric transaction API
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/952aebd0
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/952aebd0
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/952aebd0
Branch: refs/heads/master
Commit: 952aebd0ac8f2d5d590811f0ac97d3c17c9bea5a
Parents: 1accb0e
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jul 9 22:40:03 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jul 9 22:40:03 2016 +0100
----------------------------------------------------------------------
.../java/org/apache/jena/system/ThreadTxn.java | 148 ++++++++++++
.../main/java/org/apache/jena/system/Txn.java | 112 +++++++++
.../java/org/apache/jena/system/TxnCounter.java | 240 +++++++++++++++++++
.../org/apache/jena/sparql/ARQTestSuite.java | 2 +
.../apache/jena/system/ExceptionFromTest.java | 21 ++
.../java/org/apache/jena/system/TS_System.java | 32 +++
.../org/apache/jena/system/TestCounter.java | 145 +++++++++++
.../java/org/apache/jena/system/TestTxn.java | 238 ++++++++++++++++++
.../apache/jena/system/TestTxnLifecycle.java | 167 +++++++++++++
.../org/apache/jena/system/TestTxnThread.java | 92 +++++++
10 files changed, 1197 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java b/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
new file mode 100644
index 0000000..ada55b5
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
@@ -0,0 +1,148 @@
+/*
+ * 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.system;
+
+import java.util.Objects ;
+import java.util.concurrent.Executor ;
+import java.util.concurrent.Executors ;
+import java.util.concurrent.Semaphore ;
+import java.util.concurrent.atomic.AtomicReference ;
+
+import org.apache.jena.query.ReadWrite ;
+import org.apache.jena.sparql.core.Transactional ;
+
+/**
+ * An action that will happen on a different thread later when {@link #run} is
+ * called. A thread is created and the transaction started during a call to the
+ * creation operations {@link #threadTxnRead} or {@link #threadTxnWrite}.
+ * The associated Runnable is called and the transaction completed when
+ * {@link #run} is called. Being on a thread, the state of the world the
+ * forked transaction sees is outside the creating thread which may itself be in a
+ * transaction. Warning: creating a write transaction inside a write transaction
+ * will cause deadlock.
+ */
+public class ThreadTxn {
+ // ---- Thread
+
+ /** Create a thread-backed delayed READ transaction action.
+ * Call {@link ThreadTxn#run} to perform the read transaction.
+ */
+ public static ThreadTxn threadTxnRead(Transactional trans, Runnable action) {
+ return ThreadTxn.create(trans, ReadWrite.READ, action, false) ;
+ }
+
+ /** Create a thread-backed delayed WRITE action.
+ * Call {@link ThreadTxn#run} to perform the write transaction.
+ * (If called from inside a write transaction on the {@code trans},
+ * this will deadlock.)
+ */
+ public static ThreadTxn threadTxnWrite(Transactional trans, Runnable action) {
+ return ThreadTxn.create(trans, ReadWrite.WRITE, action, true) ;
+ }
+
+ /** Create a thread-backed delayed WRITE-abort action (mainly for testing). */
+ public static ThreadTxn threadTxnWriteAbort(Transactional trans, Runnable action) {
+ return ThreadTxn.create(trans, ReadWrite.WRITE, action, false) ;
+ }
+
+ private final Semaphore semaStart ;
+ private final Semaphore semaFinish ;
+ private final AtomicReference<RuntimeException> thrownRuntimeException = new AtomicReference<>(null) ;
+ private final AtomicReference<Error> thrownError = new AtomicReference<>(null) ;
+ private final Runnable action ;
+
+ private ThreadTxn(Runnable action) {
+ this.action = action ;
+ this.semaStart = new Semaphore(0, true) ;
+ this.semaFinish = new Semaphore(0, true) ;
+ }
+
+ /**
+ * Perform the Runnable, reporting any
+ * {@link java.lang.RuntimeException} or {@link java.lang.Error}
+ */
+ public void run() {
+ semaStart.release();
+ semaFinish.acquireUninterruptibly() ;
+ if ( thrownError.get() != null )
+ throw thrownError.get() ;
+ if ( thrownRuntimeException.get() != null )
+ throw thrownRuntimeException.get() ;
+ }
+
+ // Called on the async thread.
+ private void trigger() {
+ try { action.run(); }
+ catch (Error error) { thrownError.set(error) ; throw error ;}
+ catch (RuntimeException ex) { thrownRuntimeException.set(ex) ; throw ex ; }
+ }
+
+ // System-shared executor better.
+ private static Executor executor = Executors.newCachedThreadPool() ;
+
+ /*package*/ static ThreadTxn create(Transactional trans, ReadWrite mode, Runnable action, boolean isCommit) {
+ Objects.requireNonNull(trans) ;
+ Objects.requireNonNull(mode) ;
+ Objects.requireNonNull(action) ;
+
+ ThreadTxn threadAction = new ThreadTxn(action) ;
+ // Startup semaphore so that the thread has started by the
+ // time we exit this setup function.
+ Semaphore semaStartup = new Semaphore(0, true) ;
+ executor.execute( ()-> {
+ // NB. trans.begin then semaStartup.release() ;
+ // This ensures that the transaction has really started.
+ trans.begin(mode) ;
+
+ // Signal the creator (see below) that the transaction has started.
+ semaStartup.release() ;
+
+ // Wait for the signal to run the action.
+ threadAction.semaStart.acquireUninterruptibly();
+
+ try {
+ // Performane the action, catch and record any RuntimeException or Error.
+ threadAction.trigger() ;
+
+ // Finish transaction (if no throwable)
+ if ( mode == ReadWrite.WRITE ) {
+ if ( isCommit )
+ trans.commit();
+ else
+ trans.abort() ;
+ trans.end() ;
+ } else {
+ // Read
+ if ( isCommit )
+ trans.commit();
+ trans.end() ;
+ }
+ }
+ catch (Throwable ex) {
+ // Surpress now it has trigger transaction mechanism in
+ // the presence of an unchecked exception.
+ // Passed to the main thread via ThreadTxn
+ }
+ finally { threadAction.semaFinish.release() ; }
+ }) ;
+ // Don't return until the transaction has started.
+ semaStartup.acquireUninterruptibly();
+ return threadAction ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/main/java/org/apache/jena/system/Txn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/system/Txn.java b/jena-arq/src/main/java/org/apache/jena/system/Txn.java
new file mode 100644
index 0000000..c422fc4
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/system/Txn.java
@@ -0,0 +1,112 @@
+/*
+ * 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.system;
+
+import java.util.function.Supplier ;
+
+import org.apache.jena.query.ReadWrite ;
+import org.apache.jena.sparql.JenaTransactionException ;
+import org.apache.jena.sparql.core.Transactional ;
+
+/** Application utilities for transactions.
+ * <ul>
+ * <li>"Autocommit" provided.
+ * <li>Nested transaction are not supported but calling inside an existing transaction,
+ * which must be compatible, (i.e. a write needs a WRITE transaction).
+ * causes the transaction to be used.
+ * </ul>
+ */
+
+public class Txn {
+ /** Execute the Runnable in a read transaction. */
+ public static <T extends Transactional> void execRead(T txn, Runnable r) {
+ boolean b = txn.isInTransaction() ;
+ if ( !b )
+ txn.begin(ReadWrite.READ) ;
+ try { r.run() ; }
+ catch (Throwable th) {
+ onThrowable(txn);
+ throw th ;
+ }
+ if ( ! b )
+ txn.end() ;
+ }
+
+ /** Execute and return a value in a read transaction */
+ public static <T extends Transactional, X> X execReadRtn(T txn, Supplier<X> r) {
+ boolean b = txn.isInTransaction() ;
+ if ( !b )
+ txn.begin(ReadWrite.READ) ;
+ try {
+ X x = r.get() ;
+ if ( !b )
+ txn.end() ;
+ return x ;
+ } catch (Throwable th) {
+ onThrowable(txn);
+ throw th ;
+ }
+ }
+
+ /** Execute the Runnable in a write transaction */
+ public static <T extends Transactional> void execWrite(T txn, Runnable r) {
+ boolean b = txn.isInTransaction() ;
+ if ( !b )
+ txn.begin(ReadWrite.WRITE) ;
+ try { r.run() ; }
+ catch (Throwable th) {
+ onThrowable(txn);
+ throw th ;
+ }
+ if ( !b ) {
+ if ( txn.isInTransaction() )
+ // May have been explicit commit or abort.
+ txn.commit() ;
+ txn.end() ;
+ }
+ }
+
+ /** Execute and return a value in a write transaction. */
+ public static <T extends Transactional, X> X execWriteRtn(Transactional txn, Supplier<X> r) {
+ boolean b = txn.isInTransaction() ;
+ if ( !b )
+ txn.begin(ReadWrite.WRITE) ;
+ X x = null ;
+ try { x = r.get() ; }
+ catch (Throwable th) {
+ onThrowable(txn);
+ throw th ;
+ }
+ if ( !b ) {
+ if ( txn.isInTransaction() )
+ // May have been explicit commit or abort.
+ txn.commit() ;
+ txn.end() ;
+ }
+ return x ;
+ }
+
+ // Attempt some kind of cleanup.
+ private static <T extends Transactional> void onThrowable(T txn) {
+ try {
+ txn.abort() ;
+ txn.end() ;
+ } catch (JenaTransactionException ex) { }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/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
new file mode 100644
index 0000000..1477e6b
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/system/TxnCounter.java
@@ -0,0 +1,240 @@
+/*
+ * 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.system;
+
+import static org.apache.jena.query.ReadWrite.WRITE ;
+
+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 ;
+
+/** A MR+SW transactional Counter */
+public class TxnCounter implements Transactional {
+
+ // ---- TransactionCoordinator.
+
+ // Semaphore to implement "Single Active Writer" - independent of readers
+ // This is not reentrant.
+ private Semaphore writersWaiting = new Semaphore(1, true) ;
+
+ private void releaseWriterLock() {
+ int x = writersWaiting.availablePermits() ;
+ if ( x != 0 )
+ throw new JenaTransactionException("TransactionCoordinator: Probably mismatch of enable/disableWriter calls") ;
+ writersWaiting.release() ;
+ }
+
+ private boolean acquireWriterLock(boolean canBlock) {
+ if ( ! canBlock )
+ return writersWaiting.tryAcquire() ;
+ try {
+ writersWaiting.acquire() ;
+ return true;
+ } catch (InterruptedException e) { throw new JenaTransactionException(e) ; }
+ }
+ // ---- TransactionCoordinator.
+
+ // Transaction state.
+ static class IntegerState {
+ 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 trasnaction commits.
+
+ private final AtomicLong value = new AtomicLong(-1712) ;
+
+ // ---- 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) ;
+ // The kind of transaction.
+ private ThreadLocal<ReadWrite> txnMode = ThreadLocal.withInitial(()->null) ;
+
+ // Syncrhonization for making changes.
+ private Object txnLifecycleLock = new Object() ;
+
+ public TxnCounter(long x) {
+ value.set(x) ;
+ }
+
+ @Override
+ public void begin(ReadWrite readWrite) {
+ begin(readWrite, true) ;
+ }
+
+ public void begin(ReadWrite readWrite, boolean canBlock) {
+ // Ensure a single writer.
+ // (Readers never block at this point.)
+ if ( readWrite == 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) ;
+ }
+ // 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);
+ }
+ }
+
+ @Override
+ public void commit() {
+ checkTxn();
+ if ( isWriteTxn() ) {
+ // Set global.
+ value.set(getDataState().txnValue) ;
+ txnValue.set(null);
+ releaseWriterLock();
+ }
+ endOnce() ;
+ }
+
+ @Override
+ public void abort() {
+ checkTxn();
+ if ( isWriteTxn() ) {
+ txnValue.set(null);
+ releaseWriterLock();
+ }
+ endOnce() ;
+ }
+
+ @Override
+ public boolean isInTransaction() {
+ ReadWrite mode = txnMode.get() ;
+ if ( mode == null )
+ // Remove it - avoid holding the memory.
+ txnMode.remove();
+ return mode != null ;
+ }
+
+ @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() ;
+ }
+
+ private void endOnce() {
+ if ( isActiveTxn() ) {
+ synchronized(txnLifecycleLock) {
+ txnValue.remove();
+ txnMode.remove();
+ }
+ }
+ }
+
+ /** Increment the value inside a write transaction */
+ public void inc() {
+ checkWriteTxn() ;
+ IntegerState ts = getDataState() ;
+ ts.txnValue++ ;
+ }
+
+ /** Decrement the value inside a write transaction */
+ public void dec() {
+ 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 ;
+ }
+
+
+ /** Return the current value in a transaction.
+ * Must be inside a transaction.
+ * @see #get
+ */
+ public long read() {
+ checkTxn();
+ return getDataState().txnValue ;
+ }
+
+ /** Return the current value.
+ * If inside a transaction, return the transaction view of the value.
+ * If not in a transaction return the state value (effectively
+ * a read transaction, optimized by the fact that reading the
+ * {@code TransInteger} state is atomic).
+ */
+ public long get() {
+ if ( isActiveTxn() )
+ return getDataState().txnValue ;
+ else
+ return value.get() ;
+ }
+
+ /** Read the current global state (that is, the last committed value) outside a transaction. */
+ public long value() {
+ return value.get() ;
+ }
+
+ // These two operations not clear the thread local if we are not in a transaction.
+ // This is a potential memory leak.
+ // Use "isInTransaction" to read and clear.
+
+ /** Is this a write transaction? Shoudl be called inside a transaction. */
+ private boolean isWriteTxn() {
+ ReadWrite rw = txnMode.get() ;
+ if ( rw == null )
+ throw new JenaTransactionException(Lib.classShortName(this.getClass())+".isWriteTxn called outside a transaction") ;
+ return txnMode.get() == ReadWrite.WRITE ;
+ }
+
+ private boolean isActiveTxn() {
+ ReadWrite rw = txnMode.get() ;
+ return rw != null ;
+ }
+
+ private IntegerState getDataState() {
+ return txnValue.get() ;
+ }
+
+ private void checkWriteTxn() {
+ if ( ! isWriteTxn() )
+ throw new JenaTransactionException("Not in a write transaction") ;
+ }
+
+ private void checkTxn() {
+ if ( ! isActiveTxn() )
+ throw new JenaTransactionException("Not in a transaction") ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/sparql/ARQTestSuite.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/ARQTestSuite.java b/jena-arq/src/test/java/org/apache/jena/sparql/ARQTestSuite.java
index f40d8eb..23f3e66 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/ARQTestSuite.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/ARQTestSuite.java
@@ -29,6 +29,7 @@ import org.apache.jena.sparql.engine.ref.QueryEngineRef ;
import org.apache.jena.sparql.expr.E_Function ;
import org.apache.jena.sparql.expr.NodeValue ;
import org.apache.jena.system.JenaSystem ;
+import org.apache.jena.system.TS_System ;
import org.apache.jena.web.TS_Web ;
/**
@@ -60,6 +61,7 @@ public class ARQTestSuite extends TestSuite
ts.addTest(new JUnit4TestAdapter(TC_Riot.class)) ;
ts.addTest(new JUnit4TestAdapter(TS_Web.class)) ;
+ ts.addTest(new JUnit4TestAdapter(TS_System.class)) ;
// Main ARQ internal test suite.
ts.addTest(new JUnit4TestAdapter(TC_General.class)) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/ExceptionFromTest.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/ExceptionFromTest.java b/jena-arq/src/test/java/org/apache/jena/system/ExceptionFromTest.java
new file mode 100644
index 0000000..42efda6
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/ExceptionFromTest.java
@@ -0,0 +1,21 @@
+/*
+ * 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.system;
+
+class ExceptionFromTest extends RuntimeException {}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/TS_System.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TS_System.java b/jena-arq/src/test/java/org/apache/jena/system/TS_System.java
new file mode 100644
index 0000000..e8c6f05
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/TS_System.java
@@ -0,0 +1,32 @@
+/*
+ * 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.system;
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestCounter.class
+ , TestTxnLifecycle.class
+ , TestTxn.class
+ , TestTxnThread.class
+})
+
+public class TS_System {}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/TestCounter.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestCounter.java b/jena-arq/src/test/java/org/apache/jena/system/TestCounter.java
new file mode 100644
index 0000000..5eb1591
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestCounter.java
@@ -0,0 +1,145 @@
+/*
+ * 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.system;
+
+import org.apache.jena.query.ReadWrite ;
+import org.apache.jena.sparql.JenaTransactionException ;
+import org.apache.jena.system.TxnCounter ;
+import org.junit.Test ;
+
+import static org.junit.Assert.* ;
+
+// TestTxn also tests counters.
+public class TestCounter {
+ private TxnCounter counter = new TxnCounter(0) ;
+
+ @Test
+ public void counter_lifecycle_1() {
+ counter.begin(ReadWrite.WRITE) ;
+ counter.inc() ;
+ counter.commit();
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_lifecycle_2() {
+ counter.begin(ReadWrite.WRITE) ;
+ counter.abort() ;
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_lifecycle_3() {
+ counter.begin(ReadWrite.READ) ;
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_lifecycle_4() {
+ counter.begin(ReadWrite.READ) ;
+ counter.commit() ;
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_lifecycle_5() {
+ counter.begin(ReadWrite.READ) ;
+ counter.abort() ;
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_lifecycle_6() {
+ counter.end() ;
+ }
+
+ @Test
+ public void counter_01() {
+ assertEquals(0, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.begin(ReadWrite.WRITE) ;
+
+ assertEquals(0, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.inc() ;
+ long x = counter.get() ;
+ assertEquals(1, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.commit();
+ assertEquals(1, counter.value());
+
+ counter.end() ;
+ assertEquals(1, counter.value());
+ }
+
+ @Test
+ public void counter_02() {
+ assertEquals(0, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.begin(ReadWrite.WRITE) ;
+
+ assertEquals(0, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.inc() ;
+ long x = counter.get() ;
+ assertEquals(1, counter.get());
+ assertEquals(0, counter.value());
+
+ counter.abort();
+ assertEquals(0, counter.value());
+ counter.end() ;
+ assertEquals(0, counter.value());
+ }
+
+ @Test(expected=JenaTransactionException.class)
+ public void counter_bad_01() {
+ counter.inc() ;
+ }
+
+ @Test(expected=JenaTransactionException.class)
+ public void counter_bad_02() {
+ counter.begin(ReadWrite.WRITE) ;
+ counter.end() ;
+ }
+
+ @Test(expected=JenaTransactionException.class)
+ public void counter_bad_03() {
+ counter.begin(ReadWrite.READ) ;
+ counter.inc() ;
+ }
+
+ @Test(expected=JenaTransactionException.class)
+ public void counter_bad_04() {
+ counter.begin(ReadWrite.READ) ;
+ counter.end() ;
+ counter.commit() ;
+ }
+
+ @Test(expected=JenaTransactionException.class)
+ public void counter_bad_05() {
+ counter.begin(ReadWrite.WRITE) ;
+ counter.end() ;
+ counter.commit() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java b/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
new file mode 100644
index 0000000..d9a9546
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
@@ -0,0 +1,238 @@
+/*
+ * 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.system;
+
+import static org.junit.Assert.assertEquals ;
+
+import org.apache.jena.system.Txn ;
+import org.apache.jena.system.TxnCounter ;
+import org.junit.Test ;
+
+public class TestTxn {
+
+ TxnCounter counter = new TxnCounter(0) ;
+
+ @Test public void txn_basic_01() {
+ long v1 = counter.get() ;
+ assertEquals(0, v1) ;
+ Txn.execRead(counter, () -> {
+ assertEquals(0, counter.get()) ;
+ }) ;
+ }
+
+ @Test public void txn_basic_02() {
+ long x =
+ Txn.execReadRtn(counter, () -> {
+ assertEquals("In R, value()", 0, counter.value()) ;
+ assertEquals("In R, get()", 0, counter.get()) ;
+ return counter.get() ;
+ }) ;
+ assertEquals("Outside R", 0, x) ;
+ }
+
+ @Test public void txn_basic_03() {
+ Txn.execWrite(counter, counter::inc) ;
+ long x =
+ Txn.execReadRtn(counter, () -> {
+ assertEquals("In R, value()", 1, counter.value()) ;
+ assertEquals("In R, get()", 1, counter.get()) ;
+ return counter.get() ;
+ }) ;
+ assertEquals("Outside R", 1, x) ;
+ }
+
+ @Test public void txn_basic_05() {
+ long x =
+ Txn.execWriteRtn(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ return counter.get() ;
+ }) ;
+ assertEquals("Outside W",1, x) ;
+ }
+
+ @Test public void txn_write_01() {
+ long x =
+ Txn.execWriteRtn(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ long z = counter.get() ;
+ counter.commit() ;
+ return z ;
+ }) ;
+ assertEquals("Outside W",1, x) ;
+ }
+
+ @Test public void txn_write_02() {
+ long x =
+ Txn.execWriteRtn(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ long z = counter.get() ;
+ counter.abort() ;
+ return z ;
+ }) ;
+ assertEquals("Outside W",1, x) ;
+ }
+
+ @Test public void txn_write_03() {
+ Txn.execWrite(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ counter.commit() ;
+ }) ;
+ assertEquals("Outside W",1, counter.value()) ;
+ }
+
+ @Test public void txn_write_04() {
+ Txn.execWrite(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ counter.abort() ;
+ }) ;
+ assertEquals("Outside W", 0, counter.value()) ;
+ }
+
+ @Test public void txn_rw_1() {
+ assertEquals(0, counter.get()) ;
+
+ Txn.execWrite(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ }) ;
+
+ assertEquals("Direct value()", 1, counter.value()) ;
+ assertEquals("Direct get()", 1, counter.get()) ;
+
+ Txn.execRead(counter, () -> {
+ assertEquals("In R, value()", 1, counter.value()) ;
+ assertEquals("In R, get()", 1, counter.get()) ;
+ }) ;
+ }
+
+ @Test public void txn_rw_2() {
+ Txn.execRead(counter, () -> {
+ assertEquals("In R, value()", 0, counter.value()) ;
+ assertEquals("In R, get()", 0, counter.get()) ;
+ }) ;
+
+ Txn.execWrite(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 0, counter.value()) ;
+ assertEquals("In W, get()",1, counter.get()) ;
+ }) ;
+
+ assertEquals("Direct value()", 1, counter.get()) ;
+ assertEquals("Direct get()", 1, counter.get()) ;
+
+ Txn.execRead(counter, () -> {
+ assertEquals("In R, value()", 1, counter.value()) ;
+ assertEquals("In R, get()", 1, counter.get()) ;
+ }) ;
+ }
+
+ @Test public void txn_continue_1() {
+ Txn.execWrite(counter, ()->counter.set(91)) ;
+
+ Txn.execWrite(counter, ()-> {
+ assertEquals("In txn, value()", 91, counter.value()) ;
+ assertEquals("In txn, read()", 91, counter.read()) ;
+ counter.inc();
+ Txn.execWrite(counter, ()->{
+ assertEquals("In txn, value()", 91, counter.value()) ;
+ assertEquals("In txn, get()", 92, counter.read()) ;
+ }) ;
+ });
+ assertEquals(92,counter.value()) ;
+ }
+
+ @Test public void txn_continue_2() {
+ Txn.execWrite(counter, ()->counter.set(91)) ;
+
+ Txn.execWrite(counter, ()-> {
+ assertEquals("In txn, value()", 91, counter.value()) ;
+ assertEquals("In txn, read()", 91, counter.read()) ;
+ counter.inc();
+ Txn.execWrite(counter, ()->{
+ assertEquals("In txn, value()", 91, counter.value()) ;
+ assertEquals("In txn, get()", 92, counter.read()) ;
+ counter.inc();
+ }) ;
+ assertEquals("In txn, value()", 91, counter.value()) ;
+ assertEquals("In txn, read()", 93, counter.read()) ;
+ counter.inc();
+ });
+ assertEquals(94,counter.value()) ;
+ }
+
+ @Test(expected=ExceptionFromTest.class)
+ public void txn_exception_01() {
+ Txn.execWrite(counter, counter::inc) ;
+
+ Txn.execWrite(counter, () -> {
+ counter.inc() ;
+ assertEquals("In W, value()", 1, counter.value()) ;
+ assertEquals("In W, get()",2, counter.get()) ;
+ throw new ExceptionFromTest() ;
+ }) ;
+ }
+
+ @Test
+ public void txn_exception_02() {
+ Txn.execWrite(counter, ()->counter.set(8)) ;
+
+ try {
+ Txn.execWrite(counter, () -> {
+ counter.inc();
+ assertEquals("In W, value()", 8, counter.value());
+ assertEquals("In W, get()", 9, counter.get());
+ throw new ExceptionFromTest();
+ });
+ }
+ catch (ExceptionFromTest ex) {}
+ assertEquals("After W/abort, get()", 8, counter.get());
+ }
+
+ @Test
+ public void txn_exception_03() {
+ Txn.execWrite(counter, ()->counter.set(9)) ;
+
+ try {
+ Txn.execRead(counter, () -> {
+ assertEquals("In W, value()", 9, counter.value());
+ assertEquals("In W, get()", 9, counter.get());
+ throw new ExceptionFromTest();
+ });
+ }
+ catch (ExceptionFromTest ex) {}
+ assertEquals("After W/abort, get()", 9, counter.get());
+ }
+
+ // Tests for thread transactions.
+
+
+}
+
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java b/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
new file mode 100644
index 0000000..3cfa82b
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
@@ -0,0 +1,167 @@
+/*
+ * 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.system;
+
+import static org.junit.Assert.* ;
+
+import java.util.concurrent.atomic.AtomicLong ;
+
+import org.apache.jena.sparql.core.Transactional ;
+import org.apache.jena.sparql.core.TransactionalLock ;
+import org.apache.jena.system.Txn ;
+import org.junit.Test ;
+
+/** Lifecycle tests - apply tests to a provided Transactional
+ * but modify separate state.
+ */
+public class TestTxnLifecycle {
+ private AtomicLong counter = new AtomicLong(0) ;
+
+ // Not MR+SW (See TestTxn for fully transactional tests)
+ private Transactional trans = TransactionalLock.createMRSW() ;
+
+ @Test public void txn_lifecycle_01() {
+ Txn.execRead(trans, ()->{}) ;
+ }
+
+ @Test public void txn_lifecycle_02() {
+ Txn.execWrite(trans, ()->{}) ;
+ }
+
+ @Test public void txn_lifecycle_03() {
+ int x = Txn.execReadRtn(trans, ()->4) ;
+ assertEquals(4,x) ;
+ }
+
+ @Test public void txn_lifecycle_04() {
+ int x = Txn.execWriteRtn(trans, ()->5) ;
+ assertEquals(5,x) ;
+ }
+
+ @Test public void txn_lifecycle_05() {
+ int x = Txn.execWriteRtn(trans, ()-> {
+ // Continues outer transaction.
+ return Txn.execWriteRtn(trans, ()->56) ;
+ });
+ assertEquals(56,x) ;
+ }
+
+ @Test(expected=ExceptionFromTest.class)
+ public void txn_lifecycle_06() {
+ int x = Txn.execWriteRtn(trans, ()-> {
+ Txn.execWriteRtn(trans, ()-> {throw new ExceptionFromTest() ; }) ;
+ return 45 ;
+ });
+ fail("Should not be here!") ;
+ }
+
+ @Test public void txn_lifecycle_07() {
+ Txn.execWrite(trans, ()->trans.commit()) ;
+ }
+
+ @Test public void txn_lifecycle_08() {
+ Txn.execWrite(trans, ()->trans.abort()) ;
+ }
+
+ @Test public void txn_lifecycle_09() {
+ Txn.execRead(trans, ()->trans.commit()) ;
+ }
+ @Test public void txn_lifecycle_10() {
+ Txn.execRead(trans, ()->trans.abort()) ;
+ }
+
+ static void async(Runnable runnable) {
+ Thread thread = new Thread(runnable);
+ thread.start();
+ }
+
+ static void debug(String message) {
+ //System.out.println(message) ;
+ }
+
+ // Tests of isolation. Hard.
+
+ // Is this a real test?
+// @Test public void txn_lifecycle_isolation_01() {
+// Semaphore semaStep = new Semaphore(0) ;
+// Semaphore sema = new Semaphore(0) ;
+//
+// counter.set(15) ;
+// long x1 = counter.get() ;
+//
+// Runnable r = ()->{
+// Txn.executeWrite(trans, ()->{
+// debug("Thread 1");
+// // Start step.
+// semaStep.release();
+//
+// debug("Thread 2");
+// //Wait for test
+// sema.acquireUninterruptibly();
+//
+// debug("Thread 3");
+// // Make a change.
+// counter.incrementAndGet() ;
+//
+// debug("Thread 4");
+// // End step.
+// semaStep.release();
+//
+// debug("Thread 5");
+// // End change.
+// sema.release();
+//
+// debug("Thread 6");
+// });
+// } ;
+//
+// long x2 = counter.get() ;
+// assertEquals("x2", x1, x2) ;
+//
+// debug("Main 1");
+//
+// // Run!
+// async(r) ;
+//
+// debug("Main 2");
+//
+// // Let thread step
+// semaStep.acquireUninterruptibly();
+//
+// debug("Main 3");
+// // See what the state is (before change)
+// assertEquals(x1, counter.get()) ;
+// // Allow change
+// sema.release();
+//
+// debug("Main 4");
+// // Wait for change.
+// semaStep.acquireUninterruptibly();
+//
+// debug("Main 5");
+// // See what the state is (after change)
+// assertEquals(x1+1,counter.get()) ;
+// sema.acquireUninterruptibly();
+//
+// // Final state.
+// debug("Main 6");
+// long x3 = counter.get() ;
+// assertEquals(x1+1, x3) ;
+// }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/952aebd0/jena-arq/src/test/java/org/apache/jena/system/TestTxnThread.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestTxnThread.java b/jena-arq/src/test/java/org/apache/jena/system/TestTxnThread.java
new file mode 100644
index 0000000..2af8db9
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestTxnThread.java
@@ -0,0 +1,92 @@
+/*
+ * 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.system;
+
+import static org.junit.Assert.assertEquals ;
+import static org.junit.Assert.fail;
+
+import org.apache.jena.system.ThreadTxn ;
+import org.apache.jena.system.Txn ;
+import org.apache.jena.system.TxnCounter ;
+import org.junit.Test ;
+
+public class TestTxnThread {
+
+ TxnCounter counter = new TxnCounter(0) ;
+
+
+
+ // Tests for thread transactions.
+
+ @Test public void txnThread_1() {
+ ThreadTxn t = ThreadTxn.threadTxnRead(counter, ()->{}) ;
+ t.run();
+ }
+
+ @Test public void txnThread_2() {
+ ThreadTxn t = ThreadTxn.threadTxnWrite(counter, ()-> fail("")) ;
+ }
+
+ @Test(expected=AssertionError.class)
+ public void txnThread_3() {
+ ThreadTxn t = ThreadTxn.threadTxnWrite(counter, ()-> fail("")) ;
+ t.run() ;
+ }
+
+ @Test public void txnThread_10() {
+ long x1 = counter.get() ;
+ ThreadTxn t = ThreadTxn.threadTxnWrite(counter, ()->{ counter.inc() ;}) ;
+ long x2 = counter.get() ;
+ assertEquals("x2", x1, x2) ;
+ t.run() ;
+ long x3 = counter.get() ;
+ assertEquals("x3", x1+1, x3) ;
+ }
+
+ @Test public void txnThread_11() {
+ long x1 = counter.get() ;
+ Txn.execWrite(counter, ()->{
+ counter.inc();
+ // Read the "before" state
+ ThreadTxn t = ThreadTxn.threadTxnRead(counter, ()->{
+ long z1 = counter.get() ;
+ assertEquals("Thread read", x1, z1) ;
+ }) ;
+ counter.inc();
+ t.run();
+ }) ;
+ long x2 = counter.get() ;
+ assertEquals("after", x1+2, x2) ;
+ }
+
+ @Test public void txnThread_12() {
+ long x1 = counter.get() ;
+ ThreadTxn t = ThreadTxn.threadTxnRead(counter, () -> {
+ long z1 = counter.get() ;
+ assertEquals("Thread", x1, z1) ;
+ }) ;
+ Txn.execWrite(counter, ()->counter.inc()) ;
+ t.run() ;
+ long x2 = counter.get() ;
+ assertEquals("after", x1+1, x2) ;
+ }
+
+}
+
+
\ No newline at end of file
[5/6] jena git commit: Minor cleanup
Posted by an...@apache.org.
Minor cleanup
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/44784c62
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/44784c62
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/44784c62
Branch: refs/heads/master
Commit: 44784c627bb05355f2457cf0ece7dace63920ffe
Parents: 58b6b0e
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Jul 12 17:29:00 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Jul 12 17:29:00 2016 +0100
----------------------------------------------------------------------
.../tdb/transaction/TestTransactionUnionGraph.java | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/44784c62/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionUnionGraph.java
----------------------------------------------------------------------
diff --git a/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionUnionGraph.java b/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionUnionGraph.java
index 8c29f3f..2cbd310 100644
--- a/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionUnionGraph.java
+++ b/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionUnionGraph.java
@@ -18,6 +18,9 @@
package org.apache.jena.tdb.transaction;
+import static org.apache.jena.query.ReadWrite.READ ;
+import static org.apache.jena.query.ReadWrite.WRITE ;
+
import org.apache.jena.atlas.junit.BaseTest ;
import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.query.* ;
@@ -27,20 +30,12 @@ import org.apache.jena.tdb.TDB ;
import org.apache.jena.tdb.TDBFactory ;
import org.apache.jena.update.* ;
import org.junit.* ;
-import static org.apache.jena.query.ReadWrite.* ;
-/** Tests of transactions and the TDG union graph */
+/** Tests of transactions and the TDB union graph */
public class TestTransactionUnionGraph extends BaseTest
{
private Dataset ds ;
-// @BeforeClass public static void beforeClass()
-// {
-// ds = TDBFactory.createDataset() ;
-// ds.asDatasetGraph().add(SSE.parseQuad("(<g> <s> <p> 1)")) ;
-// }
-// @AfterClass public static void afterClass() { ds = null ; }
-
@Before
public void before()
{
@@ -48,7 +43,7 @@ public class TestTransactionUnionGraph extends BaseTest
ds.asDatasetGraph().add(SSE.parseQuad("(<g> <s> <p> 1)")) ;
}
- @After public void after() {}
+ @After public void after() { }
@Test public void uniontxn_global_r()
{
[3/6] jena git commit: Improve the explanation.
Posted by an...@apache.org.
Improve the explanation.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/7dc5b25a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/7dc5b25a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/7dc5b25a
Branch: refs/heads/master
Commit: 7dc5b25ae1855d6becfe1f8720f4bee9f9ace070
Parents: 52ff200
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Jul 10 15:39:44 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Jul 10 15:39:44 2016 +0100
----------------------------------------------------------------------
.../java/org/apache/jena/system/ThreadTxn.java | 59 ++++++++++----------
1 file changed, 31 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/7dc5b25a/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java b/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
index ada55b5..06e735e 100644
--- a/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
+++ b/jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java
@@ -47,7 +47,7 @@ public class ThreadTxn {
return ThreadTxn.create(trans, ReadWrite.READ, action, false) ;
}
- /** Create a thread-backed delayed WRITE action.
+ /** Create a thread-backed delayed WRITE action.
* Call {@link ThreadTxn#run} to perform the write transaction.
* (If called from inside a write transaction on the {@code trans},
* this will deadlock.)
@@ -61,16 +61,16 @@ public class ThreadTxn {
return ThreadTxn.create(trans, ReadWrite.WRITE, action, false) ;
}
- private final Semaphore semaStart ;
- private final Semaphore semaFinish ;
+ private final Semaphore semaStart = new Semaphore(0, true) ;
+ private final Semaphore semaFinish = new Semaphore(0, true) ;
+
+ // Catch the two kinds that do not need a "throws" clause.
private final AtomicReference<RuntimeException> thrownRuntimeException = new AtomicReference<>(null) ;
private final AtomicReference<Error> thrownError = new AtomicReference<>(null) ;
private final Runnable action ;
private ThreadTxn(Runnable action) {
this.action = action ;
- this.semaStart = new Semaphore(0, true) ;
- this.semaFinish = new Semaphore(0, true) ;
}
/**
@@ -78,6 +78,8 @@ public class ThreadTxn {
* {@link java.lang.RuntimeException} or {@link java.lang.Error}
*/
public void run() {
+ // Signal the thread, which is already running and inside
+ // the transaction, can now call the action.
semaStart.release();
semaFinish.acquireUninterruptibly() ;
if ( thrownError.get() != null )
@@ -102,47 +104,48 @@ public class ThreadTxn {
Objects.requireNonNull(action) ;
ThreadTxn threadAction = new ThreadTxn(action) ;
- // Startup semaphore so that the thread has started by the
- // time we exit this setup function.
- Semaphore semaStartup = new Semaphore(0, true) ;
+ // Startup semaphore so that the thread has started and entered the
+ // transaction by the time we exit this setup function.
+ Semaphore semaCreateStart = new Semaphore(0, true) ;
executor.execute( ()-> {
- // NB. trans.begin then semaStartup.release() ;
+ // NB. trans.begin then semaCreateStartup.release() ;
// This ensures that the transaction has really started.
trans.begin(mode) ;
// Signal the creator (see below) that the transaction has started.
- semaStartup.release() ;
+ semaCreateStart.release() ;
// Wait for the signal to run the action.
threadAction.semaStart.acquireUninterruptibly();
try {
- // Performane the action, catch and record any RuntimeException or Error.
+ // Perform the action, catching and recording any RuntimeException or Error.
threadAction.trigger() ;
// Finish transaction (if no throwable)
- if ( mode == ReadWrite.WRITE ) {
- if ( isCommit )
- trans.commit();
- else
- trans.abort() ;
- trans.end() ;
- } else {
- // Read
- if ( isCommit )
- trans.commit();
- trans.end() ;
+ switch (mode) {
+ case WRITE : {
+ if ( isCommit )
+ trans.commit() ;
+ else
+ trans.abort() ;
+ trans.end() ;
+ }
+ case READ : {
+ if ( isCommit )
+ trans.commit() ;
+ trans.end() ;
+ }
}
- }
- catch (Throwable ex) {
- // Surpress now it has trigger transaction mechanism in
- // the presence of an unchecked exception.
- // Passed to the main thread via ThreadTxn
+ }
+ catch (Throwable ex) {
+ // Surpress. trigger() recorded it and it is passed
+ // to the caller in run().
}
finally { threadAction.semaFinish.release() ; }
}) ;
// Don't return until the transaction has started.
- semaStartup.acquireUninterruptibly();
+ semaCreateStart.acquireUninterruptibly();
return threadAction ;
}
}
[4/6] jena git commit: Deal with a service URL with query string
Posted by an...@apache.org.
Deal with a service URL with query string
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/58b6b0e3
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/58b6b0e3
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/58b6b0e3
Branch: refs/heads/master
Commit: 58b6b0e34e02cd204329a6e1377967b6b1b4c326
Parents: 3bbe2d8
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Jul 12 13:33:57 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Jul 12 13:33:57 2016 +0100
----------------------------------------------------------------------
jena-fuseki2/apache-jena-fuseki/bin/s-delete | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-get | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-head | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-post | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-put | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-query | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-update | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/s-update-form | 9 ++++++++-
jena-fuseki2/apache-jena-fuseki/bin/soh | 9 ++++++++-
9 files changed, 72 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-delete
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-delete b/jena-fuseki2/apache-jena-fuseki/bin/s-delete
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-delete
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-delete
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-get
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-get b/jena-fuseki2/apache-jena-fuseki/bin/s-get
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-get
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-get
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-head
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-head b/jena-fuseki2/apache-jena-fuseki/bin/s-head
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-head
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-head
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-post
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-post b/jena-fuseki2/apache-jena-fuseki/bin/s-post
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-post
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-post
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-put
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-put b/jena-fuseki2/apache-jena-fuseki/bin/s-put
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-put
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-put
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-query
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-query b/jena-fuseki2/apache-jena-fuseki/bin/s-query
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-query
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-query
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-update
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-update b/jena-fuseki2/apache-jena-fuseki/bin/s-update
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-update
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-update
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/s-update-form
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/s-update-form b/jena-fuseki2/apache-jena-fuseki/bin/s-update-form
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/s-update-form
+++ b/jena-fuseki2/apache-jena-fuseki/bin/s-update-form
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
http://git-wip-us.apache.org/repos/asf/jena/blob/58b6b0e3/jena-fuseki2/apache-jena-fuseki/bin/soh
----------------------------------------------------------------------
diff --git a/jena-fuseki2/apache-jena-fuseki/bin/soh b/jena-fuseki2/apache-jena-fuseki/bin/soh
index 16cb44c..dcafe62 100755
--- a/jena-fuseki2/apache-jena-fuseki/bin/soh
+++ b/jena-fuseki2/apache-jena-fuseki/bin/soh
@@ -462,7 +462,14 @@ def SPARQL_query_GET(service, query, args2)
args = { "query" => query }
args.merge!(args2)
qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
- action="#{service}?#{qs}"
+
+ if service.include? "?"
+ then
+ action="#{service}&#{qs}"
+ else
+ action="#{service}?#{qs}"
+ end
+
headers={}
headers.merge!($headers)
headers[$hAccept]=$accept_results
[6/6] jena git commit: JENA-1090 : Merge commit 'refs/pull/153/head'
of github.com:apache/jena
Posted by an...@apache.org.
JENA-1090 : Merge commit 'refs/pull/153/head' of github.com:apache/jena
This closes #153.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/e4209054
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/e4209054
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/e4209054
Branch: refs/heads/master
Commit: e420905490cd6c8986b3276f89a372ea330f6448
Parents: 44784c6 7dc5b25
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Jul 12 19:10:20 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Jul 12 19:10:20 2016 +0100
----------------------------------------------------------------------
.../java/org/apache/jena/system/ThreadTxn.java | 151 ++++++++++++
.../main/java/org/apache/jena/system/Txn.java | 112 +++++++++
.../java/org/apache/jena/system/TxnCounter.java | 240 +++++++++++++++++++
.../org/apache/jena/sparql/ARQTestSuite.java | 2 +
.../apache/jena/system/ExceptionFromTest.java | 21 ++
.../java/org/apache/jena/system/TS_System.java | 32 +++
.../org/apache/jena/system/TestCounter.java | 145 +++++++++++
.../java/org/apache/jena/system/TestTxn.java | 238 ++++++++++++++++++
.../apache/jena/system/TestTxnLifecycle.java | 167 +++++++++++++
.../org/apache/jena/system/TestTxnThread.java | 92 +++++++
10 files changed, 1200 insertions(+)
----------------------------------------------------------------------
[2/6] jena git commit: Merge branch 'master' of
https://github.com/apache/jena into txn
Posted by an...@apache.org.
Merge branch 'master' of https://github.com/apache/jena into txn
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/52ff200c
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/52ff200c
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/52ff200c
Branch: refs/heads/master
Commit: 52ff200c2756c9844b4346ffa1bff2a09081b649
Parents: 952aebd 1028413
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jul 9 22:41:01 2016 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jul 9 22:41:01 2016 +0100
----------------------------------------------------------------------
.../apache/jena/sparql/engine/main/VarFinder.java | 9 +++++++--
.../java/org/apache/jena/sparql/util/ExprUtils.java | 3 ++-
.../java/org/apache/jena/atlas/logging/LogCtl.java | 16 +++++++++++++---
3 files changed, 22 insertions(+), 6 deletions(-)
----------------------------------------------------------------------