AU: Speed up full update payload generation by running multiple threads.

Full end-to-end payload generation drops from 140 to 40 seconds on my machine.

BUG=8747
TEST=unit tests, updated through dev server

Change-Id: Ib3934b38a55e043abfa49abb25b2931e529ff768

Review URL: http://codereview.chromium.org/4610001
diff --git a/delta_diff_generator.cc b/delta_diff_generator.cc
index 64c1766..50db931 100644
--- a/delta_diff_generator.cc
+++ b/delta_diff_generator.cc
@@ -27,6 +27,7 @@
 #include "update_engine/extent_ranges.h"
 #include "update_engine/file_writer.h"
 #include "update_engine/filesystem_iterator.h"
+#include "update_engine/full_update_generator.h"
 #include "update_engine/graph_types.h"
 #include "update_engine/graph_utils.h"
 #include "update_engine/omaha_hash_calculator.h"
@@ -1308,85 +1309,6 @@
   return true;
 }
 
-bool DeltaDiffGenerator::ReadFullUpdateFromDisk(
-    Graph* graph,
-    const std::string& new_kernel_part,
-    const std::string& new_image,
-    off_t image_size,
-    int fd,
-    off_t* data_file_size,
-    off_t chunk_size,
-    vector<DeltaArchiveManifest_InstallOperation>* kernel_ops,
-    std::vector<Vertex::Index>* final_order) {
-  TEST_AND_RETURN_FALSE(chunk_size > 0);
-  TEST_AND_RETURN_FALSE((chunk_size % kBlockSize) == 0);
-
-  // Get the sizes early in the function, so we can fail fast if the user
-  // passed us bad paths.
-  TEST_AND_RETURN_FALSE(image_size >= 0 &&
-                        image_size <= utils::FileSize(new_image));
-  const off_t kernel_size = utils::FileSize(new_kernel_part);
-  TEST_AND_RETURN_FALSE(kernel_size >= 0);
-
-  off_t part_sizes[] = { image_size, kernel_size };
-  string paths[] = { new_image, new_kernel_part };
-
-  for (int partition = 0; partition < 2; ++partition) {
-    const string& path = paths[partition];
-    LOG(INFO) << "compressing " << path;
-
-    int in_fd = open(path.c_str(), O_RDONLY, 0);
-    TEST_AND_RETURN_FALSE(in_fd >= 0);
-    ScopedFdCloser in_fd_closer(&in_fd);
-
-    for (off_t bytes_left = part_sizes[partition], counter = 0, offset = 0;
-         bytes_left > 0;
-         bytes_left -= chunk_size, ++counter, offset += chunk_size) {
-      DeltaArchiveManifest_InstallOperation* op = NULL;
-      if (partition == 0) {
-        graph->resize(graph->size() + 1);
-        graph->back().file_name = path + StringPrintf("-%" PRIi64, counter);
-        op = &graph->back().op;
-        final_order->push_back(graph->size() - 1);
-      } else {
-        kernel_ops->resize(kernel_ops->size() + 1);
-        op = &kernel_ops->back();
-      }
-
-      vector<char> buf(min(bytes_left, chunk_size));
-      ssize_t bytes_read = -1;
-
-      TEST_AND_RETURN_FALSE(utils::PReadAll(
-          in_fd, &buf[0], buf.size(), offset, &bytes_read));
-      TEST_AND_RETURN_FALSE(bytes_read == static_cast<ssize_t>(buf.size()));
-
-      vector<char> buf_compressed;
-
-      TEST_AND_RETURN_FALSE(BzipCompress(buf, &buf_compressed));
-      const bool compress = buf_compressed.size() < buf.size();
-      const vector<char>& use_buf = compress ? buf_compressed : buf;
-      if (compress) {
-        op->set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
-      } else {
-        op->set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE);
-      }
-      op->set_data_offset(*data_file_size);
-      TEST_AND_RETURN_FALSE(utils::WriteAll(fd, &use_buf[0], use_buf.size()));
-      *data_file_size += use_buf.size();
-      op->set_data_length(use_buf.size());
-      Extent* dst_extent = op->add_dst_extents();
-      dst_extent->set_start_block(offset / kBlockSize);
-      dst_extent->set_num_blocks(chunk_size / kBlockSize);
-
-      LOG(INFO) << StringPrintf("%.1f", offset * 100.0 / part_sizes[partition])
-                << "% complete (offset: " << offset << ", buf size: "
-                << buf.size() << ")";
-    }
-  }
-
-  return true;
-}
-
 bool DeltaDiffGenerator::GenerateDeltaUpdateFile(
     const string& old_root,
     const string& old_image,
@@ -1480,15 +1402,16 @@
       // Full update
       off_t new_image_size =
           static_cast<off_t>(new_image_block_count) * new_image_block_size;
-      TEST_AND_RETURN_FALSE(ReadFullUpdateFromDisk(&graph,
-                                                   new_kernel_part,
-                                                   new_image,
-                                                   new_image_size,
-                                                   fd,
-                                                   &data_file_size,
-                                                   kFullUpdateChunkSize,
-                                                   &kernel_ops,
-                                                   &final_order));
+      TEST_AND_RETURN_FALSE(FullUpdateGenerator::Run(&graph,
+                                                     new_kernel_part,
+                                                     new_image,
+                                                     new_image_size,
+                                                     fd,
+                                                     &data_file_size,
+                                                     kFullUpdateChunkSize,
+                                                     kBlockSize,
+                                                     &kernel_ops,
+                                                     &final_order));
     }
   }