Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: content/browser/tracing/tracing_controller_impl_data_sinks.cc

Issue 1088673003: CompressedStringDataSink for trace_controller. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix win compile and tests. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/tracing/tracing_controller_impl.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 #include "content/browser/tracing/tracing_controller_impl.h"
5
6 #include "base/bind.h"
7 #include "base/files/file_util.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "third_party/zlib/zlib.h"
10
11 namespace content {
12
13 namespace {
14
15 class FileTraceDataSink : public TracingController::TraceDataSink {
16 public:
17 explicit FileTraceDataSink(const base::FilePath& trace_file_path,
18 const base::Closure& callback)
19 : file_path_(trace_file_path),
20 completion_callback_(callback),
21 file_(NULL) {}
22
23 void AddTraceChunk(const std::string& chunk) override {
24 std::string tmp = chunk;
25 scoped_refptr<base::RefCountedString> chunk_ptr =
26 base::RefCountedString::TakeString(&tmp);
27 BrowserThread::PostTask(
28 BrowserThread::FILE,
29 FROM_HERE,
30 base::Bind(
31 &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr));
32 }
33 void SetSystemTrace(const std::string& data) override {
34 system_trace_ = data;
35 }
36 void Close() override {
37 BrowserThread::PostTask(
38 BrowserThread::FILE,
39 FROM_HERE,
40 base::Bind(&FileTraceDataSink::CloseOnFileThread, this));
41 }
42
43 private:
44 ~FileTraceDataSink() override { DCHECK(file_ == NULL); }
45
46 void AddTraceChunkOnFileThread(
47 const scoped_refptr<base::RefCountedString> chunk) {
48 if (file_ != NULL)
49 fputc(',', file_);
50 else if (!OpenFileIfNeededOnFileThread())
51 return;
52 ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()),
53 1, file_));
54 }
55
56 bool OpenFileIfNeededOnFileThread() {
57 if (file_ != NULL)
58 return true;
59 file_ = base::OpenFile(file_path_, "w");
60 if (file_ == NULL) {
61 LOG(ERROR) << "Failed to open " << file_path_.value();
62 return false;
63 }
64 const char preamble[] = "{\"traceEvents\": [";
65 ignore_result(fwrite(preamble, strlen(preamble), 1, file_));
66 return true;
67 }
68
69 void CloseOnFileThread() {
70 if (OpenFileIfNeededOnFileThread()) {
71 fputc(']', file_);
72 if (!system_trace_.empty()) {
73 const char systemTraceEvents[] = ",\"systemTraceEvents\": ";
74 ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents),
75 1, file_));
76 ignore_result(fwrite(system_trace_.c_str(),
77 strlen(system_trace_.c_str()), 1, file_));
78 }
79 fputc('}', file_);
80 base::CloseFile(file_);
81 file_ = NULL;
82 }
83 BrowserThread::PostTask(
84 BrowserThread::UI,
85 FROM_HERE,
86 base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this));
87 }
88
89 void FinalizeOnUIThread() { completion_callback_.Run(); }
90
91 base::FilePath file_path_;
92 base::Closure completion_callback_;
93 FILE* file_;
94 std::string system_trace_;
95
96 DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink);
97 };
98
99 class StringTraceDataSink : public TracingController::TraceDataSink {
100 public:
101 typedef base::Callback<void(base::RefCountedString*)> CompletionCallback;
102
103 explicit StringTraceDataSink(CompletionCallback callback)
104 : completion_callback_(callback) {}
105
106 // TracingController::TraceDataSink implementation
107 void AddTraceChunk(const std::string& chunk) override {
108 if (!trace_.empty())
109 trace_ += ",";
110 trace_ += chunk;
111 }
112 void SetSystemTrace(const std::string& data) override {
113 system_trace_ = data;
114 }
115 void Close() override {
116 std::string result = "{\"traceEvents\":[" + trace_ + "]";
117 if (!system_trace_.empty())
118 result += ",\"systemTraceEvents\": " + system_trace_;
119 result += "}";
120
121 scoped_refptr<base::RefCountedString> str =
122 base::RefCountedString::TakeString(&result);
123 completion_callback_.Run(str.get());
124 }
125
126 private:
127 ~StringTraceDataSink() override {}
128
129 std::string trace_;
130 std::string system_trace_;
131 CompletionCallback completion_callback_;
132
133 DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink);
134 };
135
136 class CompressedStringTraceDataSink : public TracingController::TraceDataSink {
137 public:
138 explicit CompressedStringTraceDataSink(
139 scoped_refptr<TracingController::TraceDataEndpoint> endpoint)
140 : endpoint_(endpoint), already_tried_open_(false) {}
141
142 void AddTraceChunk(const std::string& chunk) override {
143 std::string tmp = chunk;
144 scoped_refptr<base::RefCountedString> chunk_ptr =
145 base::RefCountedString::TakeString(&tmp);
146 BrowserThread::PostTask(
147 BrowserThread::FILE, FROM_HERE,
148 base::Bind(&CompressedStringTraceDataSink::AddTraceChunkOnFileThread,
149 this, chunk_ptr));
150 }
151
152 void SetSystemTrace(const std::string& data) override {
153 system_trace_ = data;
154 }
155
156 void Close() override {
157 BrowserThread::PostTask(
158 BrowserThread::FILE, FROM_HERE,
159 base::Bind(&CompressedStringTraceDataSink::CloseOnFileThread, this));
160 }
161
162 private:
163 ~CompressedStringTraceDataSink() override {}
164
165 bool OpenZStreamOnFileThread() {
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
167 if (stream_)
168 return true;
169
170 if (already_tried_open_)
171 return false;
172
173 already_tried_open_ = true;
174 stream_.reset(new z_stream);
175 *stream_ = {0};
176 stream_->zalloc = Z_NULL;
177 stream_->zfree = Z_NULL;
178 stream_->opaque = Z_NULL;
179
180 int result = deflateInit2(stream_.get(), Z_DEFAULT_COMPRESSION, Z_DEFLATED,
181 // 16 is added to produce a gzip header + trailer.
182 MAX_WBITS + 16,
183 8, // memLevel = 8 is default.
184 Z_DEFAULT_STRATEGY);
185 return result == 0;
186 }
187
188 void AddTraceChunkOnFileThread(
189 const scoped_refptr<base::RefCountedString> chunk_ptr) {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
191 std::string trace;
192 if (compressed_trace_data_.empty())
193 trace = "{\"traceEvents\":[";
194 else
195 trace = ",";
196 trace += chunk_ptr->data();
197 AddTraceChunkAndCompressOnFileThread(trace, false);
198 }
199
200 void AddTraceChunkAndCompressOnFileThread(const std::string& chunk,
201 bool finished) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
203 if (!OpenZStreamOnFileThread())
204 return;
205
206 const int kChunkSize = 0x4000;
207
208 char buffer[kChunkSize];
209 int err;
210 stream_->avail_in = chunk.size();
211 stream_->next_in = (unsigned char*)chunk.data();
212 do {
213 stream_->avail_out = kChunkSize;
214 stream_->next_out = (unsigned char*)buffer;
215 err = deflate(stream_.get(), finished ? Z_FINISH : Z_NO_FLUSH);
216 if (err != Z_OK && (err != Z_STREAM_END && finished)) {
217 stream_.reset();
218 return;
219 }
220
221 int bytes = kChunkSize - stream_->avail_out;
222 if (bytes) {
223 std::string compressed_chunk = std::string(buffer, bytes);
224 compressed_trace_data_ += compressed_chunk;
225 endpoint_->ReceiveTraceChunk(compressed_chunk);
226 }
227 } while (stream_->avail_out == 0);
228 }
229
230 void CloseOnFileThread() {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
232 if (!OpenZStreamOnFileThread())
233 return;
234
235 if (compressed_trace_data_.empty())
236 AddTraceChunkAndCompressOnFileThread("{\"traceEvents\":[", false);
237
238 AddTraceChunkAndCompressOnFileThread("]", false);
239 if (!system_trace_.empty()) {
240 AddTraceChunkAndCompressOnFileThread(
241 ",\"systemTraceEvents\": " + system_trace_, false);
242 }
243 AddTraceChunkAndCompressOnFileThread("}", true);
244
245 deflateEnd(stream_.get());
246 stream_.reset();
247
248 endpoint_->ReceiveTraceFinalContents(compressed_trace_data_);
249 }
250
251 scoped_refptr<TracingController::TraceDataEndpoint> endpoint_;
252 scoped_ptr<z_stream> stream_;
253 bool already_tried_open_;
254 std::string compressed_trace_data_;
255 std::string system_trace_;
256
257 DISALLOW_COPY_AND_ASSIGN(CompressedStringTraceDataSink);
258 };
259
260 } // namespace
261
262 scoped_refptr<TracingController::TraceDataSink>
263 TracingController::CreateStringSink(
264 const base::Callback<void(base::RefCountedString*)>& callback) {
265 return new StringTraceDataSink(callback);
266 }
267
268 scoped_refptr<TracingController::TraceDataSink>
269 TracingController::CreateCompressedStringSink(
270 scoped_refptr<TracingController::TraceDataEndpoint> endpoint) {
271 return new CompressedStringTraceDataSink(endpoint);
272 }
273
274 scoped_refptr<TracingController::TraceDataSink>
275 TracingController::CreateFileSink(const base::FilePath& file_path,
276 const base::Closure& callback) {
277 return new FileTraceDataSink(file_path, callback);
278 }
279
280 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/tracing_controller_impl.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698