/*
 * 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");
                        }
                    }
                }
            }
        }
    }
}
