/*
 * 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.
 */
/*
 * author Ian Formanek 
 *        Misha Dmitriev
 *        Tomas Hurka
 */

#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#endif

#ifdef SOLARIS
#define _STRUCTURED_PROC 1
#include <sys/procfs.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "jni.h"
#include "jvmti.h"

#include "org_netbeans_lib_profiler_server_system_Threads.h"

#include "common_functions.h"

/* The following is copied from org.netbeans.lib.profiler.global.CommonConstants */
#define THREAD_STATUS_UNKNOWN  -1
#define THREAD_STATUS_ZOMBIE    0
#define THREAD_STATUS_RUNNING   1
#define THREAD_STATUS_SLEEPING  2
#define THREAD_STATUS_MONITOR   3
#define THREAD_STATUS_WAIT      4
#define THREAD_STATUS_PARK      5

/* These masks essentially map JVMTI thread states into the above states */
static jint JF_THREAD_STATE_MASK       = JVMTI_THREAD_STATE_TERMINATED |
                                         JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_RUNNABLE |
                                         JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
                                         JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
                                         JVMTI_THREAD_STATE_SLEEPING |
                                         JVMTI_THREAD_STATE_PARKED;
static jint JF_THREAD_STATE_NEW        = 0;
static jint JF_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED;
static jint JF_THREAD_STATE_RUNNABLE   = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_RUNNABLE;
static jint JF_THREAD_STATE_BLOCKED    = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
static jint JF_THREAD_STATE_WAITING    = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
static jint JF_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_SLEEPING   = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_SLEEPING |
                                         JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_TIMED_PARKED = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_PARKED |
                                         JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_PARKED = JVMTI_THREAD_STATE_ALIVE |
                                         JVMTI_THREAD_STATE_WAITING |
                                         JVMTI_THREAD_STATE_PARKED |
                                         JVMTI_THREAD_STATE_WAITING_INDEFINITELY;


static int nProfThreads;
static jthread *profThreads = NULL;
static jthread mainThread = NULL, singleProfThread = NULL, additionalProfThread = NULL;
static jclass threadType = NULL;


jint convert_JVMTI_thread_status_to_jfluid_status(jint jvmtiThreadStatus) {
    jint status = jvmtiThreadStatus & JF_THREAD_STATE_MASK;
  
    if      (status == JF_THREAD_STATE_RUNNABLE)      return THREAD_STATUS_RUNNING;
    else if (status == JF_THREAD_STATE_BLOCKED)       return THREAD_STATUS_MONITOR;
    else if (status == JF_THREAD_STATE_WAITING)       return THREAD_STATUS_WAIT;
    else if (status == JF_THREAD_STATE_TIMED_WAITING) return THREAD_STATUS_WAIT;
    else if (status == JF_THREAD_STATE_PARKED)        return THREAD_STATUS_PARK;
    else if (status == JF_THREAD_STATE_TIMED_PARKED)  return THREAD_STATUS_PARK;
    else if (status == JF_THREAD_STATE_SLEEPING)      return THREAD_STATUS_SLEEPING;
    else if (status == JF_THREAD_STATE_NEW)           return THREAD_STATUS_ZOMBIE;
    else if (status == JF_THREAD_STATE_TERMINATED)    return THREAD_STATUS_ZOMBIE;
    else                                              return THREAD_STATUS_UNKNOWN;
}


static int isProfilerThread(JNIEnv *env, jthread thread) {
    int i;
    if (additionalProfThread != NULL) {
        if ((*env)->IsSameObject(env, thread, additionalProfThread)) {
            return 1;
         }
    }
    if (profThreads != NULL) {
        for (i = 0; i < nProfThreads; i++) {
            if ((*env)->IsSameObject(env, thread, profThreads[i])) return 1;
        }
        return 0;
    } else {
        return ((*env)->IsSameObject(env, thread, singleProfThread));
    }
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    recordProfilerOwnThreads
 * Signature: (ZLjava/lang/Thread;)I
 */
JNIEXPORT jint JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_recordProfilerOwnThreads
    (JNIEnv *env, jclass clz, jboolean excludeSpecialThread, jobject specialThread) 
{
    jvmtiError res;
    int i, j;
  
    if (profThreads != NULL) {
        for (i = 0; i < nProfThreads; i++) {
            (*env)->DeleteGlobalRef(env, profThreads[i]);
         }
        (*_jvmti)->Deallocate(_jvmti, (unsigned char*) profThreads);
    }
    
    profThreads = NULL;
    if (singleProfThread != NULL) {
        (*env)->DeleteGlobalRef(env, singleProfThread);
    }
    singleProfThread = NULL;
    if (mainThread != NULL) {
        (*env)->DeleteGlobalRef(env, mainThread);
    }
    mainThread = NULL;
  
    if (excludeSpecialThread) {
        res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nProfThreads, &profThreads);
        assert(res == JVMTI_ERROR_NONE);
        if (specialThread != NULL) {
            for (i = 0; i < nProfThreads; i++) {
                if ((*env)->IsSameObject(env, specialThread, profThreads[i])) {
                    for (j = i+1; j < nProfThreads; j++) {
                        profThreads[j-1] = profThreads[j];
                    }
                    nProfThreads--;
                    break;
                }
            }
            mainThread = (*env)->NewGlobalRef(env, specialThread);
        }
        /* Results were returned as local references; make them global to survive across native calls */
        for (i = 0; i < nProfThreads; i++) {
            profThreads[i] = (*env)->NewGlobalRef(env, profThreads[i]);
        }
        return nProfThreads;
    } else {
        singleProfThread = (*env)->NewGlobalRef(env, specialThread);
        return 1;
    }
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    recordAdditionalProfilerOwnThread
 * Signature: (Ljava/lang/Thread;)V
 */
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_recordAdditionalProfilerOwnThread
    (JNIEnv *env, jclass clz, jobject specialThread) 
{
    if (additionalProfThread != NULL) {
        (*env)->DeleteGlobalRef(env, additionalProfThread);
    }
    additionalProfThread = (*env)->NewGlobalRef(env, specialThread);
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    getTotalNumberOfThreads
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getTotalNumberOfThreads
    (JNIEnv *env, jclass clz) 
{
    jvmtiError res;
    int nThreads;
    jthread *threads = NULL;
  
    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
    if (threads != NULL) {
        (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
    }
    return nThreads;
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    suspendTargetAppThreads
 * Signature: (Ljava/lang/Thread;)V
 */
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_suspendTargetAppThreads
    (JNIEnv *env, jclass clz, jobject excludedThread) 
{
    jvmtiError res;
    int i;
    int nThreads;
    jthread *threads = NULL;
  
    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
  
    for (i = 0; i < nThreads; i++) {
        if (! (isProfilerThread(env, threads[i]) || (*env)->IsSameObject(env, excludedThread, threads[i]))) {
            (*_jvmti)->SuspendThread(_jvmti, threads[i]);
        }
    }
  
    (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    resumeTargetAppThreads
 * Signature: (Ljava/lang/Thread;)V
 */
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_resumeTargetAppThreads
    (JNIEnv *env, jclass clz, jobject excludedThread) 
{
    jvmtiError res;
    int i;
    int nThreads;
    jthread *threads = NULL;
  
    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
  
    for (i = 0; i < nThreads; i++) {
        if (! (isProfilerThread(env, threads[i]) || (*env)->IsSameObject(env, excludedThread, threads[i]))) {
            (*_jvmti)->ResumeThread(_jvmti, threads[i]);
        }
    }
  
    (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    terminateTargetAppThreads
 * Signature: (Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_terminateTargetAppThreads
    (JNIEnv *env, jclass clz, jobject excObject) 
{
    jvmtiError res;
    int i;
    int nThreads;
    jthread *threads;
  
    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
  
    for (i = 0; i < nThreads; i++) {
        if (! isProfilerThread(env, threads[i])) {
            (*_jvmti)->StopThread(_jvmti, threads[i], excObject);
        }
    }
  
    (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
    if (mainThread != NULL) {
        (*env)->DeleteGlobalRef(env, mainThread);
    }
    mainThread = NULL;
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    targetAppThreadsExist
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_targetAppThreadsExist
    (JNIEnv *env, jclass clz) 
{
    jvmtiError res;
    int i;
    jboolean exist;
    int nThreads;
    jthread *threads;
  
    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
  
    exist = 0;
    for (i = 0; i < nThreads; i++) {
        if (! isProfilerThread(env, threads[i]) && ! (*env)->IsSameObject(env, threads[i], mainThread)) {
            exist = 1;
            break;
        }
    }
  
    (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
    return exist;
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    getAllThreads
 * Signature: ([Ljava/lang/Thread;)[Ljava/lang/Thread;
 */
JNIEXPORT jobjectArray JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getAllThreads
    (JNIEnv *env , jclass clz, jobjectArray jthreads) 
{
    int nThreads, arrayLen, i;
    jthread *threads = NULL;
    jvmtiError res;

    res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
    assert(res == JVMTI_ERROR_NONE);
	  
    arrayLen = (jthreads != NULL) ? (*env)->GetArrayLength(env, jthreads) : 0;
    if (nThreads > arrayLen) {
        if (threadType == NULL) {
            threadType = (*env)->FindClass(env, "java/lang/Thread");
            threadType = (*env)->NewGlobalRef(env, threadType);
        }
        jthreads = (*env)->NewObjectArray(env, nThreads, threadType, NULL);
    }
  
    for (i = 0; i < nThreads; i++) {
        (*env)->SetObjectArrayElement(env, jthreads, i, threads[i]);
    }
    for (i = nThreads; i < arrayLen; i++) {
        (*env)->SetObjectArrayElement(env, jthreads, i, NULL);
    }
  
    (*_jvmti)->Deallocate(_jvmti, (unsigned char*) threads);
    return jthreads;
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    getThreadsStatus
 * Signature: ([Ljava/lang/Thread;[I)V
 */
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getThreadsStatus
    (JNIEnv *env, jclass clz, jobjectArray jthreads, jintArray jstatus) 
{
    int nThreads, i;
    jint threadStatus;
    jint *status;
  
    nThreads = (*env)->GetArrayLength(env, jthreads);
    status = malloc(nThreads * sizeof(jint));
  
    for (i = 0; i < nThreads; i++) {
        jthread thread = (*env)->GetObjectArrayElement(env, jthreads, i);
        if (thread == NULL) {
            continue;
         }
        (*_jvmti)->GetThreadState(_jvmti, thread, &threadStatus);
        status[i] = convert_JVMTI_thread_status_to_jfluid_status(threadStatus);
    }
  
    (*env)->SetIntArrayRegion(env, jstatus, 0, nThreads, status);
    free(status);
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    getJVMArguments
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getJVMArguments
    (JNIEnv *env, jclass clz) 
{
    jstring ret = (*env)->NewStringUTF(env, "*NOT PROVIDED IN THIS JVM VERSION*");
    return ret;
}


/*
 * Class:     org_netbeans_lib_profiler_server_system_Threads
 * Method:    getJavaCommand
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getJavaCommand
    (JNIEnv *env, jclass clz) 
{
    jstring ret = (*env)->NewStringUTF(env, "*NOT PROVIDED IN THIS JVM VERSION*");
    return ret;
}
