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

import java.util.Vector;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.tests.clientserver.Server;
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 TestCase {
    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.valueOf(Integer.MAX_VALUE-1));
            i++;
        }

        m = d.getMappingForAttributeName("number02");
        m.setWeight(Integer.valueOf(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;
        }
    }
}
