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