blob: 51e6e650dc0cd7db702b028f9b017ee672ddbe22 [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.sessions.DatabaseLogin;
/**
* The following test realises the following concurrent scenario:
* Client0 creates in a single transaction 5 Employees, than 5 Projects;
* Client1 creates in a single transaction 5 Projects, than 5 Employees.
*
* this.server.serverSession.getSequencingControl().setShouldUseSeparateConnection(true)
* line in setup insures that a separate sequencing connection pool is used - which
* allows to avoid deadlock.
* Note that if the line is changed to:
* this.server.serverSession.getSequencingControl().setShouldUseSeparateConnection(false);
* the deadlock will occur.
* Some dbs (Oracle) use deadlock-avoidance strategies. To defy those, Client0 waits after creating
* 5 Employees until Client1 will creates its 5 Projects - this would insure a deadlock in "false" case
*/
@SuppressWarnings("deprecation")
public class ClientServerSequenceDeadlockTest2 extends ClientServerSequenceDeadlockTest {
protected FIFO[] fifoInArray;
protected boolean[] firstHalfDone;
/**
*
*/
public ClientServerSequenceDeadlockTest2() {
super();
fifoInArray = new FIFO[NUM_CLIENTS];
firstHalfDone = new boolean[NUM_CLIENTS];
numObjects = 10;
setDescription("Tests concurrent writing of objects of two types for sequencing deadlock - one big transaction per thread");
}
/**
*
*/
@Override
public void setup() {
this.login = (DatabaseLogin)getSession().getLogin().clone();
this.server = new Server(this.login);
this.server.serverSession.setSessionLog(getSession().getSessionLog());
this.server.serverSession.getLogin().getDefaultSequence().setPreallocationSize(numObjects / 2);
this.server.serverSession.getSequencingControl().setShouldUseSeparateConnection(true);
this.server.login();
this.server.copyDescriptors(getSession());
for (int i = 0; i < NUM_CLIENTS; i++) {
boolean createEmployeesFirst = (i % 2) == 0;
fifoArray[i] = new FIFO(numObjects);
fifoInArray[i] = new FIFO(numObjects);
getClients().addElement(new EmployeeSeqDeadlockClient2(this.server, getSession(), "Client " + i, numObjects, createEmployeesFirst, fifoArray[i], fifoInArray[i]));
clientStateArray[i] = THREAD_UNDEFINED;
clientLastActionTimeArray[i] = 0;
firstHalfDone[i] = false;
}
doneClients = 0;
deadlock = false;
}
/**
*
*/
@Override
public void test() {
for (int i = 0; i < NUM_CLIENTS; i++) {
EmployeeSeqDeadlockClient client = (EmployeeSeqDeadlockClient)clients.elementAt(i);
client.start();
clientStateArray[i] = THREAD_RUNNING;
}
while (doneClients < NUM_CLIENTS) {
for (int i = 0; i < NUM_CLIENTS; i++) {
if (clientStateArray[i] == THREAD_RUNNING) {
if ((NUM_CLIENTS - doneClients) == 1) {
((EmployeeClient)getClients().elementAt(i)).pleaseStop();
}
long currentTime = System.currentTimeMillis();
if (!fifoArray[i].isEmpty()) {
clientLastActionTimeArray[i] = currentTime;
int objectNumber = (Integer) fifoArray[i].removeHead();
// System.out.println("Client# = " + i + " object# = " + objectNumber);
if (objectNumber == (numObjects / 2)) {
firstHalfDone[i] = true;
boolean firstHalfDoneForAll = true;
for (int j = 0; j < NUM_CLIENTS; j++) {
firstHalfDoneForAll = firstHalfDoneForAll && firstHalfDone[j];
}
if (firstHalfDoneForAll) {
for (int j = 0; j < NUM_CLIENTS; j++) {
fifoInArray[j].insertTail(Boolean.TRUE);
}
}
}
if ((objectNumber == numObjects) || (objectNumber == -1)) {
clientStateArray[i] = THREAD_EXITED;
doneClients++;
// System.out.println("Client# = " + i + " EXITED");
}
} else {
if (clientLastActionTimeArray[i] == 0) {
clientLastActionTimeArray[i] = System.currentTimeMillis();
} else if ((currentTime - clientLastActionTimeArray[i]) >= TIME_TO_PRESUME_DEADLOCK) {
clientStateArray[i] = THREAD_LOCKED;
deadlock = true;
doneClients++;
((Thread)getClients().elementAt(i)).stop();
// System.out.println("Client# = " + i + " DEADLOCK");
}
}
}
}
}
}
}