diff options
author | pstew@chromium.org <pstew@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 08:11:48 +0000 |
---|---|---|
committer | pstew@chromium.org <pstew@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 08:11:48 +0000 |
commit | 12d2bdf9693cd8229bfa594318c417a170e4b83e (patch) | |
tree | 3117c55a86018410221244693beeecaae3d90aa7 /chromeos | |
parent | f087e05eae93407bc2081b98f9e9ed6c1d605559 (diff) | |
download | chromium_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.gyp | 2 | ||||
-rw-r--r-- | chromeos/dbus/debug_daemon_client.cc | 115 | ||||
-rw-r--r-- | chromeos/dbus/pipe_reader.cc | 90 | ||||
-rw-r--r-- | chromeos/dbus/pipe_reader.h | 85 |
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_ |