/*
 * Copyright 2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @bug     5086470  6358247
 * @summary LockingThread is used by LockedMonitors test.
 *          It will create threads that have:
 *          - a stack frame acquires no monitor
 *          - a stack frame acquires one or more monitors
 *          - a stack frame blocks on Object.wait
 *            and the monitor waiting is not locked.
 * @author  Mandy Chung
 *
 * @build Barrier
 * @build ThreadDump
 */

import java.lang.management.*;
import java.util.*;

public class LockingThread extends Thread {
    static Lock lock1 = new Lock("lock1");
    static Lock lock2 = new Lock("lock2");
    static Lock lock3 = new Lock("lock3");
    static Lock lock4 = new Lock("lock4");
    static Lock lock5 = new Lock("lock5");
    static Lock lock6 = new Lock("lock6");
    static Lock lock7 = new Lock("lock7");
    static Lock lock8 = new Lock("lock8");

    static LockingThread t1 = new Thread1();
    static LockingThread t2 = new Thread2();
    static Barrier barr = new Barrier(2);
    static int count = 2;
    static void startLockingThreads() {
        t1.setDaemon(true);
        t2.setDaemon(true);
        t1.start();
        t2.start();

        // wait until t1 waits
        while (count != 0) {
           try {
               Thread.sleep(100);
           } catch (InterruptedException e) {
               throw new RuntimeException(e);
           }
        }
    }
    static long[] getThreadIds() {
        return new long[] {t1.getId(), t2.getId()};
    }

    static void checkLockedMonitors(ThreadInfo[] tinfos)
        throws Exception {

        int matches = 0;
        for (ThreadInfo ti : tinfos) {
            if (ti.getThreadId() == t1.getId()) {
                t1.checkLockedMonitors(ti);
                matches++;
            }
            if (ti.getThreadId() == t2.getId()) {
                t2.checkLockedMonitors(ti);
                matches++;
            }
        }
        if (matches != 2) {
            throw new RuntimeException("MonitorInfo missing");
        }
    }

    static class Lock {
        String name;
        Lock(String name) {
            this.name = name;
        }
        public String toString() {
            return name;
        }
    }

    final String threadName;
    Lock         waitingLock;
    int          numOwnedMonitors;
    Map<String, Lock[]> ownedMonitors;
    public LockingThread(String name) {
        this.threadName = name;
    }

    protected void setExpectedResult(Lock waitingLock,
                                     int numOwnedMonitors,
                                     Map<String, Lock[]> ownedMonitors) {
        this.waitingLock = waitingLock;
        this.numOwnedMonitors = numOwnedMonitors;
        this.ownedMonitors = ownedMonitors;
    }

    void checkLockedMonitors(ThreadInfo info)
        throws Exception {
        checkThreadInfo(info);

        MonitorInfo[] monitors = info.getLockedMonitors();
        if (monitors.length != numOwnedMonitors) {
            ThreadDump.threadDump();
            throw new RuntimeException("Number of locked monitors = " +
                monitors.length +
                " not matched. Expected: " + numOwnedMonitors);
        }
        // check if each monitor returned in the list is the expected
        // one
        for (MonitorInfo m : monitors) {
            StackTraceElement ste = m.getLockedStackFrame();
            int depth = m.getLockedStackDepth();
            checkStackFrame(info, ste, depth);
            checkMonitor(m, ste.getMethodName());
        }
        // check if each expected monitor is included in the returned
        // list
        for (Map.Entry<String, Lock[]> e : ownedMonitors.entrySet()) {
            for (Lock l : e.getValue()) {
                checkMonitor(e.getKey(), l, monitors);
            }
        }

        if (info.getLockedSynchronizers().length != 0) {
            ThreadDump.threadDump();
            throw new RuntimeException("Number of locked synchronizers = " +
                info.getLockedSynchronizers().length +
                " not matched. Expected: 0.");
        }
    }

    void checkThreadInfo(ThreadInfo info) throws Exception {
        if (!getName().equals(info.getThreadName())) {
            throw new RuntimeException("Name: " + info.getThreadName() +
                " not matched. Expected: " + getName());
        }
        LockInfo l = info.getLockInfo();
        if ((waitingLock == null && l != null) ||
            (waitingLock != null && l == null)) {
            throw new RuntimeException("LockInfo: " + l +
                " not matched. Expected: " + waitingLock);
        }

        String waitingLockName = waitingLock.getClass().getName();
        int hcode = System.identityHashCode(waitingLock);
        if (!waitingLockName.equals(l.getClassName())) {
            throw new RuntimeException("LockInfo : " + l +
                " class name not matched. Expected: " + waitingLockName);
        }
        if (hcode != l.getIdentityHashCode()) {
            throw new RuntimeException("LockInfo: " + l +
                " IdentityHashCode not matched. Expected: " + hcode);
        }

        String lockName = info.getLockName();
        String[] s = lockName.split("@");
        if (!waitingLockName.equals(s[0])) {
            throw new RuntimeException("LockName: " + lockName +
                " class name not matched. Expected: " + waitingLockName);
        }
        int i = Integer.parseInt(s[1], 16);
        if (hcode != i) {
            throw new RuntimeException("LockName: " + lockName +
                " IdentityHashCode not matched. Expected: " + hcode);
        }
    }

    void checkStackFrame(ThreadInfo info, StackTraceElement ste, int depth) {
        StackTraceElement[] stacktrace = info.getStackTrace();
        if (!ste.equals(stacktrace[depth])) {
            System.out.println("LockedStackFrame:- " + ste);
            System.out.println("StackTrace at " + depth + " :-" +
                stacktrace[depth]);
            throw new RuntimeException("LockedStackFrame does not match " +
                "stack frame in ThreadInfo.getStackTrace");
        }
    }
    void checkMonitor(MonitorInfo m, String methodName) {
        for (Map.Entry<String, Lock[]> e : ownedMonitors.entrySet()) {
            if (methodName.equals(e.getKey())) {
                for (Lock l : e.getValue()) {
                    String className = l.getClass().getName();
                    int hcode = System.identityHashCode(l);
                    if (className.equals(m.getClassName()) &&
                        hcode == m.getIdentityHashCode()) {
                        // monitor matched the expected
                        return;
                    }
                }
            }
        }
        throw new RuntimeException("Monitor not expected" + m);
    }
    void checkMonitor(String methodName, Lock l, MonitorInfo[] monitors) {
        String className = l.getClass().getName();
        int hcode = System.identityHashCode(l);
        for (MonitorInfo m : monitors) {
            if (className.equals(m.getClassName()) &&
                hcode == m.getIdentityHashCode() &&
                methodName.equals(m.getLockedStackFrame().getMethodName())) {
                return;
            }
        }
        throw new RuntimeException("Monitor not found in the returned list" +
            " Method: " + methodName + " Lock: " + l);

    }

    static class Thread1 extends LockingThread {
        public Thread1() {
            super("t1");
            initExpectedResult();
        }
        public void run() {
            A();
        }
        void A() {
            synchronized(lock1) {
                synchronized(lock2) {
                    synchronized(lock3) {
                        B();
                    }
                }
            }
        }
        void B() {
            synchronized(lock4) {
                synchronized(lock5) {
                    C();
                }
            }
        }
        void C() {
            synchronized(lock6) {
                D();
            }
        }
        void D() {
            synchronized(lock7) {
                try {
                    // signal to about to wait
                    count--;
                    lock7.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        Map<String, Lock[]> LOCKED_MONITORS;
        Lock WAITING_LOCK = lock7;
        int OWNED_MONITORS = 6;
        void initExpectedResult() {
            LOCKED_MONITORS = new HashMap<String, Lock[]>();
            LOCKED_MONITORS.put("D", new Lock[0]); // no monitored locked
            LOCKED_MONITORS.put("C", new Lock[] {lock6});
            LOCKED_MONITORS.put("B", new Lock[] {lock5, lock4});
            LOCKED_MONITORS.put("A", new Lock[] {lock3, lock2, lock1});
            this.setExpectedResult(WAITING_LOCK, OWNED_MONITORS, LOCKED_MONITORS);
        }

    }

    static class Thread2 extends LockingThread {
        Map<String, Lock[]> LOCKED_MONITORS = new HashMap<String, Lock[]>();
        Lock WAITING_LOCK = lock8;
        int OWNED_MONITORS = 0;
        public Thread2() {
            super("t2");
            this.setExpectedResult(WAITING_LOCK, OWNED_MONITORS, LOCKED_MONITORS);
        }
        public void run() {
            synchronized(lock8) {
                try {
                    synchronized(lock7) {
                        count--;
                    }
                    lock8.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

}
