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 23 namespace { 24 25 const int kEntrySize = 48; 26 const int kNumberOfEntries = 5000; // 240 KB. 27 28 struct TraceBuffer { 29 int num_traces; 30 int current; 31 char buffer[kNumberOfEntries][kEntrySize]; 32 }; 33 34 #if ENABLE_TRACING 35 void 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 46 namespace 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. 51 static TraceObject* s_trace_object = NULL; 52 53 // Static. 54 TraceObject* 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 62 TraceObject::TraceObject() { 63 InitTrace(); 64 } 65 66 TraceObject::~TraceObject() { 67 DestroyTrace(); 68 } 69 70 #if ENABLE_TRACING 71 72 static TraceBuffer* s_trace_buffer = NULL; 73 74 void 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 82 void DestroyTrace(void) { 83 delete s_trace_buffer; 84 s_trace_buffer = NULL; 85 s_trace_object = NULL; 86 } 87 88 void 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. 111 void 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 146 void InitTrace(void) { 147 return; 148 } 149 150 void DestroyTrace(void) { 151 s_trace_object = NULL; 152 } 153 154 void Trace(const char* format, ...) { 155 } 156 157 #endif // ENABLE_TRACING 158 159 } // namespace disk_cache 160