///===-- 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 <dlfcn.h>
#include <string>
#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) {
    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;
      for (activity_search = activities.begin();
           activity_search != activities.end(); ++activity_search) {
        if (activity_search->activity_id == activity_id) {
          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 =
      static_cast<uint32_t>(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(size_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;
}
