Index: tck2/src/java/org/apache/jdo/tck/query/api/QueryTimeout.java =================================================================== --- tck2/src/java/org/apache/jdo/tck/query/api/QueryTimeout.java (Revision 894745) +++ tck2/src/java/org/apache/jdo/tck/query/api/QueryTimeout.java (Arbeitskopie) @@ -1,153 +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.jdo.tck.query.api; - -import javax.jdo.PersistenceManager; -import javax.jdo.Query; -import javax.jdo.Transaction; -import javax.jdo.JDODataStoreException; - -import org.apache.jdo.tck.JDO_Test; -import org.apache.jdo.tck.pc.mylib.PCPoint; -import org.apache.jdo.tck.pc.mylib.PCPoint2; -import org.apache.jdo.tck.query.QueryTest; -import org.apache.jdo.tck.util.BatchTestRunner; - -/** - *Title: QueryTimeout - *
- *Keywords: query - *
- *Assertion ID: A14.6.1-7 - *
- *Assertion Description: -If a non-null timeout value is specified, a running query will be interrupted if -it exceeds the execution time of the timeout value. The thread executing the query -will throw JDOQueryTimeoutException. Specifying a timeout value of 0 indicates -that there is no timeout for this query (a setting of 0 overrides the default -specified in the Persistence-Manager or the PersistenceManagerFactory). - */ - -public class QueryTimeout extends QueryTest { - - /** */ - private static final String ASSERTION_FAILED = - "Assertion A14.6.1-7 (QueryTimeout) failed: "; - - /** Single String JDOQL Query. */ - private static String SSJDOQL = - "select avg (this.x + point2.y) " + - "from PCPoint " + - "where this.y >= 0 && point2.x >= 0 " + - "variables PCPoint2 point2 " + - "import org.apache.jdo.tck.pc.mylib.PCPoint; " + - "import org.apache.jdo.tck.pc.mylib.PCPoint2; "; - - /** Timeout value. */ - private static Integer TIMEOUT_MILLIS = new Integer(10); - - /** - * The main is called when the class - * is directly executed from the command line. - * @param args The arguments passed to the program. - */ - public static void main(String[] args) { - BatchTestRunner.run(QueryTimeout.class); - } - - /** Method to test setting query timeout. */ - public void testTimeout() throws Exception { - PersistenceManager pm = getPM(); - Transaction tx = pm.currentTransaction(); - - try { - tx.begin(); - Query query = pm.newQuery(SSJDOQL); - query.setDatastoreReadTimeoutMillis(TIMEOUT_MILLIS); - Object result = query.execute(); - tx.commit(); - tx = null; - fail(ASSERTION_FAILED, - "Query.execute should result in a JDOQueryTimeoutException."); - } - catch (JDODataStoreException ex) { - // expected exception - if (debug) { - logger.debug("caught expected exception " + ex); - } - } - finally { - if ((tx != null) && tx.isActive()) - tx.rollback(); - } - } - - /** Method to test setting query timeout to 0. */ - public void testZeroTimeout() throws Exception { - PersistenceManager pm = getPM(); - Transaction tx = pm.currentTransaction(); - - try { - tx.begin(); - Query query = pm.newQuery(SSJDOQL); - query.setDatastoreReadTimeoutMillis(0); - Object result = query.execute(); - tx.commit(); - tx = null; - } - catch (JDODataStoreException ex) { - // setting the timeout to 0 should not result in an exception - fail(ASSERTION_FAILED, - "Query.execute should not result in a JDOQueryTimeoutException."); - } - finally { - if ((tx != null) && tx.isActive()) - tx.rollback(); - } - } - - /** - * @see JDO_Test#localSetUp() - */ - protected void localSetUp() { - addTearDownClass(PCPoint.class); - addTearDownClass(PCPoint2.class); - - // create PCPoint and PCPoint2 instances - PersistenceManager pm = getPM(); - Transaction tx = pm.currentTransaction(); - try { - tx.begin(); - for (int i = 0; i < 1000; i++) { - PCPoint obj = new PCPoint(i, i); - pm.makePersistent(obj); - } - for (int i = 0; i < 1000; i++) { - PCPoint2 obj = new PCPoint2(i, i); - pm.makePersistent(obj); - } - tx.commit(); - tx = null; - } - finally { - if ((tx != null) && tx.isActive()) - tx.rollback(); - } - } -} - Index: tck2/src/java/org/apache/jdo/tck/api/persistencemanager/DatastoreTimeout.java =================================================================== --- tck2/src/java/org/apache/jdo/tck/api/persistencemanager/DatastoreTimeout.java (Revision 0) +++ tck2/src/java/org/apache/jdo/tck/api/persistencemanager/DatastoreTimeout.java (Revision 0) @@ -0,0 +1,422 @@ +/* + * 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.jdo.tck.api.persistencemanager; + +import java.util.List; + +import junit.framework.AssertionFailedError; + +import javax.jdo.JDOFatalException; +import javax.jdo.JDODataStoreException; +import javax.jdo.JDOUnsupportedOptionException; +import javax.jdo.PersistenceManager; +import javax.jdo.Query; +import javax.jdo.Transaction; + +import org.apache.jdo.tck.JDO_Test; +import org.apache.jdo.tck.pc.mylib.PCPoint; +import org.apache.jdo.tck.pc.mylib.PCRect; +import org.apache.jdo.tck.util.BatchTestRunner; +import org.apache.jdo.tck.util.ThreadExceptionHandler; + +/** + *Title: DatastoreTimeout + *
+ *Keywords: query, + *
+ *Assertion ID: A?? + *
+ *Assertion Description: + */ + +public class DatastoreTimeout extends JDO_Test { + + /** */ + private static final String ASSERTION_FAILED = + "Assertion A?? (DatastoreTimeout) failed: "; + + /** Timeout value for datastore read */ + private static Integer READ_TIMEOUT = new Integer(10); + + /** Timeout value for datastore write */ + private static Integer WRITE_TIMEOUT = new Integer(10); + + /** Time for the main thread to sleep after starting a parallel thread. */ + private static int MAIN_SLEEP_MILLIS = 1000; + + /** Time for the parallel threads to sleep before commit. */ + private static int THREAD_SLEEP_MILLIS = 7500; + + /** Oid of the PCRect instance created by localSetUp */ + private Object rectOid; + + /** Oid of the first PCPOint instance created by localSetUp */ + private Object point1Oid; + + /** Oid of the second PCPoint instance created by localSetUp */ + private Object point2Oid; + + /** + * The main is called when the class + * is directly executed from the command line. + * @param args The arguments passed to the program. + */ + public static void main(String[] args) { + BatchTestRunner.run(DatastoreTimeout.class); + } + + /** Method testing DatastoreReadTimeout. */ + public void testDatastoreReadTimeout() throws Exception { + + // Thread executing the query + ThreadExceptionHandler group = new ThreadExceptionHandler(); + ParallelWriter runnable = new ParallelWriter(); + Thread t = new Thread(group, runnable, "Parallel Writer"); + t.start(); + + // Wait for a second such that the other thread can lock the instancs + Thread.currentThread().sleep(MAIN_SLEEP_MILLIS); + + try { + runQueryReadingPCPointInstances(); + runGetObjectByIdReadingPCPointInstance(); + runNavigationalReadPCPointInstance(); + } + finally { + t.join(); + Throwable problem = group.getUncaughtException(t); + if (problem != null) { + if (problem instanceof AssertionFailedError) + throw (AssertionFailedError)problem; + else + throw new JDOFatalException( "Thread " + t.getName()+ + " results in exception ", problem); + } + } + } + + /** Method testing DatastoreWriteTimeout. */ + public void testDatastoreWriteTimeout() throws Exception { + + // Thread executing the query + ThreadExceptionHandler group = new ThreadExceptionHandler(); + ParallelReader runnable = new ParallelReader(); + Thread t = new Thread(group, runnable, "Parallel Reader"); + t.start(); + + // Wait for a second such that the other thread can lock the instancs + Thread.currentThread().sleep(1000); + + try { + runUpdatePCointInstance(); + runDeletePCPointInstance(); + runDeletePCPointInstancesByQuery(); + } + finally { + t.join(); + Throwable problem = group.getUncaughtException(t); + if (problem != null) { + if (problem instanceof AssertionFailedError) + throw (AssertionFailedError)problem; + else + throw new JDOFatalException( "Thread " + t.getName()+ + " results in exception ", problem); + } + } + } + + /** + * @see JDO_Test#localSetUp() + */ + protected void localSetUp() { + addTearDownClass(PCRect.class); + addTearDownClass(PCPoint.class); + + getPM(); + try { + Transaction tx = pm.currentTransaction(); + tx.begin(); + PCPoint p1 = new PCPoint(110, 120); + PCPoint p2 = new PCPoint(130, 140); + PCRect rect = new PCRect (0, p1, p2); + pm.makePersistent (rect); + tx.commit(); + rectOid = pm.getObjectId(rect); + point1Oid = pm.getObjectId(p1); + point2Oid = pm.getObjectId(p2); + } + finally { + cleanupPM(); + } + } + + // ----------------- Helper methods --------------------------- + + /** DatastoreReadTimeout helper method: query reading PCPoint instance. */ + private void runQueryReadingPCPointInstances() { + getPM(); + try { + pm.currentTransaction().begin(); + Query q = pm.newQuery(PCPoint.class); + q.setDatastoreReadTimeoutMillis(READ_TIMEOUT); + List result = (List)q.execute(); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.setDatastoreReadTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.setDatastoreReadTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.execute should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + /** DatastoreReadTimeout helper method: getObjectById reading PCPoint instance. */ + private void runGetObjectByIdReadingPCPointInstance() { + getPM(); + try { + pm.currentTransaction().begin(); + pm.setDatastoreReadTimeoutMillis(READ_TIMEOUT); + PCPoint point1 = (PCPoint)pm.getObjectById(point1Oid, true); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreReadTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreReadTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.getObjectById should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + /** DatastoreReadTimeout helper method: navigation reading PCPoint instance. */ + private void runNavigationalReadPCPointInstance() { + getPM(); + try { + pm.currentTransaction().begin(); + pm.setDatastoreReadTimeoutMillis(READ_TIMEOUT); + PCRect rect = (PCRect)pm.getObjectById(rectOid, true); + PCPoint p1 = rect.getUpperLeft(); + p1.name(); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreReadTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreReadTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Navigational access should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + /** DatastoreWriteTimeout helper method: update PCPoint instance. */ + private void runUpdatePCointInstance() { + getPM(); + try { + pm.currentTransaction().begin(); + pm.setDatastoreWriteTimeoutMillis(WRITE_TIMEOUT); + PCPoint point1 = (PCPoint)pm.getObjectById(point1Oid, true); + point1.setX(500); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreWriteTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreWriteTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.getObjectById should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + /** DatastoreWriteTimeout helper method: delete PCPoint instance. */ + private void runDeletePCPointInstance() { + getPM(); + try { + pm.currentTransaction().begin(); + pm.setDatastoreWriteTimeoutMillis(WRITE_TIMEOUT); + PCPoint point1 = (PCPoint)pm.getObjectById(point1Oid, true); + pm.deletePersistent(point1); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreWriteTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.setDatastoreWriteTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "PM.getObjectById should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + /** DatastoreWriteTimeout helper method: delete by query. */ + private void runDeletePCPointInstancesByQuery() { + getPM(); + try { + pm.currentTransaction().begin(); + Query q = pm.newQuery(PCPoint.class); + q.setDatastoreWriteTimeoutMillis(WRITE_TIMEOUT); + q.deletePersistentAll(); + pm.currentTransaction().commit(); + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.setDatastoreWriteTimeoutMillis should throw a " + + "JDOUnsupportedOptionException, if datastore timeout is not supported "); + } + } + catch (JDOUnsupportedOptionException ex) { + if (isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.setDatastoreWriteTimeoutMillis should not result " + + "in a JDOUnsupportedOptionException, if datastore timeout is supported "); + } + } + catch (JDODataStoreException ex) { + if (!isDatastoreTimeoutSupported()) { + fail(ASSERTION_FAILED, "Query.deletePersistentAll should not result in a " + + "JDODataStoreException, if datastore timeout is not supported."); + } + } + finally { + cleanupPM(); + } + } + + // ------------- Helper classes ------------------------------- + + /** Runnable class updating instances and causing them to be read locked. */ + class ParallelReader implements Runnable { + + ParallelReader() { } + + public void run() { + PersistenceManager parallelPM = getPMF().getPersistenceManager(); + Transaction tx = parallelPM.currentTransaction(); + // Run datastore transaction + tx.setOptimistic(false); + try { + tx.begin(); + // read PCPoint instances + PCPoint p1 = (PCPoint)parallelPM.getObjectById(point1Oid, true); + p1.name(); + PCPoint p2 = (PCPoint)parallelPM.getObjectById(point2Oid, true); + p2.name(); + // Give the main thread a chance to try to write the instances + Thread.currentThread().sleep(THREAD_SLEEP_MILLIS); + tx.commit(); + } + catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + finally { + cleanupPM(parallelPM); + } + } + } + + /** Runnable class updating instances and causing them to be write locked. */ + class ParallelWriter implements Runnable { + + ParallelWriter() { } + + public void run() { + PersistenceManager parallelPM = getPMF().getPersistenceManager(); + Transaction tx = parallelPM.currentTransaction(); + // Run datastore transaction + tx.setOptimistic(false); + try { + tx.begin(); + PCPoint p1 = (PCPoint)parallelPM.getObjectById(point1Oid); + p1.setX(210); + p1.setY(220); + PCPoint p2 = (PCPoint)parallelPM.getObjectById(point2Oid); + p2.setX(230); + p2.setY(240); + // Flush will set a write lock on the instances + parallelPM.flush(); + // Give the main thread a chance to try to read the instances + Thread.currentThread().sleep(THREAD_SLEEP_MILLIS); + tx.commit(); + } + catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + finally { + cleanupPM(parallelPM); + } + } + } + +} + Index: tck2/src/java/org/apache/jdo/tck/JDO_Test.java =================================================================== --- tck2/src/java/org/apache/jdo/tck/JDO_Test.java (Revision 894745) +++ tck2/src/java/org/apache/jdo/tck/JDO_Test.java (Arbeitskopie) @@ -878,6 +878,12 @@ "javax.jdo.option.QueryCancel"); } + /** Reports whether setting a Datastore timout is supported. */ + public boolean isDatastoreTimeoutSupported() { + return supportedOptions.contains( + "javax.jdo.option.DatastoreTimeout"); + } + /** Reports whether a feature is supported */ public boolean isSupported(String option) { return supportedOptions.contains(option); Index: tck2/src/conf/jdo-2_3-signatures.txt =================================================================== --- tck2/src/conf/jdo-2_3-signatures.txt (Revision 894745) +++ tck2/src/conf/jdo-2_3-signatures.txt (Arbeitskopie) @@ -126,6 +126,8 @@ = "javax.jdo.option.GetDataStoreConnection"; static String OPTION_GET_JDBC_CONNECTION = "javax.jdo.option.GetJDBCConnection"; + static String OPTION_DATASTORE_TIMEOUT + = "javax.jdo.option.DatastoreTimeout"; static String OPTION_QUERY_SQL = "javax.jdo.query.SQL"; static String OPTION_UNCONSTRAINED_QUERY_VARIABLES @@ -781,8 +783,10 @@ public varargs java.util.Set getManagedObjects(Class[] classes); public varargs java.util.Set getManagedObjects(java.util.EnumSet states, Class[] classes); javax.jdo.FetchGroup getFetchGroup(Class cls, String name); - public void setQueryTimeoutMillis(Integer interval); - public Integer getQueryTimeoutMillis(); + public void setDatastoreReadTimeoutMillis(Integer interval); + public Integer getDatastoreReadTimeoutMillis(); + public void setDatastoreWriteTimeoutMillis(Integer interval); + public Integer getDatastoreWriteTimeoutMillis(); } public interface javax.jdo.PersistenceManagerFactory extends java.io.Serializable { @@ -851,8 +855,10 @@ public void registerMetadata(javax.jdo.metadata.JDOMetadata metadata); public javax.jdo.metadata.JDOMetadata newMetadata(); public javax.jdo.metadata.TypeMetadata getMetadata(String className); - public void setQueryTimeoutMillis(Integer interval); - public Integer getQueryTimeoutMillis(); + public void setDatastoreReadTimeoutMillis(Integer interval); + public Integer getDatastoreReadTimeoutMillis(); + public void setDatastoreWriteTimeoutMillis(Integer interval); + public Integer getDatastoreWriteTimeoutMillis(); } public interface javax.jdo.Query extends java.io.Serializable { @@ -896,12 +902,14 @@ public long deletePersistentAll(); public void setUnmodifiable(); public boolean isUnmodifiable(); - public void setTimeoutMillis(Integer interval); - public Integer getTimeoutMillis(); public void cancelAll(); public void cancel(Thread); public Boolean getSerializeRead(); public void setSerializeRead(Boolean); + public void setDatastoreReadTimeoutMillis(Integer interval); + public Integer getDatastoreReadTimeoutMillis(); + public void setDatastoreWriteTimeoutMillis(Integer interval); + public Integer getDatastoreWriteTimeoutMillis(); } public interface javax.jdo.spi.Detachable { Index: tck2/src/conf/query.conf =================================================================== --- tck2/src/conf/query.conf (Revision 894745) +++ tck2/src/conf/query.conf (Arbeitskopie) @@ -51,7 +51,6 @@ org.apache.jdo.tck.query.api.NewQuerySingleString \ org.apache.jdo.tck.query.api.QueryCancel \ org.apache.jdo.tck.query.api.QueryExtentions \ -org.apache.jdo.tck.query.api.QueryTimeout \ org.apache.jdo.tck.query.api.SetCandidateCollection \ org.apache.jdo.tck.query.api.SetCandidateExtent \ org.apache.jdo.tck.query.api.SetFilter \ Index: tck2/src/conf/pm.conf =================================================================== --- tck2/src/conf/pm.conf (Revision 894745) +++ tck2/src/conf/pm.conf (Arbeitskopie) @@ -27,6 +27,7 @@ org.apache.jdo.tck.api.persistencemanager.DataStoreCacheTest \ org.apache.jdo.tck.api.persistencemanager.DataStoreConnection \ org.apache.jdo.tck.api.persistencemanager.DataStoreConnectionThrows \ +org.apache.jdo.tck.api.persistencemanager.DatastoreTimeout \ org.apache.jdo.tck.api.persistencemanager.DeletePersistent \ org.apache.jdo.tck.api.persistencemanager.DeletePersistentAllFails \ org.apache.jdo.tck.api.persistencemanager.DeletePersistentFailsIfInstanceIsTransient \