/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.testing.tests.clientserver; import org.eclipse.persistence.descriptors.ClassDescriptor; import org.eclipse.persistence.exceptions.*; import org.eclipse.persistence.sessions.DatabaseLogin; import org.eclipse.persistence.sessions.Session; import org.eclipse.persistence.queries.*; import org.eclipse.persistence.testing.framework.*; @SuppressWarnings("deprecation") public class ConcurrentTestRefreshWithOptimisticLocking extends org.eclipse.persistence.testing.framework.AutoVerifyTestCase { public static int numThreads = 6; public boolean isCheckerThread; public static Server server; public static boolean execute = true; public static Thread[] threadList = new Thread[numThreads]; public static long[] timeList = new long[numThreads]; public static long runTime; public int index; public boolean oldVersionRefresh; public ConcurrentTestRefreshWithOptimisticLocking(long runtime) { setDescription("Test Simulates a highly concurrent situation with refreshing and optimistic locks"); ConcurrentTestRefreshWithOptimisticLocking.runTime = runtime; } protected ConcurrentTestRefreshWithOptimisticLocking(boolean checkerThread, int index) { this.isCheckerThread = checkerThread; this.index = index; } public void reset() { ConcurrentTestRefreshWithOptimisticLocking.execute = false; for (int count = 0; count < numThreads; ++count) { try { ConcurrentTestRefreshWithOptimisticLocking.threadList[count].join(); } catch (InterruptedException ex) { throw new TestProblemException("Test thread was interrupted. Test failed to run properly"); } } ConcurrentTestRefreshWithOptimisticLocking.server.serverSession.getClassDescriptor(DeadLockEmployee.class).setShouldOnlyRefreshCacheIfNewerVersion(this.oldVersionRefresh); ConcurrentTestRefreshWithOptimisticLocking.server.logout(); } public void setup() { ConcurrentTestRefreshWithOptimisticLocking.execute = true; try { getSession().getLog().write("WARNING, some tests may take 3 minutes or more"); getSession().getLog().flush(); } catch (java.io.IOException e) { } try { DatabaseLogin login = (DatabaseLogin)getSession().getLogin().clone(); ConcurrentTestRefreshWithOptimisticLocking.server = new Server(login, numThreads, numThreads + 2); ConcurrentTestRefreshWithOptimisticLocking.server.serverSession.setSessionLog(getSession().getSessionLog()); ConcurrentTestRefreshWithOptimisticLocking.server.login(); ConcurrentTestRefreshWithOptimisticLocking.server.copyDescriptors(getSession()); ClassDescriptor empDesc = this.server.serverSession.getClassDescriptor(DeadLockEmployee.class); this.oldVersionRefresh = empDesc.shouldOnlyRefreshCacheIfNewerVersion(); empDesc.onlyRefreshCacheIfNewerVersion(); } catch (ValidationException ex) { this.verify(); } for (int count = 0; count < numThreads; ++count) { ConcurrentTestRefreshWithOptimisticLocking.threadList[count] = new Thread(new ConcurrentTestRefreshWithOptimisticLocking(false, count).runnable()); ConcurrentTestRefreshWithOptimisticLocking.timeList[count] = System.currentTimeMillis(); } } public void test() { for (int count = 0; count < numThreads; ++count) { ConcurrentTestRefreshWithOptimisticLocking.threadList[count].start(); } Thread checker = new Thread(new ConcurrentTestRefreshWithOptimisticLocking(true, -1).runnable()); checker.start(); try { checker.join(); } catch (InterruptedException ex) { throw new TestProblemException("Test thread was interrupted. Test failed to run properly"); } } public void verify() { if (!execute) { for (int count = 0; count < numThreads; ++count) { threadList[count].stop(); } ConcurrentTestRefreshWithOptimisticLocking.execute = true; getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); throw new TestErrorException("This test caused a deadlock in TopLink. see bug 33883838"); } } public Runnable runnable() { return new Runnable() { // This section represents the executing threads // If the type is set to checker then this set the thread // to watch the other threads for deadlock. If none occurs then // the test will time out. public void run() { if (org.eclipse.persistence.testing.tests.clientserver.ConcurrentTestRefreshWithOptimisticLocking.this.isCheckerThread) { watchOtherThreads(); } else { executeUntilStopped(); } } }; } public void watchOtherThreads() { long startTime = System.currentTimeMillis(); while (((System.currentTimeMillis() - startTime) < (runTime + 30000)) && ConcurrentTestRefreshWithOptimisticLocking.execute) { for (int localIdex = 0; localIdex < numThreads; ++localIdex) { if ((System.currentTimeMillis() - ConcurrentTestRefreshWithOptimisticLocking.timeList[localIdex]) > 30000) { // System.out.println(" Number: " + localIdex + " time: " + (System.currentTimeMillis() - this.timeList[localIdex])); execute = false; break; } } try { Thread.sleep(30000); } catch (InterruptedException ex) { throw new TestProblemException("Test thread was interrupted. Test failed to run properly"); } } } public void executeUntilStopped() { Session session = ConcurrentTestRefreshWithOptimisticLocking.server.serverSession.acquireClientSession(); DeadLockAddress address = (DeadLockAddress)session.readObject(org.eclipse.persistence.testing.tests.clientserver.DeadLockAddress.class); DeadLockEmployee employee = (DeadLockEmployee)session.readObject(DeadLockEmployee.class); ReadObjectQuery query; if ((this.index % 2) != 0) { query = new ReadObjectQuery(address); query.refreshIdentityMapResult(); query.setCascadePolicy(DatabaseQuery.CascadeAllParts); } else { query = new ReadObjectQuery(employee); query.refreshIdentityMapResult(); query.setCascadePolicy(DatabaseQuery.CascadeAllParts); } while (ConcurrentTestRefreshWithOptimisticLocking.execute) { ConcurrentTestRefreshWithOptimisticLocking.timeList[this.index] = System.currentTimeMillis(); session.executeQuery(query); } // System.out.println("BeingShutDown"); } }