// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.


#ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_
#define BASE_DEBUG_TRACE_EVENT_IMPL_H_

#include "build/build_config.h"

#include <string>
#include <vector>

#include "base/callback.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted_memory.h"
#include "base/observer_list.h"
#include "base/string_util.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/timer.h"

// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
    base::debug::TraceLog::AddTraceEventEtw( \
        TRACE_EVENT_PHASE_BEGIN, \
        name, reinterpret_cast<const void*>(id), extra)

#define TRACE_EVENT_END_ETW(name, id, extra) \
    base::debug::TraceLog::AddTraceEventEtw( \
        TRACE_EVENT_PHASE_END, \
        name, reinterpret_cast<const void*>(id), extra)

#define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
    base::debug::TraceLog::AddTraceEventEtw( \
        TRACE_EVENT_PHASE_INSTANT, \
        name, reinterpret_cast<const void*>(id), extra)

template <typename Type>
struct StaticMemorySingletonTraits;

namespace base {

namespace debug {

const int kTraceMaxNumArgs = 2;

// Output records are "Events" and can be obtained via the
// OutputCallback whenever the tracing system decides to flush. This
// can happen at any time, on any thread, or you can programatically
// force it to happen.
class BASE_EXPORT TraceEvent {
 public:
  union TraceValue {
    bool as_bool;
    unsigned long long as_uint;
    long long as_int;
    double as_double;
    const void* as_pointer;
    const char* as_string;
  };

  TraceEvent();
  TraceEvent(int thread_id,
             TimeTicks timestamp,
             TimeTicks thread_timestamp,
             char phase,
             const unsigned char* category_enabled,
             const char* name,
             unsigned long long id,
             int num_args,
             const char** arg_names,
             const unsigned char* arg_types,
             const unsigned long long* arg_values,
             unsigned char flags);
  ~TraceEvent();

  // Serialize event data to JSON
  static void AppendEventsAsJSON(const std::vector<TraceEvent>& events,
                                 size_t start,
                                 size_t count,
                                 std::string* out);
  void AppendAsJSON(std::string* out) const;

  static void AppendValueAsJSON(unsigned char type,
                                TraceValue value,
                                std::string* out);

  TimeTicks timestamp() const { return timestamp_; }
  TimeTicks thread_timestamp() const { return thread_timestamp_; }

  // Exposed for unittesting:

  const base::RefCountedString* parameter_copy_storage() const {
    return parameter_copy_storage_.get();
  }

  const unsigned char* category_enabled() const { return category_enabled_; }
  const char* name() const { return name_; }

#if defined(COBALT)
  unsigned long long id() const { return id_; }
  const TraceValue* arg_values() const { return arg_values_; }
  int thread_id() const { return thread_id_; }
  char phase() const { return phase_; }
#endif

 private:
  // Note: these are ordered by size (largest first) for optimal packing.
  TimeTicks timestamp_;
  TimeTicks thread_timestamp_;
  // id_ can be used to store phase-specific data.
  unsigned long long id_;
  TraceValue arg_values_[kTraceMaxNumArgs];
  const char* arg_names_[kTraceMaxNumArgs];
  const unsigned char* category_enabled_;
  const char* name_;
  scoped_refptr<base::RefCountedString> parameter_copy_storage_;
  int thread_id_;
  char phase_;
  unsigned char flags_;
  unsigned char arg_types_[kTraceMaxNumArgs];
};


// TraceResultBuffer collects and converts trace fragments returned by TraceLog
// to JSON output.
class BASE_EXPORT TraceResultBuffer {
 public:
  typedef base::Callback<void(const std::string&)> OutputCallback;

  // If you don't need to stream JSON chunks out efficiently, and just want to
  // get a complete JSON string after calling Finish, use this struct to collect
  // JSON trace output.
  struct BASE_EXPORT SimpleOutput {
    OutputCallback GetCallback();
    void Append(const std::string& json_string);

    // Do what you want with the json_output_ string after calling
    // TraceResultBuffer::Finish.
    std::string json_output;
  };

  TraceResultBuffer();
  ~TraceResultBuffer();

  // Set callback. The callback will be called during Start with the initial
  // JSON output and during AddFragment and Finish with following JSON output
  // chunks. The callback target must live past the last calls to
  // TraceResultBuffer::Start/AddFragment/Finish.
  void SetOutputCallback(const OutputCallback& json_chunk_callback);

  // Start JSON output. This resets all internal state, so you can reuse
  // the TraceResultBuffer by calling Start.
  void Start();

  // Call AddFragment 0 or more times to add trace fragments from TraceLog.
  void AddFragment(const std::string& trace_fragment);

  // When all fragments have been added, call Finish to complete the JSON
  // formatted output.
  void Finish();

 private:
  OutputCallback output_callback_;
  bool append_comma_;
};


class BASE_EXPORT TraceLog {
 public:
  // Notification is a mask of one or more of the following events.
  enum Notification {
    // The trace buffer does not flush dynamically, so when it fills up,
    // subsequent trace events will be dropped. This callback is generated when
    // the trace buffer is full. The callback must be thread safe.
    TRACE_BUFFER_FULL = 1 << 0,
    // A subscribed trace-event occurred.
    EVENT_WATCH_NOTIFICATION = 1 << 1
  };

  static TraceLog* GetInstance();

  // Get set of known categories. This can change as new code paths are reached.
  // The known categories are inserted into |categories|.
  void GetKnownCategories(std::vector<std::string>* categories);

  // Enable tracing for provided list of categories. If tracing is already
  // enabled, this method does nothing -- changing categories during trace is
  // not supported.
  // If both included_categories and excluded_categories are empty,
  //   all categories are traced.
  // Else if included_categories is non-empty, only those are traced.
  // Else if excluded_categories is non-empty, everything but those are traced.
  // Wildcards * and ? are supported (see MatchPattern in string_util.h).
  void SetEnabled(const std::vector<std::string>& included_categories,
                  const std::vector<std::string>& excluded_categories);

  // |categories| is a comma-delimited list of category wildcards.
  // A category can have an optional '-' prefix to make it an excluded category.
  // All the same rules apply above, so for example, having both included and
  // excluded categories in the same list would not be supported.
  //
  // Example: SetEnabled("test_MyTest*");
  // Example: SetEnabled("test_MyTest*,test_OtherStuff");
  // Example: SetEnabled("-excluded_category1,-excluded_category2");
  void SetEnabled(const std::string& categories);

  // Retieves the categories set via a prior call to SetEnabled(). Only
  // meaningful if |IsEnabled()| is true.
  void GetEnabledTraceCategories(std::vector<std::string>* included_out,
                                 std::vector<std::string>* excluded_out);

  // Disable tracing for all categories.
  void SetDisabled();
  // Helper method to enable/disable tracing for all categories.
  void SetEnabled(bool enabled);
  bool IsEnabled() { return enabled_; }

#if defined(OS_ANDROID) || defined(__LB_ANDROID__)
  static void InitATrace();
#endif

  // Enabled state listeners give a callback when tracing is enabled or
  // disabled. This can be used to tie into other library's tracing systems
  // on-demand.
  class EnabledStateChangedObserver {
   public:
    // Called just before the tracing system becomes
    // enabled. TraceLog::IsEnabled will return false at this point and trace
    // macros and methods called within the observer will deadlock.
    virtual void OnTraceLogWillEnable() { }

    // Called just before the tracing system disables. TraceLog::IsEnabled is
    // still false at this point TRACE macros will still be capturing
    // data. However, trace macros and methods called within the observer will
    // deadlock.
    virtual void OnTraceLogWillDisable() { }
  };
  void AddEnabledStateObserver(EnabledStateChangedObserver* listener);
  void RemoveEnabledStateObserver(EnabledStateChangedObserver* listener);

  float GetBufferPercentFull() const;

  // Set the thread-safe notification callback. The callback can occur at any
  // time and from any thread. WARNING: It is possible for the previously set
  // callback to be called during OR AFTER a call to SetNotificationCallback.
  // Therefore, the target of the callback must either be a global function,
  // ref-counted object or a LazyInstance with Leaky traits (or equivalent).
  typedef base::Callback<void(int)> NotificationCallback;
  void SetNotificationCallback(const NotificationCallback& cb);

  // Flush all collected events to the given output callback. The callback will
  // be called one or more times with IPC-bite-size chunks. The string format is
  // undefined. Use TraceResultBuffer to convert one or more trace strings to
  // JSON.
  typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
      OutputCallback;
  void Flush(const OutputCallback& cb);

#if defined(COBALT)
  // Flush out events as raw TraceEvent structures.  Optinally also flush out
  // JSON output as well.
  typedef base::Callback<void(const TraceEvent&)> RawEventOutputCallback;
  void FlushWithRawEvents(const RawEventOutputCallback& raw_event_callback,
                          const OutputCallback& json_output_callback);
#endif

  // Called by TRACE_EVENT* macros, don't call this directly.
  static const unsigned char* GetCategoryEnabled(const char* name);
  static const char* GetCategoryName(const unsigned char* category_enabled);

  // Called by TRACE_EVENT* macros, don't call this directly.
  // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
  // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
  void AddTraceEvent(char phase,
                    const unsigned char* category_enabled,
                    const char* name,
                    unsigned long long id,
                    int num_args,
                    const char** arg_names,
                    const unsigned char* arg_types,
                    const unsigned long long* arg_values,
                    unsigned char flags);
  static void AddTraceEventEtw(char phase,
                               const char* name,
                               const void* id,
                               const char* extra);
  static void AddTraceEventEtw(char phase,
                               const char* name,
                               const void* id,
                               const std::string& extra);

  // For every matching event, a notification will be fired. NOTE: the
  // notification will fire for each matching event that has already occurred
  // since tracing was started (including before tracing if the process was
  // started with tracing turned on).
  void SetWatchEvent(const std::string& category_name,
                     const std::string& event_name);
  // Cancel the watch event. If tracing is enabled, this may race with the
  // watch event notification firing.
  void CancelWatchEvent();

  int process_id() const { return process_id_; }

  // Exposed for unittesting:

  // Allows deleting our singleton instance.
  static void DeleteForTesting();

  // Allows resurrecting our singleton instance post-AtExit processing.
  static void Resurrect();

  // Allow tests to inspect TraceEvents.
  size_t GetEventsSize() const { return logged_events_.size(); }
  const TraceEvent& GetEventAt(size_t index) const {
    DCHECK(index < logged_events_.size());
    return logged_events_[index];
  }

  void SetProcessID(int process_id);

  // Allow setting an offset between the current TimeTicks time and the time
  // that should be reported.
  void SetTimeOffset(TimeDelta offset);

 private:
  // This allows constructor and destructor to be private and usable only
  // by the Singleton class.
  friend struct StaticMemorySingletonTraits<TraceLog>;

  // The pointer returned from GetCategoryEnabledInternal() points to a value
  // with zero or more of the following bits. Used in this class only.
  // The TRACE_EVENT macros should only use the value as a bool.
  enum CategoryEnabledFlags {
    // Normal enabled flag for categories enabled with Enable().
    CATEGORY_ENABLED = 1 << 0,
    // On Android if ATrace is enabled, all categories will have this bit.
    // Not used on other platforms.
    ATRACE_ENABLED = 1 << 1
  };

  // Helper class for managing notification_thread_count_ and running
  // notification callbacks. This is very similar to a reader-writer lock, but
  // shares the lock with TraceLog and manages the notification flags.
  class NotificationHelper {
   public:
    inline explicit NotificationHelper(TraceLog* trace_log);
    inline ~NotificationHelper();

    // Called only while TraceLog::lock_ is held. This ORs the given
    // notification with any existing notifcations.
    inline void AddNotificationWhileLocked(int notification);

    // Called only while TraceLog::lock_ is NOT held. If there are any pending
    // notifications from previous calls to AddNotificationWhileLocked, this
    // will call the NotificationCallback.
    inline void SendNotificationIfAny();

   private:
    TraceLog* trace_log_;
    NotificationCallback callback_copy_;
    int notification_;
  };

  TraceLog();
  ~TraceLog();
  const unsigned char* GetCategoryEnabledInternal(const char* name);
  void AddThreadNameMetadataEvents();

#if defined(OS_ANDROID) || defined(__LB_ANDROID__)
  void SendToATrace(char phase,
                    const char* category,
                    const char* name,
                    int num_args,
                    const char** arg_names,
                    const unsigned char* arg_types,
                    const unsigned long long* arg_values);
  void AddClockSyncMetadataEvents();
  static void ApplyATraceEnabledFlag(unsigned char* category_enabled);
#endif

  // TODO(nduca): switch to per-thread trace buffers to reduce thread
  // synchronization.
  // This lock protects TraceLog member accesses from arbitrary threads.
  Lock lock_;
  bool enabled_;
  NotificationCallback notification_callback_;
  std::vector<TraceEvent> logged_events_;
  std::vector<std::string> included_categories_;
  std::vector<std::string> excluded_categories_;
  bool dispatching_to_observer_list_;
  ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_;

  base::hash_map<int, std::string> thread_names_;

  // XORed with TraceID to make it unlikely to collide with other processes.
  unsigned long long process_id_hash_;

  int process_id_;

  TimeDelta time_offset_;

  // Allow tests to wake up when certain events occur.
  const unsigned char* watch_category_;
  std::string watch_event_name_;

  DISALLOW_COPY_AND_ASSIGN(TraceLog);
};

}  // namespace debug
}  // namespace base

#endif  // BASE_DEBUG_TRACE_EVENT_IMPL_H_
