///===-- Activity.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <Availability.h>
#include <string>
#include <dlfcn.h>
#include <uuid/uuid.h>

#include "DNBDefs.h"
#include "Genealogy.h"
#include "GenealogySPI.h"
#include "MachThreadList.h"

//---------------------------
/// Constructor
//---------------------------

Genealogy::Genealogy () :
    m_os_activity_diagnostic_for_pid (nullptr),
    m_os_activity_iterate_processes (nullptr),
    m_os_activity_iterate_breadcrumbs (nullptr),
    m_os_activity_iterate_messages (nullptr),
    m_os_activity_iterate_activities (nullptr),
    m_os_trace_get_type (nullptr),
    m_os_trace_copy_formatted_message (nullptr),
    m_os_activity_for_thread (nullptr),
    m_os_activity_for_task_thread (nullptr),
    m_thread_activities(),
    m_process_executable_infos(),
    m_diagnosticd_call_timed_out(false)
{
    m_os_activity_diagnostic_for_pid = (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym (RTLD_DEFAULT, "os_activity_diagnostic_for_pid");
    m_os_activity_iterate_processes = (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_processes");
    m_os_activity_iterate_breadcrumbs = (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t))) dlsym (RTLD_DEFAULT, "os_activity_iterate_breadcrumbs");
    m_os_activity_iterate_messages = (void (*)(os_trace_message_list_t, os_activity_process_t, bool (^)(os_trace_message_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_messages");
    m_os_activity_iterate_activities = (void (*)(os_activity_list_t, os_activity_process_t, bool (^)(os_activity_entry_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_activities");
    m_os_trace_get_type = (uint8_t (*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_get_type");
    m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_copy_formatted_message");
    m_os_activity_for_thread = (os_activity_t (*)(os_activity_process_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_thread");
    m_os_activity_for_task_thread = (os_activity_t (*)(task_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_task_thread");
    m_os_activity_messages_for_thread = (os_trace_message_list_t (*) (os_activity_process_t process, os_activity_t activity, uint64_t thread_id)) dlsym (RTLD_DEFAULT, "os_activity_messages_for_thread");
}

Genealogy::ThreadActivitySP
Genealogy::GetGenealogyInfoForThread (pid_t pid, nub_thread_t tid, const MachThreadList &thread_list, task_t task, bool &timed_out)
{
    ThreadActivitySP activity;
    //
    // if we've timed out trying to get the activities, don't try again at this process stop.
    // (else we'll need to hit the timeout for every thread we're asked about.)
    // We'll try again at the next public stop.

    if (m_thread_activities.size() == 0 && m_diagnosticd_call_timed_out == false)
    {
        GetActivities(pid, thread_list, task);
    }
    std::map<nub_thread_t, ThreadActivitySP>::const_iterator search;
    search = m_thread_activities.find(tid);
    if (search != m_thread_activities.end())
    {
        activity = search->second;
    }
    timed_out = m_diagnosticd_call_timed_out;
    return activity;
}

void
Genealogy::Clear()
{
    m_thread_activities.clear();
    m_diagnosticd_call_timed_out = false;
}

void
Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task)
{
    if (m_os_activity_diagnostic_for_pid != nullptr 
        && m_os_activity_iterate_processes != nullptr
        && m_os_activity_iterate_breadcrumbs != nullptr
        && m_os_activity_iterate_messages != nullptr
        && m_os_activity_iterate_activities != nullptr
        && m_os_trace_get_type != nullptr
        && m_os_trace_copy_formatted_message != nullptr
        && (m_os_activity_for_thread != nullptr || m_os_activity_for_task_thread != nullptr)
       )
    {
        __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        __block BreadcrumbList breadcrumbs;
        __block ActivityList activities;
        __block MessageList messages;
        __block std::map<nub_thread_t, uint64_t> thread_activity_mapping;

        os_activity_diagnostic_flag_t flags = OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES | OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY;
        if (m_os_activity_diagnostic_for_pid (pid, 0, flags, ^(os_activity_process_list_t processes, int error)
        {
            if (error == 0)
            {
                m_os_activity_iterate_processes (processes, ^bool(os_activity_process_t process_info)
                {
                    if (pid == process_info->pid)
                    {
                        // Collect all the Breadcrumbs
                        m_os_activity_iterate_breadcrumbs (process_info, ^bool(os_activity_breadcrumb_t breadcrumb)
                        {
                            Breadcrumb bc;
                            bc.breadcrumb_id = breadcrumb->breadcrumb_id;
                            bc.activity_id = breadcrumb->activity_id;
                            bc.timestamp = breadcrumb->timestamp;
                            if (breadcrumb->name) 
                                bc.name = breadcrumb->name;
                            breadcrumbs.push_back (bc);
                            return true;
                        });

                        // Collect all the Activites
                        m_os_activity_iterate_activities (process_info->activities, process_info, ^bool(os_activity_entry_t activity)
                        {
                            Activity ac;
                            ac.activity_start = activity->activity_start;
                            ac.activity_id = activity->activity_id;
                            ac.parent_id = activity->parent_id;
                            if (activity->activity_name)
                                ac.activity_name = activity->activity_name;
                            if (activity->reason)
                                ac.reason = activity->reason;
                            activities.push_back (ac);
                            return true;
                        });


                        // Collect all the Messages -- messages not associated with any thread
                        m_os_activity_iterate_messages (process_info->messages, process_info, ^bool(os_trace_message_t trace_msg)
                        {
                            Message msg;
                            msg.timestamp = trace_msg->timestamp;
                            msg.trace_id = trace_msg->trace_id;
                            msg.thread = trace_msg->thread;
                            msg.type = m_os_trace_get_type (trace_msg);
                            msg.activity_id = 0;
                            if (trace_msg->image_uuid && trace_msg->image_path)
                            {
                                ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo());
                                uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid);
                                process_info_sp->image_path = trace_msg->image_path;
                                msg.process_info_index = AddProcessExecutableInfo (process_info_sp);
                            }
                            const char *message_text = m_os_trace_copy_formatted_message (trace_msg);
                            if (message_text)
                                msg.message = message_text;
                            messages.push_back (msg);
                            return true;
                        });

                        // Discover which activities are said to be running on threads currently
                        const nub_size_t num_threads = thread_list.NumThreads();
                        for (nub_size_t i = 0; i < num_threads; ++i)
                        {
                            nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i);
                            os_activity_t act = 0;
                            if (m_os_activity_for_task_thread != nullptr)
                            {
                                act = m_os_activity_for_task_thread (task, thread_id);
                            }
                            else if (m_os_activity_for_thread != nullptr)
                            {
                                act = m_os_activity_for_thread (process_info, thread_id);
                            }
                            if (act != 0)
                                thread_activity_mapping[thread_id] = act;
                        }

                        // Collect all Messages -- messages associated with a thread

                        // When there's no genealogy information, an early version of os_activity_messages_for_thread
                        // can crash in rare circumstances.  Check to see if this process has any activities before
                        // making the call to get messages.
                        if (process_info->activities != nullptr && thread_activity_mapping.size() > 0)
                        {
                            std::map<nub_thread_t, uint64_t>::const_iterator iter;
                            for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter)
                            {
                                nub_thread_t thread_id = iter->first;
                                os_activity_t act = iter->second;
                                os_trace_message_list_t this_thread_messages = m_os_activity_messages_for_thread (process_info, act, thread_id);
                                m_os_activity_iterate_messages (this_thread_messages, process_info, ^bool(os_trace_message_t trace_msg)
                                {
                                    Message msg;
                                    msg.timestamp = trace_msg->timestamp;
                                    msg.trace_id = trace_msg->trace_id;
                                    msg.thread = trace_msg->thread;
                                    msg.type = m_os_trace_get_type (trace_msg);
                                    msg.activity_id = act;
                                    if (trace_msg->image_uuid && trace_msg->image_path)
                                    {
                                        ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo());
                                        uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid);
                                        process_info_sp->image_path = trace_msg->image_path;
                                        msg.process_info_index = AddProcessExecutableInfo (process_info_sp);
                                    }
                                    const char *message_text = m_os_trace_copy_formatted_message (trace_msg);
                                    if (message_text)
                                        msg.message = message_text;
                                    messages.push_back (msg);
                                    return true;
                                });
                            }
                        }
                    }
                return true;
                });
            }
            dispatch_semaphore_signal(semaphore);
        }) == true)
        {
            // Wait for the diagnosticd xpc calls to all finish up -- or half a second to elapse.
            dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2);
            bool success = dispatch_semaphore_wait(semaphore, timeout) == 0;
            if (!success)
            {
                m_diagnosticd_call_timed_out = true;
                return;
            }
        }

        // breadcrumbs, activities, and messages have all now been filled in.

        std::map<nub_thread_t, uint64_t>::const_iterator iter;
        for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter)
        {
            nub_thread_t thread_id = iter->first;
            uint64_t activity_id = iter->second;
            ActivityList::const_iterator activity_search;
            bool found_activity_for_this_thread = false;
            for (activity_search = activities.begin(); activity_search != activities.end(); ++activity_search)
            {
                if (activity_search->activity_id == activity_id)
                {
                    found_activity_for_this_thread = true;
                    ThreadActivitySP thread_activity_sp (new ThreadActivity());
                    thread_activity_sp->current_activity = *activity_search;
    
                    BreadcrumbList::const_iterator breadcrumb_search;
                    for (breadcrumb_search = breadcrumbs.begin(); breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search)
                    {
                        if (breadcrumb_search->activity_id == activity_id)
                        {
                            thread_activity_sp->breadcrumbs.push_back (*breadcrumb_search);
                        }
                    }
                    MessageList::const_iterator message_search;
                    for (message_search = messages.begin(); message_search != messages.end(); ++message_search)
                    {
                        if (message_search->thread == thread_id)
                        {
                            thread_activity_sp->messages.push_back (*message_search);
                        }
                    }
    
                    m_thread_activities[thread_id] = thread_activity_sp;
                    break;
                }
            }
        }
    }
}

uint32_t
Genealogy::AddProcessExecutableInfo (ProcessExecutableInfoSP process_exe_info)
{
    const uint32_t info_size = m_process_executable_infos.size();
    for (uint32_t idx = 0; idx < info_size; ++idx)
    {
        if (uuid_compare (m_process_executable_infos[idx]->image_uuid, process_exe_info->image_uuid) == 0)
        {
            return idx + 1;
        }
    }
    m_process_executable_infos.push_back (process_exe_info);
    return info_size + 1;
}

Genealogy::ProcessExecutableInfoSP
Genealogy::GetProcessExecutableInfosAtIndex(uint32_t idx)
{
    ProcessExecutableInfoSP info_sp;
    if (idx > 0)
    {
        idx--;
        if (idx <= m_process_executable_infos.size())
        {
            info_sp = m_process_executable_infos[idx];
        }
    }
    return info_sp;
}

