- add sources.
[platform/framework/web/crosswalk.git] / src / base / win / event_trace_consumer.h
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // Declaration of a Windows event trace consumer base class.
6 #ifndef BASE_WIN_EVENT_TRACE_CONSUMER_H_
7 #define BASE_WIN_EVENT_TRACE_CONSUMER_H_
8
9 #include <windows.h>
10 #include <wmistr.h>
11 #include <evntrace.h>
12 #include <vector>
13 #include "base/basictypes.h"
14
15 namespace base {
16 namespace win {
17
18 // This class is a base class that makes it easier to consume events
19 // from realtime or file sessions. Concrete consumers need to sublass
20 // a specialization of this class and override the ProcessEvent and/or
21 // the ProcessBuffer methods to implement the event consumption logic.
22 // Usage might look like:
23 // class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> {
24 //  protected:
25 //    static VOID WINAPI ProcessEvent(PEVENT_TRACE event);
26 // };
27 //
28 // MyConsumer consumer;
29 // consumer.OpenFileSession(file_path);
30 // consumer.Consume();
31 template <class ImplClass>
32 class EtwTraceConsumerBase {
33  public:
34   // Constructs a closed consumer.
35   EtwTraceConsumerBase() {
36   }
37
38   ~EtwTraceConsumerBase() {
39     Close();
40   }
41
42   // Opens the named realtime session, which must be existent.
43   // Note: You can use OpenRealtimeSession or OpenFileSession
44   //    to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at
45   //    any one time, though only one of them may be a realtime
46   //    session.
47   HRESULT OpenRealtimeSession(const wchar_t* session_name);
48
49   // Opens the event trace log in "file_name", which must be a full or
50   // relative path to an existing event trace log file.
51   // Note: You can use OpenRealtimeSession or OpenFileSession
52   //    to open as many as kNumSessions at any one time.
53   HRESULT OpenFileSession(const wchar_t* file_name);
54
55   // Consume all open sessions from beginning to end.
56   HRESULT Consume();
57
58   // Close all open sessions.
59   HRESULT Close();
60
61  protected:
62   // Override in subclasses to handle events.
63   static void ProcessEvent(EVENT_TRACE* event) {
64   }
65   // Override in subclasses to handle buffers.
66   static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) {
67     return true;  // keep going
68   }
69
70  protected:
71   // Currently open sessions.
72   std::vector<TRACEHANDLE> trace_handles_;
73
74  private:
75   // These delegate to ImplClass callbacks with saner signatures.
76   static void WINAPI ProcessEventCallback(EVENT_TRACE* event) {
77     ImplClass::ProcessEvent(event);
78   }
79   static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) {
80     return ImplClass::ProcessBuffer(buffer);
81   }
82
83   DISALLOW_COPY_AND_ASSIGN(EtwTraceConsumerBase);
84 };
85
86 template <class ImplClass> inline
87 HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession(
88     const wchar_t* session_name) {
89   EVENT_TRACE_LOGFILE logfile = {};
90   logfile.LoggerName = const_cast<wchar_t*>(session_name);
91   logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
92   logfile.BufferCallback = &ProcessBufferCallback;
93   logfile.EventCallback = &ProcessEventCallback;
94   logfile.Context = this;
95   TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
96   if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
97     return HRESULT_FROM_WIN32(::GetLastError());
98
99   trace_handles_.push_back(trace_handle);
100   return S_OK;
101 }
102
103 template <class ImplClass> inline
104 HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession(
105     const wchar_t* file_name) {
106   EVENT_TRACE_LOGFILE logfile = {};
107   logfile.LogFileName = const_cast<wchar_t*>(file_name);
108   logfile.BufferCallback = &ProcessBufferCallback;
109   logfile.EventCallback = &ProcessEventCallback;
110   logfile.Context = this;
111   TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
112   if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
113     return HRESULT_FROM_WIN32(::GetLastError());
114
115   trace_handles_.push_back(trace_handle);
116   return S_OK;
117 }
118
119 template <class ImplClass> inline
120 HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
121   ULONG err = ::ProcessTrace(&trace_handles_[0],
122                              trace_handles_.size(),
123                              NULL,
124                              NULL);
125   return HRESULT_FROM_WIN32(err);
126 }
127
128 template <class ImplClass> inline
129 HRESULT EtwTraceConsumerBase<ImplClass>::Close() {
130   HRESULT hr = S_OK;
131   for (size_t i = 0; i < trace_handles_.size(); ++i) {
132     if (NULL != trace_handles_[i]) {
133       ULONG ret = ::CloseTrace(trace_handles_[i]);
134       trace_handles_[i] = NULL;
135
136       if (FAILED(HRESULT_FROM_WIN32(ret)))
137         hr = HRESULT_FROM_WIN32(ret);
138     }
139   }
140   trace_handles_.clear();
141
142   return hr;
143 }
144
145 }  // namespace win
146 }  // namespace base
147
148 #endif  // BASE_WIN_EVENT_TRACE_CONSUMER_H_