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 |