//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/payload_generator/inplace_generator.h"

#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "update_engine/common/utils.h"
#include "update_engine/payload_consumer/payload_constants.h"
#include "update_engine/payload_generator/cycle_breaker.h"
#include "update_engine/payload_generator/delta_diff_generator.h"
#include "update_engine/payload_generator/delta_diff_utils.h"
#include "update_engine/payload_generator/extent_ranges.h"
#include "update_engine/payload_generator/graph_types.h"
#include "update_engine/payload_generator/graph_utils.h"
#include "update_engine/payload_generator/topological_sort.h"
#include "update_engine/update_metadata.pb.h"

using std::make_pair;
using std::map;
using std::pair;
using std::set;
using std::string;
using std::vector;

namespace chromeos_update_engine {

using Block = InplaceGenerator::Block;

namespace {

// The only PayloadVersion supported by this implementation.
const PayloadVersion kInPlacePayloadVersion{kChromeOSMajorPayloadVersion,
                                            kInPlaceMinorPayloadVersion};

// This class allocates non-existent temp blocks, starting from
// kTempBlockStart. Other code is responsible for converting these
// temp blocks into real blocks, as the client can't read or write to
// these blocks.
class DummyExtentAllocator {
 public:
  vector<Extent> Allocate(const uint64_t block_count) {
    vector<Extent> ret(1);
    ret[0].set_start_block(next_block_);
    ret[0].set_num_blocks(block_count);
    next_block_ += block_count;
    return ret;
  }

 private:
  uint64_t next_block_{kTempBlockStart};
};

// Takes a vector of blocks and returns an equivalent vector of Extent
// objects.
vector<Extent> CompressExtents(const vector<uint64_t>& blocks) {
  vector<Extent> new_extents;
  for (uint64_t block : blocks) {
    AppendBlockToExtents(&new_extents, block);
  }
  return new_extents;
}

// Helper class to compare two operations by start block of the first Extent in
// their destination extents given the index of the operations in the graph.
class IndexedInstallOperationsDstComparator {
 public:
  explicit IndexedInstallOperationsDstComparator(Graph* graph)
    : graph_(graph) {}

  // Compares the operations in the vertex a and b of graph_.
  bool operator()(size_t a, size_t b) const {
    return diff_utils::CompareAopsByDestination((*graph_)[a].aop,
                                                (*graph_)[b].aop);
  }

 private:
  const Graph* const graph_;
};

}  // namespace

void InplaceGenerator::CheckGraph(const Graph& graph) {
  for (const Vertex& v : graph) {
    CHECK(v.aop.op.has_type());
  }
}

void InplaceGenerator::SubstituteBlocks(
    Vertex* vertex,
    const vector<Extent>& remove_extents,
    const vector<Extent>& replace_extents) {
  // First, expand out the blocks that op reads from
  vector<uint64_t> read_blocks =
      ExpandExtents(vertex->aop.op.src_extents());
  {
    // Expand remove_extents and replace_extents
    vector<uint64_t> remove_extents_expanded = ExpandExtents(remove_extents);
    vector<uint64_t> replace_extents_expanded = ExpandExtents(replace_extents);
    CHECK_EQ(remove_extents_expanded.size(), replace_extents_expanded.size());
    map<uint64_t, uint64_t> conversion;
    for (vector<uint64_t>::size_type i = 0;
         i < replace_extents_expanded.size(); i++) {
      conversion[remove_extents_expanded[i]] = replace_extents_expanded[i];
    }
    ApplyMap(&read_blocks, conversion);
    for (auto& edge_prop_pair : vertex->out_edges) {
      vector<uint64_t> write_before_deps_expanded = ExpandExtents(
          edge_prop_pair.second.write_extents);
      ApplyMap(&write_before_deps_expanded, conversion);
      edge_prop_pair.second.write_extents =
          CompressExtents(write_before_deps_expanded);
    }
  }
  // Convert read_blocks back to extents
  vertex->aop.op.clear_src_extents();
  vector<Extent> new_extents = CompressExtents(read_blocks);
  StoreExtents(new_extents, vertex->aop.op.mutable_src_extents());
}

bool InplaceGenerator::CutEdges(Graph* graph,
                                const set<Edge>& edges,
                                vector<CutEdgeVertexes>* out_cuts) {
  DummyExtentAllocator scratch_allocator;
  vector<CutEdgeVertexes> cuts;
  cuts.reserve(edges.size());

  uint64_t scratch_blocks_used = 0;
  for (const Edge& edge : edges) {
    cuts.resize(cuts.size() + 1);
    vector<Extent> old_extents =
        (*graph)[edge.first].out_edges[edge.second].extents;
    // Choose some scratch space
    scratch_blocks_used += graph_utils::EdgeWeight(*graph, edge);
    cuts.back().tmp_extents =
        scratch_allocator.Allocate(graph_utils::EdgeWeight(*graph, edge));
    // create vertex to copy original->scratch
    cuts.back().new_vertex = graph->size();
    graph->emplace_back();
    cuts.back().old_src = edge.first;
    cuts.back().old_dst = edge.second;

    EdgeProperties& cut_edge_properties =
        (*graph)[edge.first].out_edges.find(edge.second)->second;

    // This should never happen, as we should only be cutting edges between
    // real file nodes, and write-before relationships are created from
    // a real file node to a temp copy node:
    CHECK(cut_edge_properties.write_extents.empty())
        << "Can't cut edge that has write-before relationship.";

    // make node depend on the copy operation
    (*graph)[edge.first].out_edges.insert(make_pair(graph->size() - 1,
                                                    cut_edge_properties));

    // Set src/dst extents and other proto variables for copy operation
    graph->back().aop.op.set_type(InstallOperation::MOVE);
    StoreExtents(cut_edge_properties.extents,
                 graph->back().aop.op.mutable_src_extents());
    StoreExtents(cuts.back().tmp_extents,
                 graph->back().aop.op.mutable_dst_extents());
    graph->back().aop.op.set_src_length(
        graph_utils::EdgeWeight(*graph, edge) * kBlockSize);
    graph->back().aop.op.set_dst_length(graph->back().aop.op.src_length());

    // make the dest node read from the scratch space
    SubstituteBlocks(
        &((*graph)[edge.second]),
        (*graph)[edge.first].out_edges[edge.second].extents,
        cuts.back().tmp_extents);

    // delete the old edge
    CHECK_EQ(static_cast<Graph::size_type>(1),
             (*graph)[edge.first].out_edges.erase(edge.second));

    // Add an edge from dst to copy operation
    EdgeProperties write_before_edge_properties;
    write_before_edge_properties.write_extents = cuts.back().tmp_extents;
    (*graph)[edge.second].out_edges.insert(
        make_pair(graph->size() - 1, write_before_edge_properties));
  }
  out_cuts->swap(cuts);
  return true;
}

// Creates all the edges for the graph. Writers of a block point to
// readers of the same block. This is because for an edge A->B, B
// must complete before A executes.
void InplaceGenerator::CreateEdges(
    Graph* graph,
    const vector<Block>& blocks) {
  for (vector<Block>::size_type i = 0;
       i < blocks.size(); i++) {
    // Blocks with both a reader and writer get an edge
    if (blocks[i].reader == Vertex::kInvalidIndex ||
        blocks[i].writer == Vertex::kInvalidIndex)
      continue;
    // Don't have a node depend on itself
    if (blocks[i].reader == blocks[i].writer)
      continue;
    // See if there's already an edge we can add onto
    Vertex::EdgeMap::iterator edge_it =
        (*graph)[blocks[i].writer].out_edges.find(blocks[i].reader);
    if (edge_it == (*graph)[blocks[i].writer].out_edges.end()) {
      // No existing edge. Create one
      (*graph)[blocks[i].writer].out_edges.insert(
          make_pair(blocks[i].reader, EdgeProperties()));
      edge_it = (*graph)[blocks[i].writer].out_edges.find(blocks[i].reader);
      CHECK(edge_it != (*graph)[blocks[i].writer].out_edges.end());
    }
    AppendBlockToExtents(&edge_it->second.extents, i);
  }
}

namespace {

class SortCutsByTopoOrderLess {
 public:
  explicit SortCutsByTopoOrderLess(
      const vector<vector<Vertex::Index>::size_type>& table)
      : table_(table) {}
  bool operator()(const CutEdgeVertexes& a, const CutEdgeVertexes& b) {
    return table_[a.old_dst] < table_[b.old_dst];
  }
 private:
  const vector<vector<Vertex::Index>::size_type>& table_;
};

}  // namespace

void InplaceGenerator::GenerateReverseTopoOrderMap(
    const vector<Vertex::Index>& op_indexes,
    vector<vector<Vertex::Index>::size_type>* reverse_op_indexes) {
  vector<vector<Vertex::Index>::size_type> table(op_indexes.size());
  for (vector<Vertex::Index>::size_type i = 0, e = op_indexes.size();
       i != e; ++i) {
    Vertex::Index node = op_indexes[i];
    if (table.size() < (node + 1)) {
      table.resize(node + 1);
    }
    table[node] = i;
  }
  reverse_op_indexes->swap(table);
}

void InplaceGenerator::SortCutsByTopoOrder(
    const vector<Vertex::Index>& op_indexes,
    vector<CutEdgeVertexes>* cuts) {
  // first, make a reverse lookup table.
  vector<vector<Vertex::Index>::size_type> table;
  GenerateReverseTopoOrderMap(op_indexes, &table);
  SortCutsByTopoOrderLess less(table);
  sort(cuts->begin(), cuts->end(), less);
}

void InplaceGenerator::MoveAndSortFullOpsToBack(
    Graph* graph,
    vector<Vertex::Index>* op_indexes) {
  vector<Vertex::Index> ret;
  vector<Vertex::Index> full_ops;
  ret.reserve(op_indexes->size());
  for (auto op_index : *op_indexes) {
    InstallOperation_Type type = (*graph)[op_index].aop.op.type();
    if (type == InstallOperation::REPLACE ||
        type == InstallOperation::REPLACE_BZ) {
      full_ops.push_back(op_index);
    } else {
      ret.push_back(op_index);
    }
  }
  LOG(INFO) << "Stats: " << full_ops.size() << " full ops out of "
            << (full_ops.size() + ret.size()) << " total ops.";
  // Sort full ops according to their dst_extents.
  sort(full_ops.begin(), full_ops.end(),
       IndexedInstallOperationsDstComparator(graph));
  ret.insert(ret.end(), full_ops.begin(), full_ops.end());
  op_indexes->swap(ret);
}

namespace {

template<typename T>
bool TempBlocksExistInExtents(const T& extents) {
  for (int i = 0, e = extents.size(); i < e; ++i) {
    Extent extent = GetElement(extents, i);
    uint64_t start = extent.start_block();
    uint64_t num = extent.num_blocks();
    if (start >= kTempBlockStart || (start + num) >= kTempBlockStart) {
      LOG(ERROR) << "temp block!";
      LOG(ERROR) << "start: " << start << ", num: " << num;
      LOG(ERROR) << "kTempBlockStart: " << kTempBlockStart;
      LOG(ERROR) << "returning true";
      return true;
    }
    // check for wrap-around, which would be a bug:
    CHECK(start <= (start + num));
  }
  return false;
}

// Converts the cuts, which must all have the same |old_dst| member,
// to full. It does this by converting the |old_dst| to REPLACE or
// REPLACE_BZ, dropping all incoming edges to |old_dst|, and marking
// all temp nodes invalid.
bool ConvertCutsToFull(
    Graph* graph,
    const string& new_part,
    BlobFileWriter* blob_file,
    vector<Vertex::Index>* op_indexes,
    vector<vector<Vertex::Index>::size_type>* reverse_op_indexes,
    const vector<CutEdgeVertexes>& cuts) {
  CHECK(!cuts.empty());
  set<Vertex::Index> deleted_nodes;
  for (const CutEdgeVertexes& cut : cuts) {
    TEST_AND_RETURN_FALSE(InplaceGenerator::ConvertCutToFullOp(
        graph,
        cut,
        new_part,
        blob_file));
    deleted_nodes.insert(cut.new_vertex);
  }
  deleted_nodes.insert(cuts[0].old_dst);

  vector<Vertex::Index> new_op_indexes;
  new_op_indexes.reserve(op_indexes->size());
  for (Vertex::Index vertex_index : *op_indexes) {
    if (utils::SetContainsKey(deleted_nodes, vertex_index))
      continue;
    new_op_indexes.push_back(vertex_index);
  }
  new_op_indexes.push_back(cuts[0].old_dst);
  op_indexes->swap(new_op_indexes);
  InplaceGenerator::GenerateReverseTopoOrderMap(*op_indexes,
                                                reverse_op_indexes);
  return true;
}

// Tries to assign temp blocks for a collection of cuts, all of which share
// the same old_dst member. If temp blocks can't be found, old_dst will be
// converted to a REPLACE or REPLACE_BZ operation. Returns true on success,
// which can happen even if blocks are converted to full. Returns false
// on exceptional error cases.
bool AssignBlockForAdjoiningCuts(
    Graph* graph,
    const string& new_part,
    BlobFileWriter* blob_file,
    vector<Vertex::Index>* op_indexes,
    vector<vector<Vertex::Index>::size_type>* reverse_op_indexes,
    const vector<CutEdgeVertexes>& cuts) {
  CHECK(!cuts.empty());
  const Vertex::Index old_dst = cuts[0].old_dst;
  // Calculate # of blocks needed
  uint64_t blocks_needed = 0;
  vector<uint64_t> cuts_blocks_needed(cuts.size());
  for (vector<CutEdgeVertexes>::size_type i = 0; i < cuts.size(); ++i) {
    uint64_t cut_blocks_needed = 0;
    for (const Extent& extent : cuts[i].tmp_extents) {
      cut_blocks_needed += extent.num_blocks();
    }
    blocks_needed += cut_blocks_needed;
    cuts_blocks_needed[i] = cut_blocks_needed;
  }

  // Find enough blocks
  ExtentRanges scratch_ranges;
  // Each block that's supplying temp blocks and the corresponding blocks:
  typedef vector<pair<Vertex::Index, ExtentRanges>> SupplierVector;
  SupplierVector block_suppliers;
  uint64_t scratch_blocks_found = 0;
  for (vector<Vertex::Index>::size_type i = (*reverse_op_indexes)[old_dst] + 1,
           e = op_indexes->size(); i < e; ++i) {
    Vertex::Index test_node = (*op_indexes)[i];
    if (!(*graph)[test_node].valid)
      continue;
    // See if this node has sufficient blocks
    ExtentRanges ranges;
    ranges.AddRepeatedExtents((*graph)[test_node].aop.op.dst_extents());
    ranges.SubtractExtent(ExtentForRange(
        kTempBlockStart, kSparseHole - kTempBlockStart));
    ranges.SubtractRepeatedExtents((*graph)[test_node].aop.op.src_extents());
    // For now, for simplicity, subtract out all blocks in read-before
    // dependencies.
    for (Vertex::EdgeMap::const_iterator edge_i =
             (*graph)[test_node].out_edges.begin(),
             edge_e = (*graph)[test_node].out_edges.end();
         edge_i != edge_e; ++edge_i) {
      ranges.SubtractExtents(edge_i->second.extents);
    }

    // Prevent using the block 0 as scratch space due to crbug.com/480751.
    if (ranges.ContainsBlock(0)) {
      LOG(INFO) << "Removing block 0 from the selected scratch range in vertex "
                << i;
      ranges.SubtractBlock(0);
    }

    if (ranges.blocks() == 0)
      continue;

    if (ranges.blocks() + scratch_blocks_found > blocks_needed) {
      // trim down ranges
      vector<Extent> new_ranges = ranges.GetExtentsForBlockCount(
          blocks_needed - scratch_blocks_found);
      ranges = ExtentRanges();
      ranges.AddExtents(new_ranges);
    }
    scratch_ranges.AddRanges(ranges);
    block_suppliers.push_back(make_pair(test_node, ranges));
    scratch_blocks_found += ranges.blocks();
    if (scratch_ranges.blocks() >= blocks_needed)
      break;
  }
  if (scratch_ranges.blocks() < blocks_needed) {
    LOG(INFO) << "Unable to find sufficient scratch";
    TEST_AND_RETURN_FALSE(ConvertCutsToFull(graph,
                                            new_part,
                                            blob_file,
                                            op_indexes,
                                            reverse_op_indexes,
                                            cuts));
    return true;
  }
  // Use the scratch we found
  TEST_AND_RETURN_FALSE(scratch_ranges.blocks() == scratch_blocks_found);

  // Make all the suppliers depend on this node
  for (const auto& index_range_pair : block_suppliers) {
    graph_utils::AddReadBeforeDepExtents(
        &(*graph)[index_range_pair.first],
        old_dst,
        index_range_pair.second.GetExtentsForBlockCount(
            index_range_pair.second.blocks()));
  }

  // Replace temp blocks in each cut
  for (vector<CutEdgeVertexes>::size_type i = 0; i < cuts.size(); ++i) {
    const CutEdgeVertexes& cut = cuts[i];
    vector<Extent> real_extents =
        scratch_ranges.GetExtentsForBlockCount(cuts_blocks_needed[i]);
    scratch_ranges.SubtractExtents(real_extents);

    // Fix the old dest node w/ the real blocks
    InplaceGenerator::SubstituteBlocks(&(*graph)[old_dst],
                                         cut.tmp_extents,
                                         real_extents);

    // Fix the new node w/ the real blocks. Since the new node is just a
    // copy operation, we can replace all the dest extents w/ the real
    // blocks.
    InstallOperation* op = &(*graph)[cut.new_vertex].aop.op;
    op->clear_dst_extents();
    StoreExtents(real_extents, op->mutable_dst_extents());
  }
  return true;
}

}  // namespace

bool InplaceGenerator::AssignTempBlocks(
    Graph* graph,
    const string& new_part,
    BlobFileWriter* blob_file,
    vector<Vertex::Index>* op_indexes,
    vector<vector<Vertex::Index>::size_type>* reverse_op_indexes,
    const vector<CutEdgeVertexes>& cuts) {
  CHECK(!cuts.empty());

  // group of cuts w/ the same old_dst:
  vector<CutEdgeVertexes> cuts_group;

  for (vector<CutEdgeVertexes>::size_type i = cuts.size() - 1, e = 0;
       true ; --i) {
    LOG(INFO) << "Fixing temp blocks in cut " << i
              << ": old dst: " << cuts[i].old_dst << " new vertex: "
              << cuts[i].new_vertex << " path: "
              << (*graph)[cuts[i].old_dst].aop.name;

    if (cuts_group.empty() || (cuts_group[0].old_dst == cuts[i].old_dst)) {
      cuts_group.push_back(cuts[i]);
    } else {
      CHECK(!cuts_group.empty());
      TEST_AND_RETURN_FALSE(AssignBlockForAdjoiningCuts(graph,
                                                        new_part,
                                                        blob_file,
                                                        op_indexes,
                                                        reverse_op_indexes,
                                                        cuts_group));
      cuts_group.clear();
      cuts_group.push_back(cuts[i]);
    }

    if (i == e) {
      // break out of for() loop
      break;
    }
  }
  CHECK(!cuts_group.empty());
  TEST_AND_RETURN_FALSE(AssignBlockForAdjoiningCuts(graph,
                                                    new_part,
                                                    blob_file,
                                                    op_indexes,
                                                    reverse_op_indexes,
                                                    cuts_group));
  return true;
}

bool InplaceGenerator::NoTempBlocksRemain(const Graph& graph) {
  size_t idx = 0;
  for (Graph::const_iterator it = graph.begin(), e = graph.end(); it != e;
       ++it, ++idx) {
    if (!it->valid)
      continue;
    const InstallOperation& op = it->aop.op;
    if (TempBlocksExistInExtents(op.dst_extents()) ||
        TempBlocksExistInExtents(op.src_extents())) {
      LOG(INFO) << "bad extents in node " << idx;
      LOG(INFO) << "so yeah";
      return false;
    }

    // Check out-edges:
    for (const auto& edge_prop_pair : it->out_edges) {
      if (TempBlocksExistInExtents(edge_prop_pair.second.extents) ||
          TempBlocksExistInExtents(edge_prop_pair.second.write_extents)) {
        LOG(INFO) << "bad out edge in node " << idx;
        LOG(INFO) << "so yeah";
        return false;
      }
    }
  }
  return true;
}

bool InplaceGenerator::ConvertCutToFullOp(Graph* graph,
                                          const CutEdgeVertexes& cut,
                                          const string& new_part,
                                          BlobFileWriter* blob_file) {
  // Drop all incoming edges, keep all outgoing edges

  // Keep all outgoing edges
  if ((*graph)[cut.old_dst].aop.op.type() != InstallOperation::REPLACE_BZ &&
      (*graph)[cut.old_dst].aop.op.type() != InstallOperation::REPLACE) {
    Vertex::EdgeMap out_edges = (*graph)[cut.old_dst].out_edges;
    graph_utils::DropWriteBeforeDeps(&out_edges);

    // Replace the operation with a REPLACE or REPLACE_BZ to generate the same
    // |new_extents| list of blocks and update the graph.
    vector<AnnotatedOperation> new_aop;
    vector<Extent> new_extents;
    ExtentsToVector((*graph)[cut.old_dst].aop.op.dst_extents(),
                    &new_extents);
    TEST_AND_RETURN_FALSE(diff_utils::DeltaReadFile(
        &new_aop,
        "",  // old_part
        new_part,
        vector<Extent>(),  // old_extents
        new_extents,
        (*graph)[cut.old_dst].aop.name,
        -1,  // chunk_blocks, forces to have a single operation.
        kInPlacePayloadVersion,
        blob_file));
    TEST_AND_RETURN_FALSE(new_aop.size() == 1);
    TEST_AND_RETURN_FALSE(AddInstallOpToGraph(
      graph, cut.old_dst, nullptr, new_aop.front().op, new_aop.front().name));

    (*graph)[cut.old_dst].out_edges = out_edges;

    // Right now we don't have doubly-linked edges, so we have to scan
    // the whole graph.
    graph_utils::DropIncomingEdgesTo(graph, cut.old_dst);
  }

  // Delete temp node
  (*graph)[cut.old_src].out_edges.erase(cut.new_vertex);
  CHECK((*graph)[cut.old_dst].out_edges.find(cut.new_vertex) ==
        (*graph)[cut.old_dst].out_edges.end());
  (*graph)[cut.new_vertex].valid = false;
  LOG(INFO) << "marked node invalid: " << cut.new_vertex;
  return true;
}

bool InplaceGenerator::ConvertGraphToDag(Graph* graph,
                                         const string& new_part,
                                         BlobFileWriter* blob_file,
                                         vector<Vertex::Index>* final_order,
                                         Vertex::Index scratch_vertex) {
  CycleBreaker cycle_breaker;
  LOG(INFO) << "Finding cycles...";
  set<Edge> cut_edges;
  cycle_breaker.BreakCycles(*graph, &cut_edges);
  LOG(INFO) << "done finding cycles";
  CheckGraph(*graph);

  // Calculate number of scratch blocks needed

  LOG(INFO) << "Cutting cycles...";
  vector<CutEdgeVertexes> cuts;
  TEST_AND_RETURN_FALSE(CutEdges(graph, cut_edges, &cuts));
  LOG(INFO) << "done cutting cycles";
  LOG(INFO) << "There are " << cuts.size() << " cuts.";
  CheckGraph(*graph);

  LOG(INFO) << "Creating initial topological order...";
  TopologicalSort(*graph, final_order);
  LOG(INFO) << "done with initial topo order";
  CheckGraph(*graph);

  LOG(INFO) << "Moving full ops to the back";
  MoveAndSortFullOpsToBack(graph, final_order);
  LOG(INFO) << "done moving full ops to back";

  vector<vector<Vertex::Index>::size_type> inverse_final_order;
  GenerateReverseTopoOrderMap(*final_order, &inverse_final_order);

  SortCutsByTopoOrder(*final_order, &cuts);

  if (!cuts.empty())
    TEST_AND_RETURN_FALSE(AssignTempBlocks(graph,
                                           new_part,
                                           blob_file,
                                           final_order,
                                           &inverse_final_order,
                                           cuts));
  LOG(INFO) << "Making sure all temp blocks have been allocated";

  // Remove the scratch node, if any
  if (scratch_vertex != Vertex::kInvalidIndex) {
    final_order->erase(final_order->begin() +
                       inverse_final_order[scratch_vertex]);
    (*graph)[scratch_vertex].valid = false;
    GenerateReverseTopoOrderMap(*final_order, &inverse_final_order);
  }

  graph_utils::DumpGraph(*graph);
  CHECK(NoTempBlocksRemain(*graph));
  LOG(INFO) << "done making sure all temp blocks are allocated";
  return true;
}

void InplaceGenerator::CreateScratchNode(uint64_t start_block,
                                         uint64_t num_blocks,
                                         Vertex* vertex) {
  vertex->aop.name = "<scratch>";
  vertex->aop.op.set_type(InstallOperation::REPLACE_BZ);
  vertex->aop.op.set_data_offset(0);
  vertex->aop.op.set_data_length(0);
  Extent* extent = vertex->aop.op.add_dst_extents();
  extent->set_start_block(start_block);
  extent->set_num_blocks(num_blocks);
}

bool InplaceGenerator::AddInstallOpToBlocksVector(
    const InstallOperation& operation,
    const Graph& graph,
    Vertex::Index vertex,
    vector<Block>* blocks) {
  // See if this is already present.
  TEST_AND_RETURN_FALSE(operation.dst_extents_size() > 0);

  enum BlockField { READER = 0, WRITER, BLOCK_FIELD_COUNT };
  for (int field = READER; field < BLOCK_FIELD_COUNT; field++) {
    const char* past_participle = (field == READER) ? "read" : "written";
    const google::protobuf::RepeatedPtrField<Extent>& extents =
        (field == READER) ? operation.src_extents() : operation.dst_extents();
    Vertex::Index Block::*access_type = (field == READER) ?
        &Block::reader : &Block::writer;

    for (const Extent& extent : extents) {
      for (uint64_t block = extent.start_block();
           block < (extent.start_block() + extent.num_blocks()); block++) {
        if ((*blocks)[block].*access_type != Vertex::kInvalidIndex) {
          LOG(FATAL) << "Block " << block << " is already "
                     << past_participle << " by "
                     << (*blocks)[block].*access_type << "("
                     << graph[(*blocks)[block].*access_type].aop.name
                     << ") and also " << vertex << "("
                     << graph[vertex].aop.name << ")";
        }
        (*blocks)[block].*access_type = vertex;
      }
    }
  }
  return true;
}

bool InplaceGenerator::AddInstallOpToGraph(Graph* graph,
                                           Vertex::Index existing_vertex,
                                           vector<Block>* blocks,
                                           const InstallOperation& operation,
                                           const string& op_name) {
  Vertex::Index vertex = existing_vertex;
  if (vertex == Vertex::kInvalidIndex) {
    graph->emplace_back();
    vertex = graph->size() - 1;
  }
  (*graph)[vertex].aop.op = operation;
  CHECK((*graph)[vertex].aop.op.has_type());
  (*graph)[vertex].aop.name = op_name;

  if (blocks)
    TEST_AND_RETURN_FALSE(InplaceGenerator::AddInstallOpToBlocksVector(
        (*graph)[vertex].aop.op,
        *graph,
        vertex,
        blocks));
  return true;
}

void InplaceGenerator::ApplyMap(vector<uint64_t>* collection,
                                const map<uint64_t, uint64_t>& the_map) {
  for (uint64_t& elem : *collection) {
    const auto& map_it = the_map.find(elem);
    if (map_it != the_map.end())
      elem = map_it->second;
  }
}

bool InplaceGenerator::ResolveReadAfterWriteDependencies(
    const PartitionConfig& old_part,
    const PartitionConfig& new_part,
    uint64_t partition_size,
    size_t block_size,
    BlobFileWriter* blob_file,
    vector<AnnotatedOperation>* aops) {
  // Convert the operations to the graph.
  Graph graph;
  CheckGraph(graph);
  vector<Block> blocks(std::max(old_part.size, new_part.size) / block_size);
  for (const auto& aop : *aops) {
    AddInstallOpToGraph(
        &graph, Vertex::kInvalidIndex, &blocks, aop.op, aop.name);
  }
  CheckGraph(graph);

  // Final scratch block (if there's space)
  Vertex::Index scratch_vertex = Vertex::kInvalidIndex;
  if (blocks.size() < (partition_size / block_size)) {
    scratch_vertex = graph.size();
    graph.emplace_back();
    size_t scratch_blocks = (partition_size / block_size) - blocks.size();
    LOG(INFO) << "Added " << scratch_blocks << " scratch space blocks.";
    CreateScratchNode(blocks.size(), scratch_blocks, &graph.back());
  }
  CheckGraph(graph);

  LOG(INFO) << "Creating edges...";
  CreateEdges(&graph, blocks);
  LOG(INFO) << "Done creating edges";
  CheckGraph(graph);

  vector<Vertex::Index> final_order;
  TEST_AND_RETURN_FALSE(ConvertGraphToDag(
      &graph,
      new_part.path,
      blob_file,
      &final_order,
      scratch_vertex));

  // Copy operations over to the |aops| vector in the final_order generated by
  // the topological sort.
  aops->clear();
  aops->reserve(final_order.size());
  for (const Vertex::Index vertex_index : final_order) {
    const Vertex& vertex = graph[vertex_index];
    aops->push_back(vertex.aop);
  }
  return true;
}

bool InplaceGenerator::GenerateOperations(
    const PayloadGenerationConfig& config,
    const PartitionConfig& old_part,
    const PartitionConfig& new_part,
    BlobFileWriter* blob_file,
    vector<AnnotatedOperation>* aops) {
  TEST_AND_RETURN_FALSE(old_part.name == new_part.name);
  TEST_AND_RETURN_FALSE(config.version.major == kInPlacePayloadVersion.major);
  TEST_AND_RETURN_FALSE(config.version.minor == kInPlacePayloadVersion.minor);

  ssize_t hard_chunk_blocks = (config.hard_chunk_size == -1 ? -1 :
                               config.hard_chunk_size / config.block_size);
  size_t soft_chunk_blocks = config.soft_chunk_size / config.block_size;
  uint64_t partition_size = new_part.size;
  if (new_part.name == kLegacyPartitionNameRoot)
    partition_size = config.rootfs_partition_size;

  LOG(INFO) << "Delta compressing " << new_part.name << " partition...";
  TEST_AND_RETURN_FALSE(diff_utils::DeltaReadPartition(aops,
                                                       old_part,
                                                       new_part,
                                                       hard_chunk_blocks,
                                                       soft_chunk_blocks,
                                                       config.version,
                                                       blob_file));
  LOG(INFO) << "Done reading " << new_part.name;

  TEST_AND_RETURN_FALSE(ResolveReadAfterWriteDependencies(
      old_part, new_part, partition_size, config.block_size, blob_file, aops));
  LOG(INFO) << "Done reordering " << new_part.name;
  return true;
}

};  // namespace chromeos_update_engine
