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/blockfile/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/blockfile/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 |