/*
 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/**
 * @test
 * @bug 4882798
 * @summary multi-thread test to exercise sync and contention for adds to transformer registry
 * @author Gabriel Adauto, Wily Technology
 *
 * @run build TransformerManagementThreadAddTests
 * @run shell MakeJAR.sh redefineAgent
 * @run main/othervm -javaagent:redefineAgent.jar TransformerManagementThreadAddTests TransformerManagementThreadAddTests
 */
import java.io.*;
import java.lang.instrument.*;
import java.security.ProtectionDomain;
import java.util.*;

public class TransformerManagementThreadAddTests extends ATestCaseScaffold
{
    public static void
    main (String[] args)
        throws Throwable {
        ATestCaseScaffold   test = new TransformerManagementThreadAddTests(args[0]);
        test.runTest();
    }

    protected void
    doRunTest()
        throws Throwable {
        testMultiThreadAdds();
    }


    /**
     * CONFIGURATION FOR TEST
     * ----------------------
     * Set these variables to different values to test the object that
     * manages the transformers.
     *
     * MIN_TRANS: the minimum number of transformers to add by a thread
     * MAX_TRANS: the maximum number of transformers to add by a thread
     *      There will be a total of MAX_TRANS-MIN_TRANS+1 threads created.
     *      Each thread will add between MIN_TRANS and MAX_TRANS transformers
     *      to the manager.
     *
     * REMOVE_THREADS: the number of threads to run that spend their time
     *                  removing transformers
     */
    protected static final int MIN_TRANS = 33;
    protected static final int MAX_TRANS = 45;
    protected static final int REMOVE_THREADS = 5;

    protected static final boolean LOG_TRANSFORMATIONS = false;

    /**
     * Field variables
     */
    protected static final int TOTAL_THREADS = MAX_TRANS - MIN_TRANS + 1;

    private byte[]          fDummyClassBytes;
    // fCheckedTransformers is a Vector that is used to verify
    // that the transform() function is called in the same
    // order in which the transformers were added to the
    // TransformerManager. The test currently verifies that all
    // transformers for a specific worker thread are in
    // increasing order by index value.
    private Vector              fCheckedTransformers;
    private Instrumentation fInstrumentation;
    private int             fFinished;
    private ExecuteTransformersThread fExec;

    // Need to use this for synchronization in subclass
    protected Vector            fAddedTransformers;
    private String          fDummyClassName;

    /**
     * Constructor for TransformerManagementThreadAddTests.
     * @param name  Name for the test
     */
    public TransformerManagementThreadAddTests(String name)
    {
        super(name);

        fCheckedTransformers = new Vector();
        fAddedTransformers = new Vector();

        fDummyClassName = "DummyClass";
        String resourceName = "DummyClass.class";
        File f = new File(System.getProperty("test.classes", "."), resourceName);
        System.out.println("Reading test class from " + f);
        try
        {
            InputStream redefineStream = new FileInputStream(f);
            fDummyClassBytes = NamedBuffer.loadBufferFromStream(redefineStream);
        }
        catch (IOException e)
        {
            fail("Could not load the class: "+resourceName);
        }
    }

    public void
    testMultiThreadAdds()
    {
        TransformerThread[] threads = new TransformerThread[TOTAL_THREADS];
        for (int i = MIN_TRANS; i <= MAX_TRANS; i++)
        {
            int index = i - MIN_TRANS;
            threads[index] = new TransformerThread("Trans"+prettyNum(index,2), i);
        }

        ExecuteTransformersThread exec = new ExecuteTransformersThread();
        exec.start();
        for (int i = threads.length - 1; i >= 0; i--)
        {
            threads[i].start();
        }

        // Effective Java - Item 48: Synchronize access to shared mutable data
        // Don't use a direct field getter.
        while (!exec.isDone())
        {
            // Effective Java - Item 51: Don't depend on the thread scheduler
            // Use sleep() instead of yield().
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
        assertTrue(finalCheck());

        if (LOG_TRANSFORMATIONS) {
            printTransformers();
        }
    }

    /**
     * Returns the Instrumentation.
     * @return Instrumentation  the data type with JPLIS calls
     */
    public Instrumentation getInstrumentation()
    {
        return fInstrumentation;
    }

    /**
     * Returns the execution thread
     * @return ExecuteTransformersThread
     */
    protected ExecuteTransformersThread getExecThread()
    {
        return fExec;
    }

    /**
     * Sets the execution thread
     * @param exec The execution thread to set
     */
    protected void setExecThread(ExecuteTransformersThread exec)
    {
        this.fExec = exec;
    }

    // Effective Java - Item 48: Synchronize access to shared mutable data
    // Document a synchronized setter.
    protected synchronized void
    threadFinished(Thread t)
    {
        fFinished++;
    }

    // Effective Java - Item 48: Synchronize access to shared mutable data
    // Provide synchronized getter.
    protected synchronized boolean
    threadsDone()
    {
        return fFinished == TOTAL_THREADS;
    }

    /**
     * Method testCompleted.
     * @return boolean
     */
    protected boolean
    testCompleted()
    {
        // Effective Java - Item 48: Synchronize access to shared mutable data
        // Don't use direct field getter.
        return getExecThread().isDone();
    }

    /**
     *
     */
    protected boolean
    finalCheck()
    {
        if (LOG_TRANSFORMATIONS) {
            // log the list
            for (int x = 0; x < fCheckedTransformers.size(); x++ ) {
                System.out.println(x + "\t\t" + fCheckedTransformers.get(x));
            }
            System.out.println();
            System.out.println();

            // check for multiples
            for (int x = 0; x < fCheckedTransformers.size(); x++ ) {
                Object current = fCheckedTransformers.get(x);
                for ( int y = x + 1; y < fCheckedTransformers.size(); y++) {
                    Object running = fCheckedTransformers.get(y);
                    if ( current.equals(running) ) {
                        System.out.println(x + "\t" + y + " \t" + "FOUND DUPLICATE: " + current);
                    }
                }
            }
        }

        for (int j = 1; j < fCheckedTransformers.size(); j++) {
            ThreadTransformer transformer = (ThreadTransformer)fCheckedTransformers.get(j);
            for (int i = 0; i < j; i++) {
                ThreadTransformer currTrans = (ThreadTransformer)fCheckedTransformers.get(i);
                assertTrue(currTrans + " incorrectly appeared before " +
                           transformer + " i=" + i + " j=" + j + " size=" +
                           fCheckedTransformers.size(),
                           !(
                             currTrans.getThread().equals(transformer.getThread()) &&
                             currTrans.getIndex() > transformer.getIndex()));
            }
        }
        return true;
    }

    /**
     *
     */
    protected void
    setUp()
        throws Exception
    {
        super.setUp();

        fFinished = 0;
        assertTrue(MIN_TRANS < MAX_TRANS);
        fInstrumentation = InstrumentationHandoff.getInstrumentationOrThrow();
    }

    /**
     *
     */
    protected void
    tearDown()
        throws Exception
    {
        super.tearDown();
    }



    /**
     * Method executeTransform.
     */
    private void
    executeTransform()
    {
        try
        {
            ClassDefinition cd = new ClassDefinition(DummyClass.class, fDummyClassBytes);

            // When the ClassDefinition above is created for the first
            // time and every time redefineClasses() below is called,
            // the transform() function is called for each registered
            // transformer. We only want one complete set of calls to
            // be logged in the fCheckedTransformers Vector so we clear
            // any calls logged for ClassDefinition above and just use
            // the ones logged for redefineClasses() below.
            fCheckedTransformers.clear();

            getInstrumentation().redefineClasses(new ClassDefinition[]{ cd });
        }
        catch (ClassNotFoundException e)
        {
            fail("Could not find the class: "+DummyClass.class.getName());
        }
        catch (UnmodifiableClassException e)
        {
            fail("Could not modify the class: "+DummyClass.class.getName());
        }
    }

    /**
     * Method addTransformerToManager.
     * @param threadTransformer
     */
    private void
    addTransformerToManager(ThreadTransformer threadTransformer)
    {
        getInstrumentation().addTransformer(threadTransformer);
        fAddedTransformers.add(threadTransformer);
    }

    /**
     * Method checkInTransformer.
     * @param myClassFileTransformer
     */
    private void
    checkInTransformer(ThreadTransformer transformer)
    {
        fCheckedTransformers.add(transformer);
    }

    /**
     * Method createTransformer.
     * @param transformerThread
     * @param i
     * @return ThreadTransformer
     */
    private ThreadTransformer
    createTransformer(TransformerThread thread, int index)
    {
        ThreadTransformer tt = null;

        tt = new ThreadTransformer(thread, index);

        return tt;
    }


    protected class
    ExecuteTransformersThread
        extends Thread
    {
        private boolean fDone = false;

        // Effective Java - Item 48: Synchronize access to shared mutable data
        // Provide a synchronized getter.
        private synchronized boolean isDone() {
            return fDone;
        }

        // Effective Java - Item 48: Synchronize access to shared mutable data
        // Provide a synchronized setter.
        private synchronized void setIsDone() {
            fDone = true;
        }

        public void
        run()
        {
            while(!threadsDone())
            {
                executeTransform();
            }

            // Do a final check for good measure
            executeTransform();
            // Effective Java - Item 48: Synchronize access to shared mutable data
            // Don't use direct field setter.
            setIsDone();
        }
    }


    protected class
    TransformerThread
        extends Thread
    {
        private final ThreadTransformer[] fThreadTransformers;

        TransformerThread(String name, int numTransformers)
        {
            super(name);

            fThreadTransformers = makeTransformers(numTransformers);
        }

        /**
         * Method makeTransformers.
         * @param numTransformers
         * @return ThreadTransformer[]
         */
        private ThreadTransformer[]
        makeTransformers(int numTransformers)
        {
            ThreadTransformer[] trans = new ThreadTransformer[numTransformers];

            for (int i = 0; i < trans.length; i++)
            {
                trans[i] = createTransformer(TransformerThread.this, i);
            }

            return trans;
        }

        public void
        run()
        {
            for (int i = 0; i < fThreadTransformers.length; i++)
            {
                addTransformerToManager(fThreadTransformers[i]);
            }
            threadFinished(TransformerThread.this);
        }
    }

    /**
     * ClassFileTransformer implementation that knows its thread
     */
    protected class
    ThreadTransformer extends SimpleIdentityTransformer
    {
        private final String    fName;
        private final int       fIndex;
        private final Thread    fThread;

        /**
         * Constructor for ThreadTransformer.
         */
        public ThreadTransformer(Thread thread, int index) {
            super();
            fThread = thread;
            fIndex = index;
            fName = "TT["+fThread.getName()+"]["+prettyNum(fIndex,3)+"]";
        }

        public String toString()
        {
            return fName;
        }

        /**
         *
         */
        public byte[]
        transform(
            ClassLoader loader,
            String className,
            Class<?> classBeingRedefined,
            ProtectionDomain domain,
            byte[] classfileBuffer)
        {
            if ( className.equals(TransformerManagementThreadAddTests.this.fDummyClassName) ) {
                checkInTransformer(ThreadTransformer.this);
            }
            return super.transform(    loader,
                                        className,
                                        classBeingRedefined,
                                        domain,
                                        classfileBuffer);
        }

        /**
         * Returns the index.
         * @return int
         */
        public int getIndex()
        {
            return fIndex;
        }

        /**
         * Returns the thread.
         * @return Thread
         */
        public Thread getThread()
        {
            return fThread;
        }

    }

    /**
     * DEBUG STUFF
     */
    private int NUM_SWITCHES;

    /**
     * Method printTransformers.
     */
    protected void printTransformers()
    {
        NUM_SWITCHES = 0;
        Iterator trans = fCheckedTransformers.iterator();
        ThreadTransformer old = null;
        StringBuffer buf = new StringBuffer();

        for (int i = 1; trans.hasNext(); i++)
        {
            ThreadTransformer t = (ThreadTransformer)trans.next();
            buf.append(t.toString());
            if (old != null)
            {
                if (!old.getThread().equals(t.getThread()))
                {
                    NUM_SWITCHES++;
                    buf.append("*");
                }
                else
                { buf.append(" "); }
            }
            else
            { buf.append(" "); }

            if (i % 5 == 0)
            {
                buf.append("\n");
            }
            else
            { buf.append(" "); }

            old = t;
        }
        System.out.println(buf);
        System.out.println("\nNumber of transitions from one thread to another: "+NUM_SWITCHES);
    }

    protected String
    prettyNum(int n, int numSize)
    {
        StringBuffer num = new StringBuffer(Integer.toString(n));
        int size = num.length();
        for (int i = 0; i < numSize - size; i++)
        {
            num.insert(0, "0");
        }

        return num.toString();
    }
    /**
     * END DEBUG STUFF
     */

}
