Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / tracing / trace_subscriber_stdio.cc
blobb5f6e828c60b581f83a9ab4bb35209717e259d8b
1 // Copyright (c) 2012 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.
5 #include "content/browser/tracing/trace_subscriber_stdio.h"
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/public/browser/browser_thread.h"
14 namespace content {
16 // All method calls on this class are done on a SequencedWorkerPool thread.
17 class TraceSubscriberStdioImpl
18 : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> {
19 public:
20 explicit TraceSubscriberStdioImpl(const base::FilePath& path)
21 : path_(path),
22 file_(0) {}
24 void OnStart() {
25 DCHECK(!file_);
26 trace_buffer_.SetOutputCallback(
27 base::Bind(&TraceSubscriberStdioImpl::Write, this));
28 file_ = file_util::OpenFile(path_, "w+");
29 if (IsValid()) {
30 LOG(INFO) << "Logging performance trace to file: " << path_.value();
31 trace_buffer_.Start();
32 } else {
33 LOG(ERROR) << "Failed to open performance trace file: " << path_.value();
37 void OnData(const scoped_refptr<base::RefCountedString>& data_ptr) {
38 trace_buffer_.AddFragment(data_ptr->data());
41 void OnEnd() {
42 trace_buffer_.Finish();
43 CloseFile();
46 private:
47 friend class base::RefCountedThreadSafe<TraceSubscriberStdioImpl>;
49 ~TraceSubscriberStdioImpl() {
50 CloseFile();
53 bool IsValid() const {
54 return file_ && (0 == ferror(file_));
57 void CloseFile() {
58 if (file_) {
59 fclose(file_);
60 file_ = 0;
62 // This is important, as it breaks a reference cycle.
63 trace_buffer_.SetOutputCallback(
64 base::debug::TraceResultBuffer::OutputCallback());
67 void Write(const std::string& output_str) {
68 if (IsValid()) {
69 size_t written = fwrite(output_str.data(), 1, output_str.size(), file_);
70 if (written != output_str.size()) {
71 LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file";
72 CloseFile();
77 base::FilePath path_;
78 FILE* file_;
79 base::debug::TraceResultBuffer trace_buffer_;
82 TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path)
83 : impl_(new TraceSubscriberStdioImpl(path)) {
84 BrowserThread::PostBlockingPoolSequencedTask(
85 __FILE__, FROM_HERE,
86 base::Bind(&TraceSubscriberStdioImpl::OnStart, impl_));
89 TraceSubscriberStdio::~TraceSubscriberStdio() {
92 void TraceSubscriberStdio::OnEndTracingComplete() {
93 BrowserThread::PostBlockingPoolSequencedTask(
94 __FILE__, FROM_HERE,
95 base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_));
98 void TraceSubscriberStdio::OnTraceDataCollected(
99 const scoped_refptr<base::RefCountedString>& data_ptr) {
100 BrowserThread::PostBlockingPoolSequencedTask(
101 __FILE__, FROM_HERE,
102 base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr));
105 } // namespace content