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