/*
 * Copyright (c) 2005, 2015, 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     5086470 6358247
 * @summary Basic Test for ThreadMXBean.dumpAllThreads(false, true)
 *          and getThreadInfo of customized JSR-166 synchronizers.
 * @author  Mandy Chung
 *
 * @modules java.management
 * @build Barrier
 * @build ThreadDump
 * @run main/othervm MyOwnSynchronizer
 */

import java.lang.management.*;
import java.util.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.TimeUnit;
import java.io.*;

public class MyOwnSynchronizer {
    static ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
    static Mutex mutex = new Mutex();
    static MyThread thread = new MyThread();
    public static void main(String[] argv) throws Exception {
        if (!mbean.isSynchronizerUsageSupported()) {
            System.out.println("Monitoring of synchronizer usage not supported");
            return;
        }

        thread.setDaemon(true);
        thread.start();

        // wait until myThread acquires mutex
        while (!mutex.isLocked()) {
           try {
               Thread.sleep(100);
           } catch (InterruptedException e) {
               throw new RuntimeException(e);
           }
        }

        ThreadDump.threadDump();
        // Test dumpAllThreads with locked synchronizers
        ThreadInfo[] tinfos = mbean.dumpAllThreads(false, true);
        for (ThreadInfo ti : tinfos) {
           MonitorInfo[] monitors = ti.getLockedMonitors();
           if (monitors.length != 0) {
               throw new RuntimeException("Name: " + ti.getThreadName() +
                   " has non-empty locked monitors = " + monitors.length);
           }
           LockInfo[] syncs = ti.getLockedSynchronizers();
           if (ti.getThreadId() == thread.getId()) {
               thread.checkLockedSyncs(ti, syncs);
           }
        }

        // Test getThreadInfo with locked synchronizers
        tinfos = mbean.getThreadInfo(new long[] {thread.getId()}, false, true);
        if (tinfos.length != 1) {
            throw new RuntimeException("getThreadInfo() returns " +
                tinfos.length + " ThreadInfo objects. Expected 0.");
        }
        ThreadInfo ti = tinfos[0];
        if (ti.getLockedMonitors().length != 0) {
            throw new RuntimeException("Name: " + ti.getThreadName() +
               " has non-empty locked monitors = " +
               ti.getLockedMonitors().length);
        }
        thread.checkLockedSyncs(ti, ti.getLockedSynchronizers());

        System.out.println("Test passed");
    }

    static class Mutex implements Lock, java.io.Serializable {

        // Our internal helper class
        class Sync extends AbstractQueuedSynchronizer {
            // Report whether in locked state
            protected boolean isHeldExclusively() {
                return getState() == 1;
            }

            // Acquire the lock if state is zero
            public boolean tryAcquire(int acquires) {
                assert acquires == 1; // Otherwise unused
                if (compareAndSetState(0, 1)) {
                  setExclusiveOwnerThread(Thread.currentThread());
                  return true;
                }
                return false;
            }

            // Release the lock by setting state to zero
            protected boolean tryRelease(int releases) {
                assert releases == 1; // Otherwise unused
                if (getState() == 0) throw new IllegalMonitorStateException();
                setExclusiveOwnerThread(null);
                setState(0);
                return true;
            }

            // Provide a Condition
            Condition newCondition() { return new ConditionObject(); }

            // Deserialize properly
            private void readObject(ObjectInputStream s)
                throws IOException, ClassNotFoundException {
                s.defaultReadObject();
                setState(0); // reset to unlocked state
            }
        }

        // The sync object does all the hard work. We just forward to it.
        private final Sync sync = new Sync();

        public void lock()                { sync.acquire(1); }
        public boolean tryLock()          { return sync.tryAcquire(1); }
        public void unlock()              { sync.release(1); }
        public Condition newCondition()   { return sync.newCondition(); }
        public boolean isLocked()         { return sync.isHeldExclusively(); }
        public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }

        public AbstractOwnableSynchronizer getSync() { return sync; }
    }

    static class MyThread extends Thread {
        public MyThread() {
            super("MyThread");
        }
        public void run() {
            mutex.lock();
            Object o = new Object();
            synchronized(o) {
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        int OWNED_SYNCS = 1;
        void checkLockedSyncs(ThreadInfo info, LockInfo[] syncs) {
            if (!getName().equals(info.getThreadName())) {
                throw new RuntimeException("Name: " + info.getThreadName() +
                    " not matched. Expected: " + getName());
            }

            if (syncs.length != OWNED_SYNCS) {
                throw new RuntimeException("Number of locked syncs = " +
                    syncs.length +
                    " not matched. Expected: " + OWNED_SYNCS);
            }
            AbstractOwnableSynchronizer s = mutex.getSync();
            String lockName = s.getClass().getName();
            int hcode = System.identityHashCode(s);
            if (!lockName.equals(syncs[0].getClassName())) {
                throw new RuntimeException("LockInfo : " + syncs[0] +
                    " class name not matched. Expected: " + lockName);
            }
            if (hcode != syncs[0].getIdentityHashCode()) {
                throw new RuntimeException("LockInfo: " + syncs[0] +
                    " IdentityHashCode not matched. Expected: " + hcode);
            }

        }
    }
}
