trace.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Copyright (c) 2011 The Chromium Authors. All rights reserved. 22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Use of this source code is governed by a BSD-style license that can be 32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// found in the LICENSE file. 42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "net/disk_cache/blockfile/trace.h" 62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <stdio.h> 82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(OS_WIN) 92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <windows.h> 102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "base/lazy_instance.h" 132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "base/logging.h" 142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "base/synchronization/lock.h" 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "net/disk_cache/blockfile/stress_support.h" 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Change this value to 1 to enable tracing on a release build. By default, 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// tracing is enabled only on debug builds. 192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define ENABLE_TRACING 0 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifndef NDEBUG 222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#undef ENABLE_TRACING 235d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#define ENABLE_TRACING 1 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace { 272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst int kEntrySize = 12 * sizeof(size_t); 292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(NET_BUILD_STRESS_CACHE) 302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst int kNumberOfEntries = 500000; 312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst int kNumberOfEntries = 5000; // 240 KB on 32bit, 480 KB on 64bit 332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool s_trace_enabled = false; 362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbase::LazyInstance<base::Lock>::Leaky s_lock = LAZY_INSTANCE_INITIALIZER; 372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct TraceBuffer { 392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int num_traces; 405d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines int current; 412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char buffer[kNumberOfEntries][kEntrySize]; 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if ENABLE_TRACING 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DebugOutput(const char* msg) { 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(OS_WIN) 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines OutputDebugStringA(msg); 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines NOTIMPLEMENTED(); 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // ENABLE_TRACING 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // namespace 552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 565d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesnamespace disk_cache { 575d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 585d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// s_trace_buffer and s_trace_object are not singletons because I want the 595d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// buffer to be destroyed and re-created when the last user goes away, and it 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// must be straightforward to access the buffer from the debugger. 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic TraceObject* s_trace_object = NULL; 622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Static. 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTraceObject* TraceObject::GetTraceObject() { 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines base::AutoLock lock(s_lock.Get()); 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (s_trace_object) 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return s_trace_object; 695d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 705d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines s_trace_object = new TraceObject(); 715d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines return s_trace_object; 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTraceObject::TraceObject() { 752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InitTrace(); 762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTraceObject::~TraceObject() { 792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DestroyTrace(); 802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid TraceObject::EnableTracing(bool enable) { 832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines base::AutoLock lock(s_lock.Get()); 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_enabled = enable; 855d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines} 865d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 875d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if ENABLE_TRACING 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic TraceBuffer* s_trace_buffer = NULL; 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InitTrace(void) { 925d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines s_trace_enabled = true; 935d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines if (s_trace_buffer) 945d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines return; 955d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_buffer = new TraceBuffer; 972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines memset(s_trace_buffer, 0, sizeof(*s_trace_buffer)); 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DestroyTrace(void) { 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines base::AutoLock lock(s_lock.Get()); 1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines delete s_trace_buffer; 1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_buffer = NULL; 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_object = NULL; 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid Trace(const char* format, ...) { 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!s_trace_buffer || !s_trace_enabled) 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines va_list ap; 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines va_start(ap, format); 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char line[kEntrySize + 2]; 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(OS_WIN) 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines vsprintf_s(line, format, ap); 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines vsnprintf(line, kEntrySize, format, ap); 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(DISK_CACHE_TRACE_TO_LOG) 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines line[kEntrySize] = '\0'; 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines LOG(INFO) << line; 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines va_end(ap); 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines base::AutoLock lock(s_lock.Get()); 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!s_trace_buffer || !s_trace_enabled) 1325d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines return; 1335d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 1345d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines memcpy(s_trace_buffer->buffer[s_trace_buffer->current], line, kEntrySize); 1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_buffer->num_traces++; 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_buffer->current++; 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (s_trace_buffer->current == kNumberOfEntries) 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines s_trace_buffer->current = 0; 1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Writes the last num_traces to the debugger output. 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DumpTrace(int num_traces) { 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DCHECK(s_trace_buffer); 1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DebugOutput("Last traces:\n"); 1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (num_traces > kNumberOfEntries || num_traces < 0) 1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines num_traces = kNumberOfEntries; 1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (s_trace_buffer->num_traces) { 1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char line[kEntrySize + 2]; 1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int current = s_trace_buffer->current - num_traces; 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (current < 0) 1565d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines current += kNumberOfEntries; 1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 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 179void InitTrace(void) { 180 return; 181} 182 183void DestroyTrace(void) { 184 s_trace_object = NULL; 185} 186 187void Trace(const char* format, ...) { 188} 189 190#endif // ENABLE_TRACING 191 192} // namespace disk_cache 193