blob: a3370985441e00e0b471be41d4e798a360026db2 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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;
}
@Override
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();
}
@Override
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 = 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();
}
}
@Override
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");
}
}
@Override
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.
@Override
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");
}
}