summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorpstew@chromium.org <pstew@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-03 08:11:48 +0000
committerpstew@chromium.org <pstew@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-03 08:11:48 +0000
commit12d2bdf9693cd8229bfa594318c417a170e4b83e (patch)
tree3117c55a86018410221244693beeecaae3d90aa7 /chromeos
parentf087e05eae93407bc2081b98f9e9ed6c1d605559 (diff)
downloadchromium_src-12d2bdf9693cd8229bfa594318c417a170e4b83e.zip
chromium_src-12d2bdf9693cd8229bfa594318c417a170e4b83e.tar.gz
chromium_src-12d2bdf9693cd8229bfa594318c417a170e4b83e.tar.bz2
Split PipeReader off into a separate class
While here, clean up the API to PipeReader a little bit and split up the class so there can be multiple ways to accept the data from the pipe. BUG=358344 Review URL: https://codereview.chromium.org/219333010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261319 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/chromeos.gyp2
-rw-r--r--chromeos/dbus/debug_daemon_client.cc115
-rw-r--r--chromeos/dbus/pipe_reader.cc90
-rw-r--r--chromeos/dbus/pipe_reader.h85
4 files changed, 184 insertions, 108 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 89c64fe..e660535 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -222,6 +222,8 @@
'dbus/modem_messaging_client.h',
'dbus/permission_broker_client.cc',
'dbus/permission_broker_client.h',
+ 'dbus/pipe_reader.cc',
+ 'dbus/pipe_reader.h',
'dbus/power_manager_client.cc',
'dbus/power_manager_client.h',
'dbus/power_policy_controller.cc',
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 6c377ae..73d86ae 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -19,13 +19,11 @@
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_util.h"
#include "base/threading/worker_pool.h"
+#include "chromeos/dbus/pipe_reader.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
@@ -35,107 +33,6 @@ void EmptyStopSystemTracingCallbackBody(
const scoped_refptr<base::RefCountedString>& unused_result) {
}
-// Simple class to encapsulate collecting data from a pipe into a
-// string. To use, instantiate the class, start i/o, and then delete
-// the instance on callback. The data should be retrieved before
-// delete and extracted or copied.
-//
-// TODO(sleffler) move data collection to a sub-class so this
-// can be reused to process data as it is received
-class PipeReader {
- public:
- typedef base::Callback<void(void)>IOCompleteCallback;
-
- explicit PipeReader(IOCompleteCallback callback)
- : io_buffer_(new net::IOBufferWithSize(4096)),
- callback_(callback),
- weak_ptr_factory_(this) {
- pipe_fd_[0] = pipe_fd_[1] = -1;
- }
-
- virtual ~PipeReader() {
- // Don't close pipe_fd_[0] as it's closed by data_stream_.
- if (pipe_fd_[1] != -1)
- if (IGNORE_EINTR(close(pipe_fd_[1])) < 0)
- PLOG(ERROR) << "close[1]";
- }
-
- // Returns descriptor for the writeable side of the pipe.
- int GetWriteFD() { return pipe_fd_[1]; }
-
- // Closes writeable descriptor; normally used in parent process after fork.
- void CloseWriteFD() {
- if (pipe_fd_[1] != -1) {
- if (IGNORE_EINTR(close(pipe_fd_[1])) < 0)
- PLOG(ERROR) << "close";
- pipe_fd_[1] = -1;
- }
- }
-
- // Returns collected data.
- std::string* data() { return &data_; }
-
- // Starts data collection. Returns true if stream was setup correctly.
- // On success data will automatically be accumulated into a string that
- // can be retrieved with PipeReader::data(). To shutdown collection delete
- // the instance and/or use PipeReader::OnDataReady(-1).
- bool StartIO() {
- // Use a pipe to collect data
- const int status = HANDLE_EINTR(pipe(pipe_fd_));
- if (status < 0) {
- PLOG(ERROR) << "pipe";
- return false;
- }
- base::PlatformFile data_file_ = pipe_fd_[0]; // read side
- data_stream_.reset(new net::FileStream(data_file_,
- base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC,
- NULL));
-
- // Post an initial async read to setup data collection
- int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
- base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
- if (rv != net::ERR_IO_PENDING) {
- LOG(ERROR) << "Unable to post initial read";
- return false;
- }
- return true;
- }
-
- // Called when pipe data are available. Can also be used to shutdown
- // data collection by passing -1 for |byte_count|.
- void OnDataReady(int byte_count) {
- DVLOG(1) << "OnDataReady byte_count " << byte_count;
- if (byte_count <= 0) {
- callback_.Run(); // signal creator to take data and delete us
- return;
- }
- data_.append(io_buffer_->data(), byte_count);
-
- // Post another read
- int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
- base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
- if (rv != net::ERR_IO_PENDING) {
- LOG(ERROR) << "Unable to post another read";
- // TODO(sleffler) do something more intelligent?
- }
- }
-
- private:
- friend class base::RefCounted<PipeReader>;
-
- int pipe_fd_[2];
- scoped_ptr<net::FileStream> data_stream_;
- scoped_refptr<net::IOBufferWithSize> io_buffer_;
- std::string data_;
- IOCompleteCallback callback_;
-
- // Note: This should remain the last member so it'll be destroyed and
- // invalidate its weak pointers before any other members are destroyed.
- base::WeakPtrFactory<PipeReader> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PipeReader);
-};
-
} // namespace
namespace chromeos {
@@ -324,7 +221,7 @@ class DebugDaemonClientImpl : public DebugDaemonClient {
return false;
}
- pipe_reader_.reset(new PipeReader(
+ pipe_reader_.reset(new PipeReaderForString(
base::Bind(&DebugDaemonClientImpl::OnIOComplete,
weak_ptr_factory_.GetWeakPtr())));
int write_fd = -1;
@@ -334,7 +231,7 @@ class DebugDaemonClientImpl : public DebugDaemonClient {
write_fd = HANDLE_EINTR(open("/dev/null", O_WRONLY));
// TODO(sleffler) if this fails AppendFileDescriptor will abort
} else {
- write_fd = pipe_reader_->GetWriteFD();
+ write_fd = pipe_reader_->write_fd();
}
dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor(write_fd);
@@ -616,12 +513,14 @@ class DebugDaemonClientImpl : public DebugDaemonClient {
// Called when pipe i/o completes; pass data on and delete the instance.
void OnIOComplete() {
- callback_.Run(base::RefCountedString::TakeString(pipe_reader_->data()));
+ std::string pipe_data;
+ pipe_reader_->GetData(&pipe_data);
+ callback_.Run(base::RefCountedString::TakeString(&pipe_data));
pipe_reader_.reset();
}
dbus::ObjectProxy* debugdaemon_proxy_;
- scoped_ptr<PipeReader> pipe_reader_;
+ scoped_ptr<PipeReaderForString> pipe_reader_;
StopSystemTracingCallback callback_;
base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
diff --git a/chromeos/dbus/pipe_reader.cc b/chromeos/dbus/pipe_reader.cc
new file mode 100644
index 0000000..8d857ea
--- /dev/null
+++ b/chromeos/dbus/pipe_reader.cc
@@ -0,0 +1,90 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/pipe_reader.h"
+
+#include "base/bind.h"
+#include "base/platform_file.h"
+#include "base/posix/eintr_wrapper.h"
+#include "net/base/net_errors.h"
+
+namespace chromeos {
+
+PipeReader::PipeReader(PipeReader::IOCompleteCallback callback)
+ : write_fd_(-1),
+ io_buffer_(new net::IOBufferWithSize(4096)),
+ callback_(callback),
+ weak_ptr_factory_(this) {}
+
+PipeReader::~PipeReader() {
+ CloseWriteFD();
+}
+
+void PipeReader::CloseWriteFD() {
+ if (write_fd_ == -1)
+ return;
+ if (IGNORE_EINTR(close(write_fd_)) < 0)
+ PLOG(ERROR) << "close";
+ write_fd_ = -1;
+}
+
+bool PipeReader::StartIO() {
+ // Use a pipe to collect data
+ int pipe_fds[2];
+ const int status = HANDLE_EINTR(pipe(pipe_fds));
+ if (status < 0) {
+ PLOG(ERROR) << "pipe";
+ return false;
+ }
+ write_fd_ = pipe_fds[1];
+ base::PlatformFile data_file_ = pipe_fds[0];
+ // Pass ownership of pipe_fds[0] to data_stream_, which will will close it.
+ data_stream_.reset(new net::FileStream(
+ data_file_,
+ base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC,
+ NULL));
+
+ // Post an initial async read to setup data collection
+ int rv = data_stream_->Read(
+ io_buffer_.get(), io_buffer_->size(),
+ base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
+ if (rv != net::ERR_IO_PENDING) {
+ LOG(ERROR) << "Unable to post initial read";
+ return false;
+ }
+ return true;
+}
+
+void PipeReader::OnDataReady(int byte_count) {
+ DVLOG(1) << "OnDataReady byte_count " << byte_count;
+ if (byte_count <= 0) {
+ callback_.Run(); // signal creator to take data and delete us
+ return;
+ }
+
+ AcceptData(io_buffer_->data(), byte_count);
+
+ // Post another read
+ int rv = data_stream_->Read(
+ io_buffer_.get(), io_buffer_->size(),
+ base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
+ if (rv != net::ERR_IO_PENDING) {
+ LOG(ERROR) << "Unable to post another read";
+ // TODO(sleffler) do something more intelligent?
+ }
+}
+
+PipeReaderForString::PipeReaderForString(
+ PipeReader::IOCompleteCallback callback) : PipeReader(callback) {}
+
+void PipeReaderForString::AcceptData(const char *data, int byte_count) {
+ data_.append(data, byte_count);
+}
+
+
+void PipeReaderForString::GetData(std::string* data) {
+ data_.swap(*data);
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/pipe_reader.h b/chromeos/dbus/pipe_reader.h
new file mode 100644
index 0000000..bae1723
--- /dev/null
+++ b/chromeos/dbus/pipe_reader.h
@@ -0,0 +1,85 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_PIPE_READER_H_
+#define CHROMEOS_DBUS_PIPE_READER_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted_memory.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+
+namespace chromeos {
+
+// Simple class to encapsulate collecting data from a pipe into a
+// string. To use:
+// - Instantiate the appropriate subclass of PipeReader
+// - Call StartIO() which will create the appropriate FDs.
+// - Call GetWriteFD() which will return a file descriptor that can
+// be sent to a separate process which will write data there.
+// - After handing off the FD, call CloseWriteFD() so there is
+// only one copy of the FD open.
+// - As data is received, the PipeReader will collect this data
+// as appropriate to the subclass.
+// - When the there is no more data to read, the PipeReader calls
+// |callback|.
+class PipeReader {
+ public:
+ typedef base::Callback<void(void)>IOCompleteCallback;
+
+ explicit PipeReader(PipeReader::IOCompleteCallback callback);
+ virtual ~PipeReader();
+
+ // Closes writeable descriptor; normally used in parent process after fork.
+ void CloseWriteFD();
+
+ // Starts data collection. Returns true if stream was setup correctly.
+ // On success data will automatically be accumulated into a string that
+ // can be retrieved with PipeReader::data(). To shutdown collection delete
+ // the instance and/or use PipeReader::OnDataReady(-1).
+ bool StartIO();
+
+ // Called when pipe data are available. Can also be used to shutdown
+ // data collection by passing -1 for |byte_count|.
+ void OnDataReady(int byte_count);
+
+ // Virtual function that subclasses will override in order to deal
+ // with incoming data.
+ virtual void AcceptData(const char *data, int length) = 0;
+
+ // Getter for |write_fd_|.
+ int write_fd() const { return write_fd_; }
+
+ private:
+ int write_fd_;
+ scoped_ptr<net::FileStream> data_stream_;
+ scoped_refptr<net::IOBufferWithSize> io_buffer_;
+ IOCompleteCallback callback_;
+
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<PipeReader> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipeReader);
+};
+
+// PipeReader subclass which accepts incoming data to a string.
+class PipeReaderForString : public PipeReader {
+ public:
+ explicit PipeReaderForString(PipeReader::IOCompleteCallback callback);
+
+ virtual void AcceptData(const char *data, int length) OVERRIDE;
+
+ // Destructively returns collected data, by swapping |data_| with |data|.
+ void GetData(std::string* data);
+
+ private:
+ std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipeReaderForString);
+};
+
+}
+
+#endif // CHROMEOS_DBUS_PIPE_READER_H_