/*
 * 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.feature;

import java.util.Comparator;
import java.util.Arrays;

import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.sessions.server.Server;

import org.eclipse.persistence.testing.framework.TestCase;
import org.eclipse.persistence.testing.models.employee.domain.Employee;

/**
 * This testcase test the thread-safeness of TopLink's sequencing. The type of sequencing specified in the login
 * info is tested (either native or table sequencing is used). To test the other kind of sequencing you must logout,
 * change you login info, login, and rerun the test.
 * The test start a number of threads. Each thread generates a number of sequence numbers. For this test the
 * preallocation size is set to 1. This maximizes the concurrency of the threads and increases the effectiveness
 * of this test.
 * The choice of number of threads and iterations must be large enough for the test to be effective. I got this test
 * to fail (with the 2.5.1.1 sequences bug) with 5 threads and 50 iterations.
 *
 * Caveat: This test cannot prove that sequencing is thread safe, it can only prove that it is not.
 *
 * author: Robert Campbell
 */
public class SequencingConcurrencyTest extends TestCase implements Comparator {
    public java.util.Vector sequences;
    public SequencingConcurrencyTest[] tests;
    public int nThreads;
    public boolean useServerSession;
    public boolean useSeparateConnection;
    public Server serverSession;
    public DatabaseSession dbSession;
    public int previousSequencePreallocationSize;
    public int sequencePreallocationSize;
    public boolean useSeparateConnectionOriginal;
    public boolean shouldLogMessages;
    public int originalLogLevel;
    public int nIterations;
    public Session session;
    public int threadNumber;
    public boolean handleException;
    public Exception exception;

    protected SequencingConcurrencyTest(int threadNumber, int nIterations, java.util.Vector sequences, Session session, boolean handleException) {
        this.threadNumber = threadNumber;
        this.nIterations = nIterations;
        this.sequences = sequences;
        this.session = session;
        this.handleException = handleException;
    }

    /**
     * To be called by testing framework.
     */
    public SequencingConcurrencyTest(int nThreads, int nIterations, boolean useServerSession, boolean useSeparateConnection) {
        this(nThreads, nIterations, useServerSession, useSeparateConnection, 1);
    }

    /**
     * To be called by testing framework.
     */
    public SequencingConcurrencyTest(int nThreads, int nIterations, boolean useServerSession, boolean useSeparateConnection, int sequencePreallocationSize) {
        this.nThreads = nThreads;
        this.nIterations = nIterations;
        this.useServerSession = useServerSession;
        this.useSeparateConnection = useSeparateConnection;
        String sessionUsed;
        if (useServerSession) {
            sessionUsed = "ServerSession";
        } else {
            sessionUsed = "DatabaseSession";
        }
        shouldLogMessages = false;
        this.sequencePreallocationSize = sequencePreallocationSize;
        setName(getName() + " " + sessionUsed + " separateConnection=" + useSeparateConnection + " seqPreallocSize=" + sequencePreallocationSize + " threads=" + nThreads + " iterations=" + nIterations);
    }

    /**
     * Compare the two BigDecimal, for using TOPSort.
     */
    @Override
    public int compare(Object b1, Object b2) {
        java.math.BigDecimal big1 = new java.math.BigDecimal(((Number)b1).longValue());
        java.math.BigDecimal big2 = new java.math.BigDecimal(((Number)b2).longValue());
        return big1.compareTo(big2);
    }

    /**
     * Sets the logging and the sequence preallocation size the way it was.
     */
    @Override
    public void reset() {
        if (useServerSession) {
            if (serverSession != null) {
                serverSession.logout();
                serverSession = null;
            }
        } else {
            if (dbSession != null) {
//            dbSession.getSequencingControl().setPreallocationSize(this.previousSequencePreallocationSize);
                dbSession.getSequencingControl().initializePreallocated();
                if (useSeparateConnection != useSeparateConnectionOriginal) {
                    dbSession.getSequencingControl().setShouldUseSeparateConnection(useSeparateConnectionOriginal);
                    dbSession.getSequencingControl().resetSequencing();
                }
                dbSession.setLogLevel(originalLogLevel);
                dbSession = null;
            }
        }
    }

    public Runnable runnable() {
        return new Runnable() {

                /**
                 * Each thread does this: gets nIterations number of sequence numbers and puts them in a thread specific array.
                 */
                @Override
                public void run() {
                    // Test
                    Number[] sequence = (Number[])sequences.elementAt(threadNumber);
                    try {
                        if (handleException) {
                            for (int i = 0; i < nIterations; i++) {
                                try {
                                    sequence[i] = (Number)((AbstractSession)session).getSequencing().getNextValue(org.eclipse.persistence.testing.models.employee.domain.Employee.class);
                                } catch (org.eclipse.persistence.exceptions.ConcurrencyException ex) {
                                    if (ex.getErrorCode() == org.eclipse.persistence.exceptions.ConcurrencyException.SEQUENCING_MULTITHREAD_THRU_CONNECTION) {
                                        // that's an acceptable exception, try again.
                                        i--;
                                    } else {
                                        throw ex;
                                    }
                                }
                            }
                        } else {
                            for (int i = 0; i < nIterations; i++) {
                                sequence[i] = (Number)((AbstractSession)session).getSequencing().getNextValue(org.eclipse.persistence.testing.models.employee.domain.Employee.class);
                            }
                        }
                    } catch (Exception ex2) {
                        exception = ex2;
                    } finally {
                        if (session.isClientSession()) {
                            session.release();
                        }
                    }
                }
            };
    }

    @Override
    public void setup() {
        if (getAbstractSession().getDescriptor(Employee.class).getSequence().shouldAcquireValueAfterInsert()) {
            throw new org.eclipse.persistence.testing.framework.TestWarningException("Not a valid test against databases where the native sequencing is done entirely in the database.");
        }

        // Setup
        dbSession = (DatabaseSession)getSession();
        if (useServerSession) {
            int numConnections = java.lang.Math.min(nThreads, 5);
            serverSession = new Project(getSession().getDatasourceLogin().clone()).createServerSession(numConnections, numConnections);
            serverSession.addDescriptors(new org.eclipse.persistence.testing.models.employee.relational.EmployeeProject());
//        serverSession.getSequencingControl().setPreallocationSize(sequencePreallocationSize);
            serverSession.getSequencingControl().setShouldUseSeparateConnection(useSeparateConnection);
            serverSession.setSessionLog(getSession().getSessionLog());
            if (shouldLogMessages) {
                serverSession.setLogLevel(SessionLog.FINE);
            }
            serverSession.login();
        } else {
            originalLogLevel = dbSession.getLogLevel();
            if (shouldLogMessages) {
                dbSession.setLogLevel(SessionLog.FINE);
            }
//        this.previousSequencePreallocationSize = dbSession.getSequencingControl().getPreallocationSize();
//        dbSession.getSequencingControl().setPreallocationSize(sequencePreallocationSize);
            dbSession.getSequencingControl().resetSequencing();
            dbSession.getSequencingControl().initializePreallocated();
            useSeparateConnectionOriginal = dbSession.getSequencingControl().shouldUseSeparateConnection();
            if (useSeparateConnection != useSeparateConnectionOriginal) {
                dbSession.getSequencingControl().setShouldUseSeparateConnection(useSeparateConnection);
                dbSession.getSequencingControl().resetSequencing();
            }
        }

        // Setup the arrays of BigDecimals to be filled.
        sequences = new java.util.Vector(nThreads);
        for (int i = 0; i < nThreads; i++) {
            sequences.addElement(new Number[nIterations]);
        }
    }

    /**
     * Start each thread, then wait until all of them are finished.
     */
    @Override
    public void test() {
        //
        Thread[] threads = new Thread[nThreads];
        tests = new SequencingConcurrencyTest[nThreads];
        Session writeSession = getSession();
        boolean handleException = !useServerSession && !useSeparateConnection;
        for (int i = 0; i < nThreads; i++) {
            if (useServerSession) {
                writeSession = serverSession.acquireClientSession();
            }
            tests[i] = new SequencingConcurrencyTest(i, nIterations, sequences, writeSession, handleException);
            threads[i] = new Thread(tests[i].runnable());
            threads[i].start();
        }

        // Join with all the threads so we don't proceed until all the threads have finished.
        for (int i = 0; i < nThreads; i++) {
            try {
                threads[i].join();
            } catch (Exception ex) {
                throw new org.eclipse.persistence.testing.framework.TestErrorException(ex.getMessage());
            }
        }
    }

    /**
     * Make sure that the sequence numbers generated contained no gaps or duplicates.
     */
    @Override
    public void verify() {
        // Verify
        for (int i = 0; i < nThreads; i++) {
            if (tests[i].exception != null) {
                throw new org.eclipse.persistence.testing.framework.TestErrorException("exception in thread " + i + ", session(" + String.valueOf(System.identityHashCode(session)) + ") ", tests[i].exception);
            }
        }

        // Put all the sequences into one big array.
        Number[] big = new Number[nThreads * nIterations];
        for (int i = 0; i < nThreads; i++) {
            System.arraycopy(sequences.elementAt(i), 0, big, i * nIterations, nIterations);
        }
        try {
            // sort the array.
            Arrays.sort(big, this);

            // Verify that there are no duplicates or gaps in the array.
            Number previous = big[0];
            for (int i = 1; i < (nIterations * nThreads); i++) {
                Number current = big[i];
                if ((previous.intValue() + 1) != current.intValue()) {
                    throw new org.eclipse.persistence.testing.framework.TestErrorException("Gap in sequencing, or incorrect sequences generated.");
                }
                previous = current;
            }
        } catch (Exception ex) {
            throw new org.eclipse.persistence.testing.framework.TestErrorException(ex.getMessage());
        }
    }
}
