| /* |
| * 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 |
| <<<<<<< Updated upstream |
| * |
| * 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 |
| ======= |
| * |
| * https://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 |
| >>>>>>> Stashed changes |
| * limitations under the License. |
| */ |
| |
| package org.apache.jdo.tck.api.persistencemanager; |
| |
| import java.util.List; |
| import javax.jdo.JDODataStoreException; |
| import javax.jdo.JDOFatalException; |
| import javax.jdo.JDOUnsupportedOptionException; |
| import javax.jdo.PersistenceManager; |
| import javax.jdo.Query; |
| import javax.jdo.Transaction; |
| import junit.framework.AssertionFailedError; |
| 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; |
| |
| /** |
| * <B>Title:</B> DatastoreTimeout <br> |
| * <B>Keywords:</B> datastore timeout <br> |
| * <B>Assertion ID:</B> A12.6.9-1, A14.6.1-7 <br> |
| * <B>Assertion Description: </B> |
| */ |
| public class DatastoreTimeout extends JDO_Test { |
| |
| /** */ |
| private static final String ASSERTION_FAILED = |
| "Assertion A12.6.9-1, A14.6.1-7 (DatastoreTimeout) failed: "; |
| |
| /** Timeout value for datastore read */ |
| private static final Integer READ_TIMEOUT = Integer.valueOf(100); |
| |
| /** Timeout value for datastore write */ |
| private static final Integer WRITE_TIMEOUT = Integer.valueOf(100); |
| |
| /** Zero Timeout value */ |
| private static final Integer ZERO_TIMEOUT = Integer.valueOf(0); |
| |
| /** Time for the main thread to sleep after starting a parallel thread. */ |
| private static final int MAIN_SLEEP_MILLIS = 1000; |
| |
| /** Time for the parallel threads to sleep before commit. */ |
| private static final int THREAD_SLEEP_MILLIS_SHORT = 2500; |
| |
| /** Time for the parallel threads to sleep before commit. */ |
| private static final int THREAD_SLEEP_MILLIS_LONG = 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 <code>main</code> 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. |
| * |
| * @throws Exception exception |
| */ |
| public void testDatastoreReadTimeout() throws Exception { |
| |
| if (debug) logger.debug("isDatastoreTimeoutSupported:" + isDatastoreTimeoutSupported()); |
| |
| // Parallel thread writing the instances and causing them to be locked |
| ThreadExceptionHandler group = new ThreadExceptionHandler(); |
| ParallelWriter runnable = new ParallelWriter(THREAD_SLEEP_MILLIS_LONG); |
| Thread t = new Thread(group, runnable, "Parallel Writer"); |
| t.start(); |
| |
| // Wait for a second such that the other thread can lock the instances |
| Thread.sleep(MAIN_SLEEP_MILLIS); |
| |
| try { |
| runQueryReadingPCPointInstances(READ_TIMEOUT); |
| runGetObjectByIdReadingPCPointInstance(READ_TIMEOUT); |
| runNavigationalReadPCPointInstance(READ_TIMEOUT); |
| } 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. |
| * |
| * @throws Exception exception |
| */ |
| public void testDatastoreWriteTimeout() throws Exception { |
| |
| if (debug) logger.debug("isDatastoreTimeoutSupported:" + isDatastoreTimeoutSupported()); |
| |
| // Parallel thread reading the instances and causing them to be locked |
| ThreadExceptionHandler group = new ThreadExceptionHandler(); |
| ParallelReader runnable = new ParallelReader(THREAD_SLEEP_MILLIS_LONG); |
| Thread t = new Thread(group, runnable, "Parallel Reader"); |
| t.start(); |
| |
| // Wait for a second such that the other thread can lock the instances |
| Thread.sleep(MAIN_SLEEP_MILLIS); |
| |
| try { |
| runUpdatePCointInstance(WRITE_TIMEOUT); |
| runDeletePCPointInstance(WRITE_TIMEOUT); |
| runDeletePCPointInstancesByQuery(WRITE_TIMEOUT); |
| } 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 zero DatastoreReadTimeout. |
| * |
| * @throws Exception exception |
| */ |
| public void testZeroDatastoreReadTimeout() throws Exception { |
| |
| // Parallel thread writing the instances and causing them to be locked |
| ThreadExceptionHandler group = new ThreadExceptionHandler(); |
| ParallelWriter runnable = new ParallelWriter(THREAD_SLEEP_MILLIS_SHORT); |
| Thread t = new Thread(group, runnable, "Parallel Writer"); |
| t.start(); |
| |
| // Wait for a second such that the other thread can lock the instances |
| Thread.sleep(MAIN_SLEEP_MILLIS); |
| |
| try { |
| runQueryReadingPCPointInstances(ZERO_TIMEOUT); |
| } 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 zero DatastoreWriteTimeout. |
| * |
| * @throws Exception exception |
| */ |
| public void testZeroDatastoreWriteTimeout() throws Exception { |
| |
| // Parallel thread reading the instances and causing them to be locked |
| ThreadExceptionHandler group = new ThreadExceptionHandler(); |
| ParallelReader runnable = new ParallelReader(THREAD_SLEEP_MILLIS_SHORT); |
| Thread t = new Thread(group, runnable, "Parallel Reader"); |
| t.start(); |
| |
| // Wait for a second such that the other thread can lock the instances |
| Thread.sleep(MAIN_SLEEP_MILLIS); |
| |
| try { |
| runUpdatePCointInstance(ZERO_TIMEOUT); |
| } 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 org.apache.jdo.tck.JDO_Test#localSetUp() |
| */ |
| @Override |
| 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(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| Query<PCPoint> q = pm.newQuery(PCPoint.class); |
| q.setDatastoreReadTimeoutMillis(timeout); |
| @SuppressWarnings("unused") |
| List<PCPoint> result = q.executeList(); |
| 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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "Query.execute should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| /** DatastoreReadTimeout helper method: getObjectById reading PCPoint instance. */ |
| private void runGetObjectByIdReadingPCPointInstance(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| pm.setDatastoreReadTimeoutMillis(timeout); |
| @SuppressWarnings("unused") |
| 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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "PM.getObjectById should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| /** DatastoreReadTimeout helper method: navigation reading PCPoint instance. */ |
| private void runNavigationalReadPCPointInstance(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| pm.setDatastoreReadTimeoutMillis(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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "Navigational access should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| /** DatastoreWriteTimeout helper method: update PCPoint instance. */ |
| private void runUpdatePCointInstance(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| pm.setDatastoreWriteTimeoutMillis(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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "PM.getObjectById should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| /** DatastoreWriteTimeout helper method: delete PCPoint instance. */ |
| private void runDeletePCPointInstance(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| pm.setDatastoreWriteTimeoutMillis(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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "PM.getObjectById should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| /** DatastoreWriteTimeout helper method: delete by query. */ |
| private void runDeletePCPointInstancesByQuery(Integer timeout) { |
| getPM(); |
| try { |
| pm.currentTransaction().begin(); |
| Query<PCPoint> q = pm.newQuery(PCPoint.class); |
| q.setDatastoreWriteTimeoutMillis(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."); |
| } else if (timeout == ZERO_TIMEOUT) { |
| fail( |
| ASSERTION_FAILED, |
| "Query.deletePersistentAll should not result in a " |
| + "JDODataStoreException, if zero timeout is specified (meaning no timeout)."); |
| } |
| } finally { |
| cleanupPM(); |
| } |
| } |
| |
| // ------------- Helper classes ------------------------------- |
| |
| /** Runnable class updating instances and causing them to be read locked. */ |
| class ParallelReader implements Runnable { |
| |
| private final int sleepMillis; |
| |
| ParallelReader(int sleepMillis) { |
| this.sleepMillis = sleepMillis; |
| } |
| |
| 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.sleep(sleepMillis); |
| 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 { |
| |
| private final int sleepMillis; |
| |
| ParallelWriter(int sleepMillis) { |
| this.sleepMillis = sleepMillis; |
| } |
| |
| 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.sleep(sleepMillis); |
| tx.commit(); |
| } catch (InterruptedException ex) { |
| throw new RuntimeException(ex); |
| } finally { |
| cleanupPM(parallelPM); |
| } |
| } |
| } |
| } |