| Index: src/platform/update_engine/filesystem_copier_action.h
|
| diff --git a/src/platform/update_engine/filesystem_copier_action.h b/src/platform/update_engine/filesystem_copier_action.h
|
| index 3a330efd5b3ed6b065c3da5bc01a94d538bd0caa..9e7f0606796edad379f2c0faf5a6540361a1dfc9 100644
|
| --- a/src/platform/update_engine/filesystem_copier_action.h
|
| +++ b/src/platform/update_engine/filesystem_copier_action.h
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2010 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.
|
|
|
| @@ -8,30 +8,14 @@
|
| #include <sys/stat.h>
|
| #include <sys/types.h>
|
| #include <string>
|
| +#include <vector>
|
| +#include <gio/gio.h>
|
| #include <glib.h>
|
| #include "update_engine/action.h"
|
| #include "update_engine/install_plan.h"
|
|
|
| // This action will only do real work if it's a delta update. It will
|
| -// format the install partition as ext3/4, copy the root filesystem into it,
|
| -// and then terminate.
|
| -
|
| -// Implementation notes: This action uses a helper thread, which seems to
|
| -// violate the design decision to only have a single thread and use
|
| -// asynchronous i/o. The issue is that (to the best of my knowledge),
|
| -// there are no linux APIs to crawl a filesystem's metadata asynchronously.
|
| -// The suggested way seems to be to open the raw device and parse the ext
|
| -// filesystem. That's not a good approach for a number of reasons:
|
| -// - ties us to ext filesystem
|
| -// - although this wouldn't happen at the time of writing, it may not handle
|
| -// changes to the source fs during the copy as gracefully.
|
| -// - requires us to have read-access to the source filesystem device, which
|
| -// may be a security issue.
|
| -//
|
| -// Having said this, using a helper thread is not ideal, but it's acceptable:
|
| -// we still honor the Action API. That is, all interaction between the action
|
| -// and other objects in the system (e.g. the ActionProcessor) happens on the
|
| -// main thread. The helper thread is fully encapsulated by the action.
|
| +// copy the root partition to install partition, and then terminate.
|
|
|
| namespace chromeos_update_engine {
|
|
|
| @@ -49,10 +33,11 @@ class ActionTraits<FilesystemCopierAction> {
|
| class FilesystemCopierAction : public Action<FilesystemCopierAction> {
|
| public:
|
| FilesystemCopierAction()
|
| - : thread_should_exit_(0),
|
| - is_mounted_(false),
|
| - copy_source_("/"),
|
| - skipped_copy_(false) {}
|
| + : src_stream_(NULL),
|
| + dst_stream_(NULL),
|
| + canceller_(NULL),
|
| + read_in_flight_(false),
|
| + buffer_valid_size_(0) {}
|
| typedef ActionTraits<FilesystemCopierAction>::InputObjectType
|
| InputObjectType;
|
| typedef ActionTraits<FilesystemCopierAction>::OutputObjectType
|
| @@ -64,81 +49,51 @@ class FilesystemCopierAction : public Action<FilesystemCopierAction> {
|
| void set_copy_source(const std::string& path) {
|
| copy_source_ = path;
|
| }
|
| - // Returns true if we detected that a copy was unneeded and thus skipped it.
|
| - bool skipped_copy() { return skipped_copy_; }
|
|
|
| // Debugging/logging
|
| static std::string StaticType() { return "FilesystemCopierAction"; }
|
| std::string Type() const { return StaticType(); }
|
|
|
| private:
|
| - // These synchronously mount or unmount the given mountpoint
|
| - bool Mount(const std::string& device, const std::string& mountpoint);
|
| - bool Unmount(const std::string& mountpoint);
|
| -
|
| - // Performs a recursive file/directory copy from copy_source_ to dest_path_.
|
| - // Doesn't return until the copy has completed. Returns true on success
|
| - // or false on error.
|
| - bool CopySynchronously();
|
| -
|
| - // There are helper functions for CopySynchronously. They handle creating
|
| - // various types of files. They return true on success.
|
| - bool CreateDirSynchronously(const std::string& new_path,
|
| - const struct stat& stbuf);
|
| - bool CopyFileSynchronously(const std::string& old_path,
|
| - const std::string& new_path,
|
| - const struct stat& stbuf);
|
| - bool CreateHardLinkSynchronously(const std::string& old_path,
|
| - const std::string& new_path);
|
| - // Note: Here, old_path is an existing symlink that will be copied to
|
| - // new_path. Thus, old_path is *not* the same as the old_path from
|
| - // the symlink() syscall.
|
| - bool CopySymlinkSynchronously(const std::string& old_path,
|
| - const std::string& new_path,
|
| - const struct stat& stbuf);
|
| - bool CreateNodeSynchronously(const std::string& new_path,
|
| - const struct stat& stbuf);
|
| -
|
| - // Returns NULL on success
|
| - void* HelperThreadMain();
|
| - static void* HelperThreadMainStatic(void* data) {
|
| - FilesystemCopierAction* self =
|
| - reinterpret_cast<FilesystemCopierAction*>(data);
|
| - return self->HelperThreadMain();
|
| + // Callback from glib when the copy operation is done.
|
| + void AsyncReadyCallback(GObject *source_object, GAsyncResult *res);
|
| + static void StaticAsyncReadyCallback(GObject *source_object,
|
| + GAsyncResult *res,
|
| + gpointer user_data) {
|
| + reinterpret_cast<FilesystemCopierAction*>(user_data)->AsyncReadyCallback(
|
| + source_object, res);
|
| }
|
| -
|
| - // Joins the thread and tells the processor that we're done
|
| - void CollectThread();
|
| - // GMainLoop callback function:
|
| - static gboolean CollectThreadStatic(gpointer data) {
|
| - FilesystemCopierAction* self =
|
| - reinterpret_cast<FilesystemCopierAction*>(data);
|
| - self->CollectThread();
|
| - return FALSE;
|
| - }
|
| -
|
| - pthread_t helper_thread_;
|
| -
|
| - volatile gint thread_should_exit_;
|
| -
|
| - static const char* kCompleteFilesystemMarker;
|
| -
|
| - // Whether or not the destination device is currently mounted.
|
| - bool is_mounted_;
|
| -
|
| - // Where the destination device is mounted.
|
| - std::string dest_path_;
|
| -
|
| - // The path to copy from. Usually left as the default "/", but tests can
|
| - // change it.
|
| +
|
| + // Cleans up all the variables we use for async operations and tells
|
| + // the ActionProcessor we're done w/ success as passed in.
|
| + // was_cancelled should be true if TerminateProcessing() was called.
|
| + void Cleanup(bool success, bool was_cancelled);
|
| +
|
| + // The path to copy from. If empty (the default), the source is from the
|
| + // passed in InstallPlan.
|
| std::string copy_source_;
|
|
|
| + // If non-NULL, these are GUnixInputStream objects for the opened
|
| + // source/destination partitions.
|
| + GInputStream* src_stream_;
|
| + GOutputStream* dst_stream_;
|
| +
|
| + // If non-NULL, the cancellable object for the in-flight async call.
|
| + GCancellable* canceller_;
|
| +
|
| + // True if we're waiting on a read to complete; false if we're
|
| + // waiting on a write.
|
| + bool read_in_flight_;
|
| +
|
| + // The buffer for storing data we read/write.
|
| + std::vector<char> buffer_;
|
| +
|
| + // Number of valid elements in buffer_.
|
| + std::vector<char>::size_type buffer_valid_size_;
|
| +
|
| // The install plan we're passed in via the input pipe.
|
| InstallPlan install_plan_;
|
| -
|
| - // Set to true if we detected the copy was unneeded and thus we skipped it.
|
| - bool skipped_copy_;
|
| -
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(FilesystemCopierAction);
|
| };
|
|
|
|
|