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

import java.util.Vector;

import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.testing.tests.clientserver.Server;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.bigbad.*;

/**
 * This test is set up to have one thread build a BigBadObject instance, while multiple other threads
 * attempt to access the same instance from the cache.  The test fails if any of the threads access
 * an incomplete instance of the BigBadObject object - where it has been only partially built.  Only
 * the "number02" attribute is checked, as all mapping weights are changed so this mapping is
 * built last.  Built to test bug 4772232
 */
public class ConcurrentReadBigBadObjectTest extends AutoVerifyTestCase {
    public ConcurrentReadBigBadObjectTest() {
    }

    BigBadObject referenceObject;
    protected int numOftries = 300;
    protected int numOfThreads = 10;
    protected boolean failed;
    protected Server server;
    protected int OrigDirectMapWeight;


    @Override
    public void setup() throws Exception {

        DatabaseLogin login;
        login = (DatabaseLogin)getSession().getLogin().clone();
        server = new Server(login);
        server.serverSession.setLogLevel(getSession().getLogLevel());
        server.serverSession.setLog(getSession().getLog());


        server.copyDescriptors(getSession());
        ClassDescriptor d = (server.serverSession).getClassDescriptor(BigBadObject.class);
        DatabaseMapping m;

        Vector v = d.getMappings();
        int mappings = v.size();
        int i = 0;
        while (i < mappings) {
            m = (DatabaseMapping)v.get(i);
            m.setWeight(Integer.MAX_VALUE - 1);
            i++;
        }

        m = d.getMappingForAttributeName("number02");
        m.setWeight(Integer.MAX_VALUE);

        server.login();
        server.serverSession.setLogLevel(getSession().getLogLevel());
        server.serverSession.setLog(getSession().getLog());
    }

    @Override
    public void reset() throws Exception {
        server.logout();
    }

    @Override
    public void test() {
        failed = false;

        referenceObject = (BigBadObject)this.getSession().readObject(BigBadObject.class);
        Reader[] threadList = new Reader[numOfThreads];

        for (int i = 0; i < numOfThreads; ) {
            threadList[i] = new Reader(referenceObject, server.serverSession.acquireClientSession(), ++i);
        }

        for (int i = 0; i < numOfThreads; i++) {
            threadList[i].start();
        }

        try {
            for (int i = 0; i < numOfThreads; i++) {
                threadList[i].join();
            }
        } catch (InterruptedException ex) {
        }
        int count = 0;
        while (!failed && count < numOfThreads) {
            if (threadList[count].exception != null) {
                throw threadList[count].exception;
            }
            failed = threadList[count].hadError();
            count++;
        }
        if (failed) {
            throw new TestErrorException("Test failed, getFromIdentityMap returned an object before it was finished being built");
        }

    }


    /**
     * Threads to read/access the cache numOftries times.  Only thread 1 will initialize the cache and
     * read the BigBadObject object instance.
     */
    private class Reader extends Thread {
        protected BigBadObject referenceObject, readObject;
        protected Session session;
        public int thread;
        public int counter;
        public RuntimeException exception;

        protected boolean experienceError = false;

        public Reader(BigBadObject object, Session session, int thread) {
            this.referenceObject = object;
            this.session = session;
            this.thread = thread;
            counter = 0;
        }

        @Override
        public void run() {
            try {
                counter = 0;
                while (!experienceError && counter < numOftries) {
                    if (thread == 1) {
                        session.getIdentityMapAccessor().initializeIdentityMap(BigBadObject.class);
                        readObject = (BigBadObject)session.readObject(referenceObject);
                    } else {
                        readObject = (BigBadObject)session.getIdentityMapAccessor().getFromIdentityMap(referenceObject);
                    }
                    if ((readObject != null) &&
                        ((readObject.number02 == null) || (!readObject.number02.equals(referenceObject.number02)))) {
                        this.experienceError = true;
                    }
                    counter++;
                }
            } catch (RuntimeException ex) {
                this.experienceError = true;
                this.exception = ex;
            }
        }

        public boolean hadError() {
            return experienceError;
        }
    }
}
