// 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"

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() {
  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_
