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