Chromium Code Reviews| Index: content/browser/tracing/trace_subscriber_stdio.cc |
| diff --git a/content/browser/tracing/trace_subscriber_stdio.cc b/content/browser/tracing/trace_subscriber_stdio.cc |
| index b5f6e828c60b581f83a9ab4bb35209717e259d8b..2849c8fa32c733be720a5c58ff30b58ad5d244c9 100644 |
| --- a/content/browser/tracing/trace_subscriber_stdio.cc |
| +++ b/content/browser/tracing/trace_subscriber_stdio.cc |
| @@ -14,39 +14,78 @@ |
| namespace content { |
| // All method calls on this class are done on a SequencedWorkerPool thread. |
| -class TraceSubscriberStdioImpl |
| - : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> { |
| +class TraceSubscriberStdio::TraceSubscriberStdioWorker |
| + : public base::RefCountedThreadSafe<TraceSubscriberStdioWorker> { |
| public: |
| - explicit TraceSubscriberStdioImpl(const base::FilePath& path) |
| + explicit TraceSubscriberStdioWorker(const base::FilePath& path, |
| + FileType file_type, |
| + bool has_system_trace) |
| : path_(path), |
| - file_(0) {} |
| - |
| - void OnStart() { |
| + file_type_(file_type), |
| + has_system_trace_(has_system_trace), |
| + file_(0), |
| + needs_comma_(false), |
| + wrote_trace_(false), |
| + has_pending_system_trace_(false), |
| + wrote_system_trace_(false) {} |
| + |
| + void OnTraceStart() { |
| DCHECK(!file_); |
| - trace_buffer_.SetOutputCallback( |
| - base::Bind(&TraceSubscriberStdioImpl::Write, this)); |
| file_ = file_util::OpenFile(path_, "w+"); |
| - if (IsValid()) { |
| - LOG(INFO) << "Logging performance trace to file: " << path_.value(); |
| - trace_buffer_.Start(); |
| - } else { |
| + if (!IsValid()) { |
| LOG(ERROR) << "Failed to open performance trace file: " << path_.value(); |
| + return; |
| } |
| + |
| + LOG(INFO) << "Logging performance trace to file: " << path_.value(); |
| + if (file_type_ == FILE_TYPE_PROPERTY_LIST) |
| + WriteString("{\"traceEvents\":"); |
| + WriteString("["); |
| } |
| - void OnData(const scoped_refptr<base::RefCountedString>& data_ptr) { |
| - trace_buffer_.AddFragment(data_ptr->data()); |
| + void OnTraceData(const scoped_refptr<base::RefCountedString>& data_ptr) { |
| + if (!IsValid()) |
| + return; |
| + if (needs_comma_) |
| + WriteString(","); |
| + WriteString(data_ptr->data()); |
| + needs_comma_ = true; |
| } |
| - void OnEnd() { |
| - trace_buffer_.Finish(); |
| - CloseFile(); |
| + void OnSystemTraceData( |
| + const scoped_refptr<base::RefCountedString>& data_ptr) { |
|
dsinclair
2013/08/19 20:12:26
nit: indenting.
DaveMoore
2013/08/19 22:07:46
Done.
|
| + if (wrote_trace_) { |
| + WriteSystemTrace(data_ptr); |
| + End(); |
| + } else { |
| + pending_system_trace_ = data_ptr; |
| + has_pending_system_trace_ = true; |
| + } |
| + } |
| + |
| + void OnTraceEnd() { |
| + if (!IsValid()) |
| + return; |
| + WriteString("]"); |
| + |
| + wrote_trace_ = true; |
| + |
| + if (!has_system_trace_ || wrote_system_trace_) { |
| + End(); |
| + return; |
| + } |
| + |
| + WriteString(","); |
| + if (has_pending_system_trace_) { |
| + WriteSystemTrace(pending_system_trace_); |
| + End(); |
| + } |
| } |
| private: |
| - friend class base::RefCountedThreadSafe<TraceSubscriberStdioImpl>; |
| + friend class base::RefCountedThreadSafe<TraceSubscriberStdioWorker>; |
| - ~TraceSubscriberStdioImpl() { |
| + ~TraceSubscriberStdioWorker() { |
| CloseFile(); |
| } |
| @@ -58,32 +97,69 @@ class TraceSubscriberStdioImpl |
| if (file_) { |
| fclose(file_); |
| file_ = 0; |
| + |
| + } |
| + } |
| + |
| + void End() { |
| + if (file_type_ == FILE_TYPE_PROPERTY_LIST) |
| + WriteString("}"); |
| + CloseFile(); |
| + } |
| + |
| + void WriteSystemTrace(const scoped_refptr<base::RefCountedString>& data_ptr) { |
| + // Newlines need to be replaced with the string "\n" to be parsed correctly. |
| + std::string data = data_ptr->data(); |
| + const char* chars = data.data(); |
|
dsinclair
2013/08/19 20:12:26
Is it guaranteed that data() won't have any "'s in
DaveMoore
2013/08/19 22:07:46
Done.
|
| + WriteString("\"systemTraceEvents\":\""); |
| + int old_index = 0; |
| + for (size_t new_index = data.find('\n'); |
| + std::string::npos != new_index; |
| + old_index = new_index + 1, new_index = data.find('\n', old_index)) { |
| + WriteChars(chars + old_index, new_index - old_index); |
| + WriteChars("\\n", 2); |
| } |
| - // This is important, as it breaks a reference cycle. |
| - trace_buffer_.SetOutputCallback( |
| - base::debug::TraceResultBuffer::OutputCallback()); |
| + WriteChars(chars + old_index, data.size() - old_index); |
| + WriteString("\""); |
| + wrote_system_trace_ = true; |
| } |
| - void Write(const std::string& output_str) { |
| + void WriteChars(const char* output_chars, size_t size) { |
| if (IsValid()) { |
|
dsinclair
2013/08/19 20:12:26
We seem to be doing if (!IsValid()) early returns
|
| - size_t written = fwrite(output_str.data(), 1, output_str.size(), file_); |
| - if (written != output_str.size()) { |
| + size_t written = fwrite(output_chars, 1, size, file_); |
| + if (written != size) { |
| LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file"; |
| CloseFile(); |
| } |
| } |
| } |
| + void WriteString(const std::string& output_str) { |
| + WriteChars(output_str.data(), output_str.size()); |
| + } |
| + |
| base::FilePath path_; |
| + FileType file_type_; |
| + bool has_system_trace_; |
| FILE* file_; |
| - base::debug::TraceResultBuffer trace_buffer_; |
| + bool needs_comma_; |
| + bool wrote_trace_; |
| + bool has_pending_system_trace_; |
| + bool wrote_system_trace_; |
| + scoped_refptr<base::RefCountedString> pending_system_trace_; |
| }; |
| -TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path) |
| - : impl_(new TraceSubscriberStdioImpl(path)) { |
| +TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path, |
| + FileType file_type, |
| + bool has_system_trace) |
| + : worker_(new TraceSubscriberStdioWorker(path, |
| + file_type, |
| + has_system_trace)) { |
| + if (has_system_trace) |
| + CHECK_EQ(FILE_TYPE_PROPERTY_LIST, file_type); |
| BrowserThread::PostBlockingPoolSequencedTask( |
| __FILE__, FROM_HERE, |
| - base::Bind(&TraceSubscriberStdioImpl::OnStart, impl_)); |
| + base::Bind(&TraceSubscriberStdioWorker::OnTraceStart, worker_)); |
| } |
| TraceSubscriberStdio::~TraceSubscriberStdio() { |
| @@ -92,14 +168,23 @@ TraceSubscriberStdio::~TraceSubscriberStdio() { |
| void TraceSubscriberStdio::OnEndTracingComplete() { |
| BrowserThread::PostBlockingPoolSequencedTask( |
| __FILE__, FROM_HERE, |
| - base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_)); |
| + base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd, worker_)); |
| } |
| void TraceSubscriberStdio::OnTraceDataCollected( |
| const scoped_refptr<base::RefCountedString>& data_ptr) { |
| BrowserThread::PostBlockingPoolSequencedTask( |
| __FILE__, FROM_HERE, |
| - base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr)); |
| + base::Bind(&TraceSubscriberStdioWorker::OnTraceData, worker_, data_ptr)); |
| +} |
| + |
| +void TraceSubscriberStdio::OnEndSystemTracing( |
| + const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| + BrowserThread::PostBlockingPoolSequencedTask( |
| + __FILE__, FROM_HERE, |
| + base::Bind(&TraceSubscriberStdioWorker::OnSystemTraceData, |
| + worker_, |
| + events_str_ptr)); |
| } |
| } // namespace content |