Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "update_engine/delta_diff_generator.h" | 5 #include "update_engine/delta_diff_generator.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <inttypes.h> | 9 #include <inttypes.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 #include "update_engine/payload_signer.h" | 33 #include "update_engine/payload_signer.h" |
| 34 #include "update_engine/subprocess.h" | 34 #include "update_engine/subprocess.h" |
| 35 #include "update_engine/topological_sort.h" | 35 #include "update_engine/topological_sort.h" |
| 36 #include "update_engine/update_metadata.pb.h" | 36 #include "update_engine/update_metadata.pb.h" |
| 37 #include "update_engine/utils.h" | 37 #include "update_engine/utils.h" |
| 38 | 38 |
| 39 using std::make_pair; | 39 using std::make_pair; |
| 40 using std::map; | 40 using std::map; |
| 41 using std::max; | 41 using std::max; |
| 42 using std::min; | 42 using std::min; |
| 43 using std::pair; | |
| 43 using std::set; | 44 using std::set; |
| 44 using std::string; | 45 using std::string; |
| 45 using std::vector; | 46 using std::vector; |
| 46 | 47 |
| 47 namespace chromeos_update_engine { | 48 namespace chromeos_update_engine { |
| 48 | 49 |
| 49 typedef DeltaDiffGenerator::Block Block; | 50 typedef DeltaDiffGenerator::Block Block; |
| 50 typedef map<const DeltaArchiveManifest_InstallOperation*, | 51 typedef map<const DeltaArchiveManifest_InstallOperation*, |
| 51 const string*> OperationNameMap; | 52 const string*> OperationNameMap; |
| 52 | 53 |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 916 LOG(ERROR) << "kTempBlockStart: " << kTempBlockStart; | 917 LOG(ERROR) << "kTempBlockStart: " << kTempBlockStart; |
| 917 LOG(ERROR) << "returning true"; | 918 LOG(ERROR) << "returning true"; |
| 918 return true; | 919 return true; |
| 919 } | 920 } |
| 920 // check for wrap-around, which would be a bug: | 921 // check for wrap-around, which would be a bug: |
| 921 CHECK(start <= (start + num)); | 922 CHECK(start <= (start + num)); |
| 922 } | 923 } |
| 923 return false; | 924 return false; |
| 924 } | 925 } |
| 925 | 926 |
| 927 bool ConvertCutsToFull( | |
|
petkov
2010/10/23 04:52:52
Might be useful to add a docstring.
| |
| 928 Graph* graph, | |
| 929 const string& new_root, | |
| 930 int data_fd, | |
| 931 off_t* data_file_size, | |
| 932 vector<Vertex::Index>* op_indexes, | |
| 933 vector<vector<Vertex::Index>::size_type>* reverse_op_indexes, | |
| 934 const vector<CutEdgeVertexes>& cuts) { | |
| 935 CHECK(!cuts.empty()); | |
| 936 set<Vertex::Index> deleted_nodes; | |
| 937 for (vector<CutEdgeVertexes>::const_iterator it = cuts.begin(), | |
| 938 e = cuts.end(); it != e; ++it) { | |
| 939 TEST_AND_RETURN_FALSE(DeltaDiffGenerator::ConvertCutToFullOp( | |
| 940 graph, | |
| 941 *it, | |
| 942 new_root, | |
| 943 data_fd, | |
| 944 data_file_size)); | |
| 945 deleted_nodes.insert(it->new_vertex); | |
| 946 } | |
| 947 deleted_nodes.insert(cuts[0].old_dst); | |
| 948 | |
| 949 vector<Vertex::Index> new_op_indexes; | |
| 950 new_op_indexes.reserve(op_indexes->size()); | |
| 951 for (vector<Vertex::Index>::iterator it = op_indexes->begin(), | |
| 952 e = op_indexes->end(); it != e; ++it) { | |
| 953 if (utils::SetContainsKey(deleted_nodes, *it)) | |
| 954 continue; | |
| 955 new_op_indexes.push_back(*it); | |
| 956 } | |
| 957 new_op_indexes.push_back(cuts[0].old_dst); | |
| 958 op_indexes->swap(new_op_indexes); | |
| 959 DeltaDiffGenerator::GenerateReverseTopoOrderMap(*op_indexes, | |
| 960 reverse_op_indexes); | |
| 961 return true; | |
| 962 } | |
| 963 | |
| 964 // All cuts must have the same old_dst. | |
| 965 bool AssignBlockForAdjoiningCuts( | |
|
petkov
2010/10/23 04:52:52
A docstring might be useful. Also, it might make s
| |
| 966 Graph* graph, | |
| 967 const string& new_root, | |
| 968 int data_fd, | |
| 969 off_t* data_file_size, | |
| 970 vector<Vertex::Index>* op_indexes, | |
| 971 vector<vector<Vertex::Index>::size_type>* reverse_op_indexes, | |
| 972 const vector<CutEdgeVertexes>& cuts) { | |
| 973 CHECK(!cuts.empty()); | |
| 974 const Vertex::Index old_dst = cuts[0].old_dst; | |
| 975 // Calculate # of blocks needed | |
| 976 uint64_t blocks_needed = 0; | |
| 977 map<const CutEdgeVertexes*, uint64_t> cuts_blocks_needed; | |
| 978 for (vector<CutEdgeVertexes>::const_iterator it = cuts.begin(), | |
| 979 e = cuts.end(); it != e; ++it) { | |
| 980 uint64_t cut_blocks_needed = 0; | |
| 981 for (vector<Extent>::const_iterator jt = it->tmp_extents.begin(), | |
| 982 je = it->tmp_extents.end(); jt != je; ++jt) { | |
| 983 cut_blocks_needed += jt->num_blocks(); | |
| 984 } | |
| 985 blocks_needed += cut_blocks_needed; | |
| 986 cuts_blocks_needed[&*it] = cut_blocks_needed; | |
| 987 } | |
| 988 LOG(INFO) << "Need to find " << blocks_needed << " blocks for " | |
| 989 << cuts.size() << " cuts"; | |
| 990 | |
| 991 // Find enough blocks | |
| 992 ExtentRanges scratch_ranges; | |
| 993 // Each block that's supplying temp blocks and the corresponding blocks: | |
| 994 typedef vector<pair<Vertex::Index, ExtentRanges> > SupplierVector; | |
| 995 SupplierVector block_suppliers; | |
| 996 uint64_t scratch_blocks_found = 0; | |
| 997 LOG(INFO) << "scan from " << (*reverse_op_indexes)[old_dst] + 1 | |
| 998 << " to " << op_indexes->size(); | |
| 999 for (vector<Vertex::Index>::size_type i = (*reverse_op_indexes)[old_dst] + 1, | |
| 1000 e = op_indexes->size(); i < e; ++i) { | |
| 1001 Vertex::Index test_node = (*op_indexes)[i]; | |
| 1002 if (!(*graph)[test_node].valid) | |
| 1003 continue; | |
| 1004 // See if this node has sufficient blocks | |
| 1005 ExtentRanges ranges; | |
| 1006 ranges.AddRepeatedExtents((*graph)[test_node].op.dst_extents()); | |
| 1007 ranges.SubtractExtent(ExtentForRange( | |
| 1008 kTempBlockStart, kSparseHole - kTempBlockStart)); | |
| 1009 ranges.SubtractRepeatedExtents((*graph)[test_node].op.src_extents()); | |
| 1010 // For now, for simplicity, subtract out all blocks in read-before | |
| 1011 // dependencies. | |
| 1012 for (Vertex::EdgeMap::const_iterator edge_i = | |
| 1013 (*graph)[test_node].out_edges.begin(), | |
| 1014 edge_e = (*graph)[test_node].out_edges.end(); | |
| 1015 edge_i != edge_e; ++edge_i) { | |
| 1016 ranges.SubtractExtents(edge_i->second.extents); | |
| 1017 } | |
| 1018 if (ranges.blocks() == 0) | |
| 1019 continue; | |
| 1020 | |
| 1021 if (ranges.blocks() + scratch_blocks_found > blocks_needed) { | |
| 1022 // trim down ranges | |
| 1023 vector<Extent> new_ranges = ranges.GetExtentsForBlockCount( | |
| 1024 blocks_needed - scratch_blocks_found); | |
| 1025 ranges = ExtentRanges(); | |
| 1026 ranges.AddExtents(new_ranges); | |
| 1027 } | |
| 1028 scratch_ranges.AddRanges(ranges); | |
| 1029 block_suppliers.push_back(make_pair(test_node, ranges)); | |
| 1030 scratch_blocks_found += ranges.blocks(); | |
| 1031 LOG(INFO) << "Adding " << ranges.blocks() << " blocks. Now have " | |
| 1032 << scratch_ranges.blocks(); | |
| 1033 if (scratch_ranges.blocks() >= blocks_needed) | |
| 1034 break; | |
| 1035 } | |
| 1036 if (scratch_ranges.blocks() < blocks_needed) { | |
| 1037 LOG(INFO) << "Unable to find sufficient scratch"; | |
| 1038 TEST_AND_RETURN_FALSE(ConvertCutsToFull(graph, | |
| 1039 new_root, | |
| 1040 data_fd, | |
| 1041 data_file_size, | |
| 1042 op_indexes, | |
| 1043 reverse_op_indexes, | |
| 1044 cuts)); | |
| 1045 return true; | |
| 1046 } | |
| 1047 // Use the scratch we found | |
| 1048 TEST_AND_RETURN_FALSE(scratch_ranges.blocks() == scratch_blocks_found); | |
| 1049 | |
| 1050 // Make all the suppliers depend on this node | |
| 1051 for (SupplierVector::iterator it = block_suppliers.begin(), | |
| 1052 e = block_suppliers.end(); it != e; ++it) { | |
| 1053 graph_utils::AddReadBeforeDepExtents( | |
| 1054 &(*graph)[it->first], | |
| 1055 old_dst, | |
| 1056 it->second.GetExtentsForBlockCount(it->second.blocks())); | |
| 1057 } | |
| 1058 | |
| 1059 // Replace temp blocks in each cut | |
| 1060 for (vector<CutEdgeVertexes>::const_iterator it = cuts.begin(), | |
| 1061 e = cuts.end(); it != e; ++it) { | |
| 1062 vector<Extent> real_extents = | |
| 1063 scratch_ranges.GetExtentsForBlockCount(cuts_blocks_needed[&*it]); | |
| 1064 scratch_ranges.SubtractExtents(real_extents); | |
| 1065 | |
| 1066 // Fix the old dest node w/ the real blocks | |
| 1067 DeltaDiffGenerator::SubstituteBlocks(&(*graph)[old_dst], | |
| 1068 it->tmp_extents, | |
| 1069 real_extents); | |
| 1070 | |
| 1071 // Fix the new node w/ the real blocks. Since the new node is just a | |
| 1072 // copy operation, we can replace all the dest extents w/ the real | |
| 1073 // blocks. | |
| 1074 DeltaArchiveManifest_InstallOperation *op = | |
| 1075 &(*graph)[it->new_vertex].op; | |
| 1076 op->clear_dst_extents(); | |
| 1077 DeltaDiffGenerator::StoreExtents(real_extents, op->mutable_dst_extents()); | |
| 1078 } | |
| 1079 LOG(INFO) << "Done subbing in for cut set"; | |
| 1080 return true; | |
| 1081 } | |
| 1082 | |
| 926 } // namespace {} | 1083 } // namespace {} |
| 927 | 1084 |
| 928 // Returns true if |op| is a no-op operation that doesn't do any useful work | 1085 // Returns true if |op| is a no-op operation that doesn't do any useful work |
| 929 // (e.g., a move operation that copies blocks onto themselves). | 1086 // (e.g., a move operation that copies blocks onto themselves). |
| 930 bool DeltaDiffGenerator::IsNoopOperation( | 1087 bool DeltaDiffGenerator::IsNoopOperation( |
| 931 const DeltaArchiveManifest_InstallOperation& op) { | 1088 const DeltaArchiveManifest_InstallOperation& op) { |
| 932 return (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE && | 1089 return (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE && |
| 933 ExpandExtents(op.src_extents()) == ExpandExtents(op.dst_extents())); | 1090 ExpandExtents(op.src_extents()) == ExpandExtents(op.dst_extents())); |
| 934 } | 1091 } |
| 935 | 1092 |
| 936 bool DeltaDiffGenerator::AssignTempBlocks( | 1093 bool DeltaDiffGenerator::AssignTempBlocks( |
| 937 Graph* graph, | 1094 Graph* graph, |
| 938 const string& new_root, | 1095 const string& new_root, |
| 939 int data_fd, | 1096 int data_fd, |
| 940 off_t* data_file_size, | 1097 off_t* data_file_size, |
| 941 vector<Vertex::Index>* op_indexes, | 1098 vector<Vertex::Index>* op_indexes, |
| 942 vector<vector<Vertex::Index>::size_type>* reverse_op_indexes, | 1099 vector<vector<Vertex::Index>::size_type>* reverse_op_indexes, |
| 943 vector<CutEdgeVertexes>& cuts) { | 1100 const vector<CutEdgeVertexes>& cuts) { |
| 944 CHECK(!cuts.empty()); | 1101 CHECK(!cuts.empty()); |
| 1102 | |
| 1103 // group of cuts w/ the same old_dst: | |
| 1104 vector<CutEdgeVertexes> cuts_group; | |
| 1105 | |
| 945 for (vector<CutEdgeVertexes>::size_type i = cuts.size() - 1, e = 0; | 1106 for (vector<CutEdgeVertexes>::size_type i = cuts.size() - 1, e = 0; |
| 946 true ; --i) { | 1107 true ; --i) { |
| 947 LOG(INFO) << "Fixing temp blocks in cut " << i | 1108 LOG(INFO) << "Fixing temp blocks in cut " << i |
| 948 << ": old dst: " << cuts[i].old_dst << " new vertex: " | 1109 << ": old dst: " << cuts[i].old_dst << " new vertex: " |
| 949 << cuts[i].new_vertex; | 1110 << cuts[i].new_vertex << " path: " |
| 950 const uint64_t blocks_needed = | 1111 << (*graph)[cuts[i].old_dst].file_name; |
| 951 graph_utils::BlocksInExtents(cuts[i].tmp_extents); | 1112 |
| 952 LOG(INFO) << "Scanning for usable blocks (" << blocks_needed << " needed)"; | 1113 if (cuts_group.empty() || (cuts_group[0].old_dst == cuts[i].old_dst)) { |
| 953 // For now, just look for a single op w/ sufficient blocks, not | 1114 cuts_group.push_back(cuts[i]); |
| 954 // considering blocks from outgoing read-before deps. | 1115 } else { |
| 955 Vertex::Index node = cuts[i].old_dst; | 1116 CHECK(!cuts_group.empty()); |
| 956 DeltaArchiveManifest_InstallOperation_Type node_type = | 1117 TEST_AND_RETURN_FALSE(AssignBlockForAdjoiningCuts(graph, |
| 957 (*graph)[node].op.type(); | 1118 new_root, |
| 958 if (node_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE || | 1119 data_fd, |
| 959 node_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { | 1120 data_file_size, |
| 960 LOG(INFO) << "This was already converted to full, so skipping."; | 1121 op_indexes, |
| 961 // Delete the temp node and pointer to it from old src | 1122 reverse_op_indexes, |
| 962 if (!(*graph)[cuts[i].old_src].out_edges.erase(cuts[i].new_vertex)) { | 1123 cuts_group)); |
| 963 LOG(INFO) << "Odd. node " << cuts[i].old_src << " didn't point to " | 1124 cuts_group.clear(); |
| 964 << cuts[i].new_vertex; | 1125 cuts_group.push_back(cuts[i]); |
| 965 } | |
| 966 (*graph)[cuts[i].new_vertex].valid = false; | |
| 967 vector<Vertex::Index>::size_type new_topo_idx = | |
| 968 (*reverse_op_indexes)[cuts[i].new_vertex]; | |
| 969 op_indexes->erase(op_indexes->begin() + new_topo_idx); | |
| 970 GenerateReverseTopoOrderMap(*op_indexes, reverse_op_indexes); | |
| 971 continue; | |
| 972 } | 1126 } |
| 973 bool found_node = false; | |
| 974 for (vector<Vertex::Index>::size_type j = (*reverse_op_indexes)[node] + 1, | |
| 975 je = op_indexes->size(); j < je; ++j) { | |
| 976 Vertex::Index test_node = (*op_indexes)[j]; | |
| 977 // See if this node has sufficient blocks | |
| 978 ExtentRanges ranges; | |
| 979 ranges.AddRepeatedExtents((*graph)[test_node].op.dst_extents()); | |
| 980 ranges.SubtractExtent(ExtentForRange( | |
| 981 kTempBlockStart, kSparseHole - kTempBlockStart)); | |
| 982 ranges.SubtractRepeatedExtents((*graph)[test_node].op.src_extents()); | |
| 983 // For now, for simplicity, subtract out all blocks in read-before | |
| 984 // dependencies. | |
| 985 for (Vertex::EdgeMap::const_iterator edge_i = | |
| 986 (*graph)[test_node].out_edges.begin(), | |
| 987 edge_e = (*graph)[test_node].out_edges.end(); | |
| 988 edge_i != edge_e; ++edge_i) { | |
| 989 ranges.SubtractExtents(edge_i->second.extents); | |
| 990 } | |
| 991 | 1127 |
| 992 uint64_t blocks_found = ranges.blocks(); | |
| 993 if (blocks_found < blocks_needed) { | |
| 994 if (blocks_found > 0) | |
| 995 LOG(INFO) << "insufficient blocks found in topo node " << j | |
| 996 << " (node " << (*op_indexes)[j] << "). Found only " | |
| 997 << blocks_found; | |
| 998 continue; | |
| 999 } | |
| 1000 found_node = true; | |
| 1001 LOG(INFO) << "Found sufficient blocks in topo node " << j | |
| 1002 << " (node " << (*op_indexes)[j] << ")"; | |
| 1003 // Sub in the blocks, and make the node supplying the blocks | |
| 1004 // depend on old_dst. | |
| 1005 vector<Extent> real_extents = | |
| 1006 ranges.GetExtentsForBlockCount(blocks_needed); | |
| 1007 | |
| 1008 // Fix the old dest node w/ the real blocks | |
| 1009 SubstituteBlocks(&(*graph)[node], | |
| 1010 cuts[i].tmp_extents, | |
| 1011 real_extents); | |
| 1012 | |
| 1013 // Fix the new node w/ the real blocks. Since the new node is just a | |
| 1014 // copy operation, we can replace all the dest extents w/ the real | |
| 1015 // blocks. | |
| 1016 DeltaArchiveManifest_InstallOperation *op = | |
| 1017 &(*graph)[cuts[i].new_vertex].op; | |
| 1018 op->clear_dst_extents(); | |
| 1019 StoreExtents(real_extents, op->mutable_dst_extents()); | |
| 1020 | |
| 1021 // Add an edge from the real-block supplier to the old dest block. | |
| 1022 graph_utils::AddReadBeforeDepExtents(&(*graph)[test_node], | |
| 1023 node, | |
| 1024 real_extents); | |
| 1025 break; | |
| 1026 } | |
| 1027 if (!found_node) { | |
| 1028 // convert to full op | |
| 1029 LOG(WARNING) << "Failed to find enough temp blocks for cut " << i | |
| 1030 << " with old dest (graph node " << node | |
| 1031 << "). Converting to a full op, at the expense of a " | |
| 1032 << "good compression ratio."; | |
| 1033 TEST_AND_RETURN_FALSE(ConvertCutToFullOp(graph, | |
| 1034 cuts[i], | |
| 1035 new_root, | |
| 1036 data_fd, | |
| 1037 data_file_size)); | |
| 1038 // move the full op to the back | |
| 1039 vector<Vertex::Index> new_op_indexes; | |
| 1040 for (vector<Vertex::Index>::const_iterator iter_i = op_indexes->begin(), | |
| 1041 iter_e = op_indexes->end(); iter_i != iter_e; ++iter_i) { | |
| 1042 if ((*iter_i == cuts[i].old_dst) || (*iter_i == cuts[i].new_vertex)) | |
| 1043 continue; | |
| 1044 new_op_indexes.push_back(*iter_i); | |
| 1045 } | |
| 1046 new_op_indexes.push_back(cuts[i].old_dst); | |
| 1047 op_indexes->swap(new_op_indexes); | |
| 1048 | |
| 1049 GenerateReverseTopoOrderMap(*op_indexes, reverse_op_indexes); | |
| 1050 } | |
| 1051 if (i == e) { | 1128 if (i == e) { |
| 1052 // break out of for() loop | 1129 // break out of for() loop |
| 1053 break; | 1130 break; |
| 1054 } | 1131 } |
| 1055 } | 1132 } |
| 1133 CHECK(!cuts_group.empty()); | |
| 1134 TEST_AND_RETURN_FALSE(AssignBlockForAdjoiningCuts(graph, | |
| 1135 new_root, | |
| 1136 data_fd, | |
| 1137 data_file_size, | |
| 1138 op_indexes, | |
| 1139 reverse_op_indexes, | |
| 1140 cuts_group)); | |
| 1056 return true; | 1141 return true; |
| 1057 } | 1142 } |
| 1058 | 1143 |
| 1059 bool DeltaDiffGenerator::NoTempBlocksRemain(const Graph& graph) { | 1144 bool DeltaDiffGenerator::NoTempBlocksRemain(const Graph& graph) { |
| 1060 size_t idx = 0; | 1145 size_t idx = 0; |
| 1061 for (Graph::const_iterator it = graph.begin(), e = graph.end(); it != e; | 1146 for (Graph::const_iterator it = graph.begin(), e = graph.end(); it != e; |
| 1062 ++it, ++idx) { | 1147 ++it, ++idx) { |
| 1063 if (!it->valid) | 1148 if (!it->valid) |
| 1064 continue; | 1149 continue; |
| 1065 const DeltaArchiveManifest_InstallOperation& op = it->op; | 1150 const DeltaArchiveManifest_InstallOperation& op = it->op; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1125 } | 1210 } |
| 1126 | 1211 |
| 1127 bool DeltaDiffGenerator::ConvertCutToFullOp(Graph* graph, | 1212 bool DeltaDiffGenerator::ConvertCutToFullOp(Graph* graph, |
| 1128 const CutEdgeVertexes& cut, | 1213 const CutEdgeVertexes& cut, |
| 1129 const string& new_root, | 1214 const string& new_root, |
| 1130 int data_fd, | 1215 int data_fd, |
| 1131 off_t* data_file_size) { | 1216 off_t* data_file_size) { |
| 1132 // Drop all incoming edges, keep all outgoing edges | 1217 // Drop all incoming edges, keep all outgoing edges |
| 1133 | 1218 |
| 1134 // Keep all outgoing edges | 1219 // Keep all outgoing edges |
| 1135 Vertex::EdgeMap out_edges = (*graph)[cut.old_dst].out_edges; | 1220 if ((*graph)[cut.old_dst].op.type() != |
| 1136 graph_utils::DropWriteBeforeDeps(&out_edges); | 1221 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ && |
| 1222 (*graph)[cut.old_dst].op.type() != | |
| 1223 DeltaArchiveManifest_InstallOperation_Type_REPLACE) { | |
| 1224 Vertex::EdgeMap out_edges = (*graph)[cut.old_dst].out_edges; | |
| 1225 graph_utils::DropWriteBeforeDeps(&out_edges); | |
| 1137 | 1226 |
| 1138 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, | 1227 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, |
| 1139 cut.old_dst, | 1228 cut.old_dst, |
| 1140 NULL, | 1229 NULL, |
| 1141 "/-!@:&*nonexistent_path", | 1230 "/-!@:&*nonexistent_path", |
| 1142 new_root, | 1231 new_root, |
| 1143 (*graph)[cut.old_dst].file_name, | 1232 (*graph)[cut.old_dst].file_name, |
| 1144 data_fd, | 1233 data_fd, |
| 1145 data_file_size)); | 1234 data_file_size)); |
| 1146 | 1235 |
| 1147 (*graph)[cut.old_dst].out_edges = out_edges; | 1236 (*graph)[cut.old_dst].out_edges = out_edges; |
| 1148 | 1237 |
| 1149 // Right now we don't have doubly-linked edges, so we have to scan | 1238 // Right now we don't have doubly-linked edges, so we have to scan |
| 1150 // the whole graph. | 1239 // the whole graph. |
| 1151 graph_utils::DropIncomingEdgesTo(graph, cut.old_dst); | 1240 graph_utils::DropIncomingEdgesTo(graph, cut.old_dst); |
| 1241 } | |
| 1152 | 1242 |
| 1153 // Delete temp node | 1243 // Delete temp node |
| 1154 (*graph)[cut.old_src].out_edges.erase(cut.new_vertex); | 1244 (*graph)[cut.old_src].out_edges.erase(cut.new_vertex); |
| 1155 CHECK((*graph)[cut.old_dst].out_edges.find(cut.new_vertex) == | 1245 CHECK((*graph)[cut.old_dst].out_edges.find(cut.new_vertex) == |
| 1156 (*graph)[cut.old_dst].out_edges.end()); | 1246 (*graph)[cut.old_dst].out_edges.end()); |
| 1157 (*graph)[cut.new_vertex].valid = false; | 1247 (*graph)[cut.new_vertex].valid = false; |
| 1248 LOG(INFO) << "marked node invalid: " << cut.new_vertex; | |
| 1158 return true; | 1249 return true; |
| 1159 } | 1250 } |
| 1160 | 1251 |
| 1161 bool DeltaDiffGenerator::ConvertGraphToDag(Graph* graph, | 1252 bool DeltaDiffGenerator::ConvertGraphToDag(Graph* graph, |
| 1162 const string& new_root, | 1253 const string& new_root, |
| 1163 int fd, | 1254 int fd, |
| 1164 off_t* data_file_size, | 1255 off_t* data_file_size, |
| 1165 vector<Vertex::Index>* final_order) { | 1256 vector<Vertex::Index>* final_order) { |
| 1166 CycleBreaker cycle_breaker; | 1257 CycleBreaker cycle_breaker; |
| 1167 LOG(INFO) << "Finding cycles..."; | 1258 LOG(INFO) << "Finding cycles..."; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1184 LOG(INFO) << "done with initial topo order"; | 1275 LOG(INFO) << "done with initial topo order"; |
| 1185 CheckGraph(*graph); | 1276 CheckGraph(*graph); |
| 1186 | 1277 |
| 1187 LOG(INFO) << "Moving full ops to the back"; | 1278 LOG(INFO) << "Moving full ops to the back"; |
| 1188 MoveFullOpsToBack(graph, final_order); | 1279 MoveFullOpsToBack(graph, final_order); |
| 1189 LOG(INFO) << "done moving full ops to back"; | 1280 LOG(INFO) << "done moving full ops to back"; |
| 1190 | 1281 |
| 1191 vector<vector<Vertex::Index>::size_type> inverse_final_order; | 1282 vector<vector<Vertex::Index>::size_type> inverse_final_order; |
| 1192 GenerateReverseTopoOrderMap(*final_order, &inverse_final_order); | 1283 GenerateReverseTopoOrderMap(*final_order, &inverse_final_order); |
| 1193 | 1284 |
| 1285 SortCutsByTopoOrder(*final_order, &cuts); | |
| 1286 | |
| 1194 if (!cuts.empty()) | 1287 if (!cuts.empty()) |
| 1195 TEST_AND_RETURN_FALSE(AssignTempBlocks(graph, | 1288 TEST_AND_RETURN_FALSE(AssignTempBlocks(graph, |
| 1196 new_root, | 1289 new_root, |
| 1197 fd, | 1290 fd, |
| 1198 data_file_size, | 1291 data_file_size, |
| 1199 final_order, | 1292 final_order, |
| 1200 &inverse_final_order, | 1293 &inverse_final_order, |
| 1201 cuts)); | 1294 cuts)); |
| 1202 LOG(INFO) << "Making sure all temp blocks have been allocated"; | 1295 LOG(INFO) << "Making sure all temp blocks have been allocated"; |
| 1296 | |
| 1203 graph_utils::DumpGraph(*graph); | 1297 graph_utils::DumpGraph(*graph); |
| 1204 CHECK(NoTempBlocksRemain(*graph)); | 1298 CHECK(NoTempBlocksRemain(*graph)); |
| 1205 LOG(INFO) << "done making sure all temp blocks are allocated"; | 1299 LOG(INFO) << "done making sure all temp blocks are allocated"; |
| 1206 return true; | 1300 return true; |
| 1207 } | 1301 } |
| 1208 | 1302 |
| 1209 bool DeltaDiffGenerator::ReadFullUpdateFromDisk( | 1303 bool DeltaDiffGenerator::ReadFullUpdateFromDisk( |
| 1210 Graph* graph, | 1304 Graph* graph, |
| 1211 const std::string& new_kernel_part, | 1305 const std::string& new_kernel_part, |
| 1212 const std::string& new_image, | 1306 const std::string& new_image, |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1416 { | 1510 { |
| 1417 for (int i = 0; i < (manifest.install_operations_size() + | 1511 for (int i = 0; i < (manifest.install_operations_size() + |
| 1418 manifest.kernel_install_operations_size()); i++) { | 1512 manifest.kernel_install_operations_size()); i++) { |
| 1419 DeltaArchiveManifest_InstallOperation* op = | 1513 DeltaArchiveManifest_InstallOperation* op = |
| 1420 i < manifest.install_operations_size() ? | 1514 i < manifest.install_operations_size() ? |
| 1421 manifest.mutable_install_operations(i) : | 1515 manifest.mutable_install_operations(i) : |
| 1422 manifest.mutable_kernel_install_operations( | 1516 manifest.mutable_kernel_install_operations( |
| 1423 i - manifest.install_operations_size()); | 1517 i - manifest.install_operations_size()); |
| 1424 if (op->has_data_offset()) { | 1518 if (op->has_data_offset()) { |
| 1425 if (op->data_offset() != next_blob_offset) { | 1519 if (op->data_offset() != next_blob_offset) { |
| 1426 LOG(FATAL) << "bad blob offset! " << op->data_offset() << " != " | 1520 LOG(WARNING) << "bad blob offset! " << op->data_offset() << " != " |
|
petkov
2010/10/23 04:52:52
why is this not FATAL any more?
| |
| 1427 << next_blob_offset; | 1521 << next_blob_offset; |
| 1428 } | 1522 } |
| 1429 next_blob_offset += op->data_length(); | 1523 next_blob_offset += op->data_length(); |
| 1430 } | 1524 } |
| 1431 } | 1525 } |
| 1432 } | 1526 } |
| 1433 | 1527 |
| 1434 // Signatures appear at the end of the blobs. Note the offset in the | 1528 // Signatures appear at the end of the blobs. Note the offset in the |
| 1435 // manifest | 1529 // manifest |
| 1436 if (!private_key_path.empty()) { | 1530 if (!private_key_path.empty()) { |
| 1437 LOG(INFO) << "Making room for signature in file"; | 1531 LOG(INFO) << "Making room for signature in file"; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1528 | 1622 |
| 1529 LOG(INFO) << "All done. Successfully created delta file."; | 1623 LOG(INFO) << "All done. Successfully created delta file."; |
| 1530 return true; | 1624 return true; |
| 1531 } | 1625 } |
| 1532 | 1626 |
| 1533 const char* const kBsdiffPath = "/usr/bin/bsdiff"; | 1627 const char* const kBsdiffPath = "/usr/bin/bsdiff"; |
| 1534 const char* const kBspatchPath = "/usr/bin/bspatch"; | 1628 const char* const kBspatchPath = "/usr/bin/bspatch"; |
| 1535 const char* const kDeltaMagic = "CrAU"; | 1629 const char* const kDeltaMagic = "CrAU"; |
| 1536 | 1630 |
| 1537 }; // namespace chromeos_update_engine | 1631 }; // namespace chromeos_update_engine |
| OLD | NEW |