org.apache.ambari.server.testing.DeadlockWarningThread.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.server.testing.DeadlockWarningThread.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
* http://www.apache.org/licenses/LICENSE-2.0
 * 
* Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.ambari.server.testing;

import org.apache.commons.lang.ArrayUtils;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 
 * Monitoring of deadlocks thread
 * Please note. This class can not be used outside of tests
 */
public class DeadlockWarningThread extends Thread {

    private final List<String> errorMessages;
    private static final int MAX_STACK_DEPTH = 30;
    private Collection<Thread> monitoredThreads = null;
    private boolean deadlocked = false;
    private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();

    public List<String> getErrorMessages() {
        return errorMessages;
    }

    public boolean isDeadlocked() {
        return deadlocked;
    }

    public DeadlockWarningThread(Collection<Thread> monitoredThreads) {
        this.errorMessages = new ArrayList<String>();
        this.monitoredThreads = monitoredThreads;
        start();
    }

    public String getThreadsStacktraces(Collection<Long> ids) {
        StringBuilder errBuilder = new StringBuilder();
        for (long id : ids) {
            ThreadInfo ti = mbean.getThreadInfo(id, MAX_STACK_DEPTH);
            errBuilder.append("Deadlocked Thread:\n").append("------------------\n").append(ti).append('\n');
            for (StackTraceElement ste : ti.getStackTrace()) {
                errBuilder.append('\t').append(ste);
            }
            errBuilder.append('\n');
        }
        return errBuilder.toString();
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException ex) {
            }
            long[] ids = mbean.findMonitorDeadlockedThreads();
            StringBuilder errBuilder = new StringBuilder();
            if (ids != null && ids.length > 0) {
                errBuilder.append(getThreadsStacktraces(Arrays.asList(ArrayUtils.toObject(ids))));
                errorMessages.add(errBuilder.toString());
                System.out.append(errBuilder.toString());
                //Exit if deadlocks have been found         
                deadlocked = true;
                break;
            } else {
                //Exit if all monitored threads were finished
                boolean hasLive = false;
                boolean hasRunning = false;
                for (Thread monTh : monitoredThreads) {
                    State state = monTh.getState();
                    if (state != State.TERMINATED && state != State.NEW) {
                        hasLive = true;
                    }
                    if (state == State.RUNNABLE || state == State.TIMED_WAITING) {
                        hasRunning = true;
                        break;
                    }
                }

                if (!hasLive) {
                    deadlocked = false;
                    break;
                } else if (!hasRunning) {
                    List<Long> tIds = new ArrayList<Long>();
                    for (Thread monitoredThread : monitoredThreads) {
                        State state = monitoredThread.getState();
                        if (state == State.WAITING || state == State.BLOCKED) {
                            tIds.add(monitoredThread.getId());
                        }
                    }
                    errBuilder.append(getThreadsStacktraces(tIds));
                    errorMessages.add(errBuilder.toString());
                    deadlocked = true;
                    break;
                }
            }
        }
    }
}