1// Copyright (c) 2006-2008 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#include "net/disk_cache/trace.h"
6
7#include <stdio.h>
8#if defined(OS_WIN)
9#include <windows.h>
10#endif
11
12#include "base/logging.h"
13
14// Change this value to 1 to enable tracing on a release build. By default,
15// tracing is enabled only on debug builds.
16#define ENABLE_TRACING 0
17
18#ifndef NDEBUG
19#undef ENABLE_TRACING
20#define ENABLE_TRACING 1
21#endif
22
23namespace {
24
25const int kEntrySize = 48;
26const int kNumberOfEntries = 5000;  // 240 KB.
27
28struct TraceBuffer {
29  int num_traces;
30  int current;
31  char buffer[kNumberOfEntries][kEntrySize];
32};
33
34#if ENABLE_TRACING
35void DebugOutput(const char* msg) {
36#if defined(OS_WIN)
37  OutputDebugStringA(msg);
38#else
39  NOTIMPLEMENTED();
40#endif
41}
42#endif  // ENABLE_TRACING
43
44}  // namespace
45
46namespace disk_cache {
47
48// s_trace_buffer and s_trace_object are not singletons because I want the
49// buffer to be destroyed and re-created when the last user goes away, and it
50// must be straightforward to access the buffer from the debugger.
51static TraceObject* s_trace_object = NULL;
52
53// Static.
54TraceObject* TraceObject::GetTraceObject() {
55  if (s_trace_object)
56    return s_trace_object;
57
58  s_trace_object = new TraceObject();
59  return s_trace_object;
60}
61
62TraceObject::TraceObject() {
63  InitTrace();
64}
65
66TraceObject::~TraceObject() {
67  DestroyTrace();
68}
69
70#if ENABLE_TRACING
71
72static TraceBuffer* s_trace_buffer = NULL;
73
74void InitTrace(void) {
75  if (s_trace_buffer)
76    return;
77
78  s_trace_buffer = new TraceBuffer;
79  memset(s_trace_buffer, 0, sizeof(*s_trace_buffer));
80}
81
82void DestroyTrace(void) {
83  delete s_trace_buffer;
84  s_trace_buffer = NULL;
85  s_trace_object = NULL;
86}
87
88void Trace(const char* format, ...) {
89  if (!s_trace_buffer)
90    return;
91
92  va_list ap;
93  va_start(ap, format);
94
95#if defined(OS_WIN)
96  vsprintf_s(s_trace_buffer->buffer[s_trace_buffer->current], format, ap);
97#else
98  vsnprintf(s_trace_buffer->buffer[s_trace_buffer->current],
99            sizeof(s_trace_buffer->buffer[s_trace_buffer->current]), format,
100            ap);
101#endif
102  s_trace_buffer->num_traces++;
103  s_trace_buffer->current++;
104  if (s_trace_buffer->current == kNumberOfEntries)
105    s_trace_buffer->current = 0;
106
107  va_end(ap);
108}
109
110// Writes the last num_traces to the debugger output.
111void DumpTrace(int num_traces) {
112  DCHECK(s_trace_buffer);
113  DebugOutput("Last traces:\n");
114
115  if (num_traces > kNumberOfEntries || num_traces < 0)
116    num_traces = kNumberOfEntries;
117
118  if (s_trace_buffer->num_traces) {
119    char line[kEntrySize + 2];
120
121    int current = s_trace_buffer->current - num_traces;
122    if (current < 0)
123      current += kNumberOfEntries;
124
125    for (int i = 0; i < num_traces; i++) {
126      memcpy(line, s_trace_buffer->buffer[current], kEntrySize);
127      line[kEntrySize] = '\0';
128      size_t length = strlen(line);
129      if (length) {
130        line[length] = '\n';
131        line[length + 1] = '\0';
132        DebugOutput(line);
133      }
134
135      current++;
136      if (current ==  kNumberOfEntries)
137        current = 0;
138    }
139  }
140
141  DebugOutput("End of Traces\n");
142}
143
144#else  // ENABLE_TRACING
145
146void InitTrace(void) {
147  return;
148}
149
150void DestroyTrace(void) {
151  s_trace_object = NULL;
152}
153
154void Trace(const char* format, ...) {
155}
156
157#endif  // ENABLE_TRACING
158
159}  // namespace disk_cache
160