// 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.
//
// Declaration of a Windows event trace consumer base class.
#ifndef BASE_WIN_EVENT_TRACE_CONSUMER_H_
#define BASE_WIN_EVENT_TRACE_CONSUMER_H_

#include <windows.h>
#include <wmistr.h>
#include <evntrace.h>
#include <stddef.h>
#include <vector>

#include "base/macros.h"
#include "base/threading/scoped_blocking_call.h"

namespace base {
namespace win {

// This class is a base class that makes it easier to consume events
// from realtime or file sessions. Concrete consumers need to subclass
// a specialization of this class and override the ProcessEvent and/or
// the ProcessBuffer methods to implement the event consumption logic.
// Usage might look like:
// class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> {
//  protected:
//    static VOID WINAPI ProcessEvent(PEVENT_TRACE event);
// };
//
// MyConsumer consumer;
// consumer.OpenFileSession(file_path);
// consumer.Consume();
template <class ImplClass>
class EtwTraceConsumerBase {
 public:
  // Constructs a closed consumer.
  EtwTraceConsumerBase() {
  }

  ~EtwTraceConsumerBase() {
    Close();
  }

  // Opens the named realtime session, which must be existent.
  // Note: You can use OpenRealtimeSession or OpenFileSession
  //    to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at
  //    any one time, though only one of them may be a realtime
  //    session.
  HRESULT OpenRealtimeSession(const wchar_t* session_name);

  // Opens the event trace log in "file_name", which must be a full or
  // relative path to an existing event trace log file.
  // Note: You can use OpenRealtimeSession or OpenFileSession
  //    to open as many as kNumSessions at any one time.
  HRESULT OpenFileSession(const wchar_t* file_name);

  // Consume all open sessions from beginning to end.
  HRESULT Consume();

  // Close all open sessions.
  HRESULT Close();

 protected:
  // Override in subclasses to handle events.
  static void ProcessEvent(EVENT_TRACE* event) {
  }
  // Override in subclasses to handle buffers.
  static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) {
    return true;  // keep going
  }

 protected:
  // Currently open sessions.
  std::vector<TRACEHANDLE> trace_handles_;

 private:
  // These delegate to ImplClass callbacks with saner signatures.
  static void WINAPI ProcessEventCallback(EVENT_TRACE* event) {
    ImplClass::ProcessEvent(event);
  }
  static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) {
    return ImplClass::ProcessBuffer(buffer);
  }

  DISALLOW_COPY_AND_ASSIGN(EtwTraceConsumerBase);
};

template <class ImplClass> inline
HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession(
    const wchar_t* session_name) {
  EVENT_TRACE_LOGFILE logfile = {};
  logfile.LoggerName = const_cast<wchar_t*>(session_name);
  logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  logfile.BufferCallback = &ProcessBufferCallback;
  logfile.EventCallback = &ProcessEventCallback;
  logfile.Context = this;
  TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
  if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
    return HRESULT_FROM_WIN32(::GetLastError());

  trace_handles_.push_back(trace_handle);
  return S_OK;
}

template <class ImplClass> inline
HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession(
    const wchar_t* file_name) {
  EVENT_TRACE_LOGFILE logfile = {};
  logfile.LogFileName = const_cast<wchar_t*>(file_name);
  logfile.BufferCallback = &ProcessBufferCallback;
  logfile.EventCallback = &ProcessEventCallback;
  logfile.Context = this;
  TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
  if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
    return HRESULT_FROM_WIN32(::GetLastError());

  trace_handles_.push_back(trace_handle);
  return S_OK;
}

template <class ImplClass> inline
HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  ULONG err = ::ProcessTrace(&trace_handles_[0],
                             static_cast<ULONG>(trace_handles_.size()),
                             NULL,
                             NULL);
  return HRESULT_FROM_WIN32(err);
}

template <class ImplClass> inline
HRESULT EtwTraceConsumerBase<ImplClass>::Close() {
  HRESULT hr = S_OK;
  for (size_t i = 0; i < trace_handles_.size(); ++i) {
    if (NULL != trace_handles_[i]) {
      ULONG ret = ::CloseTrace(trace_handles_[i]);
      trace_handles_[i] = NULL;

      if (FAILED(HRESULT_FROM_WIN32(ret)))
        hr = HRESULT_FROM_WIN32(ret);
    }
  }
  trace_handles_.clear();

  return hr;
}

}  // namespace win
}  // namespace base

#endif  // BASE_WIN_EVENT_TRACE_CONSUMER_H_
