Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: delta_diff_generator.cc

Issue 3550020: AU: support for generating new style full updates. (Closed) Base URL: ssh://git@chromiumos-git/update_engine.git
Patch Set: fixes for review Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « delta_diff_generator.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <sys/stat.h> 10 #include <sys/stat.h>
10 #include <sys/types.h> 11 #include <sys/types.h>
11 12
12 #include <algorithm> 13 #include <algorithm>
13 #include <map> 14 #include <map>
14 #include <set> 15 #include <set>
15 #include <string> 16 #include <string>
16 #include <utility> 17 #include <utility>
17 #include <vector> 18 #include <vector>
18 19
(...skipping 21 matching lines...) Expand all
40 using std::min; 41 using std::min;
41 using std::set; 42 using std::set;
42 using std::string; 43 using std::string;
43 using std::vector; 44 using std::vector;
44 45
45 namespace chromeos_update_engine { 46 namespace chromeos_update_engine {
46 47
47 typedef DeltaDiffGenerator::Block Block; 48 typedef DeltaDiffGenerator::Block Block;
48 49
49 namespace { 50 namespace {
50 const size_t kBlockSize = 4096; 51 const size_t kBlockSize = 4096; // bytes
51 const size_t kRootFSPartitionSize = 1 * 1024 * 1024 * 1024; // 1 GiB 52 const size_t kRootFSPartitionSize = 1 * 1024 * 1024 * 1024; // 1 GiB
52 const uint64_t kVersionNumber = 1; 53 const uint64_t kVersionNumber = 1;
54 const uint64_t kFullUpdateChunkSize = 128 * 1024; // bytes
53 55
54 // Stores all Extents for a file into 'out'. Returns true on success. 56 // Stores all Extents for a file into 'out'. Returns true on success.
55 bool GatherExtents(const string& path, 57 bool GatherExtents(const string& path,
56 google::protobuf::RepeatedPtrField<Extent>* out) { 58 google::protobuf::RepeatedPtrField<Extent>* out) {
57 vector<Extent> extents; 59 vector<Extent> extents;
58 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents)); 60 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents));
59 DeltaDiffGenerator::StoreExtents(extents, out); 61 DeltaDiffGenerator::StoreExtents(extents, out);
60 return true; 62 return true;
61 } 63 }
62 64
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 final_order, 1114 final_order,
1113 &inverse_final_order, 1115 &inverse_final_order,
1114 cuts)); 1116 cuts));
1115 LOG(INFO) << "Making sure all temp blocks have been allocated"; 1117 LOG(INFO) << "Making sure all temp blocks have been allocated";
1116 graph_utils::DumpGraph(*graph); 1118 graph_utils::DumpGraph(*graph);
1117 CHECK(NoTempBlocksRemain(*graph)); 1119 CHECK(NoTempBlocksRemain(*graph));
1118 LOG(INFO) << "done making sure all temp blocks are allocated"; 1120 LOG(INFO) << "done making sure all temp blocks are allocated";
1119 return true; 1121 return true;
1120 } 1122 }
1121 1123
1124 bool DeltaDiffGenerator::ReadFullUpdateFromDisk(
1125 Graph* graph,
1126 const std::string& new_kernel_part,
1127 const std::string& new_image,
1128 int fd,
1129 off_t* data_file_size,
1130 off_t chunk_size,
1131 vector<DeltaArchiveManifest_InstallOperation>* kernel_ops,
1132 std::vector<Vertex::Index>* final_order) {
1133 TEST_AND_RETURN_FALSE(chunk_size > 0);
1134 TEST_AND_RETURN_FALSE((chunk_size % kBlockSize) == 0);
1135
1136 // Get the sizes early in the function, so we can fail fast if the user
1137 // passed us bad paths.
1138 const off_t image_size = utils::FileSize(new_image);
1139 TEST_AND_RETURN_FALSE(image_size >= 0);
1140 const off_t kernel_size = utils::FileSize(new_kernel_part);
1141 TEST_AND_RETURN_FALSE(kernel_size >= 0);
1142
1143 off_t part_sizes[] = { image_size, kernel_size };
1144 string paths[] = { new_image, new_kernel_part };
1145
1146 for (int partition = 0; partition < 2; ++partition) {
1147 const string& path = paths[partition];
1148 LOG(INFO) << "compressing " << path;
1149
1150 int in_fd = open(path.c_str(), O_RDONLY, 0);
1151 TEST_AND_RETURN_FALSE(in_fd >= 0);
1152 ScopedFdCloser in_fd_closer(&in_fd);
1153
1154 for (off_t bytes_left = part_sizes[partition], counter = 0, offset = 0;
1155 bytes_left > 0;
1156 bytes_left -= chunk_size, ++counter, offset += chunk_size) {
1157 LOG(INFO) << "offset = " << offset;
1158 DeltaArchiveManifest_InstallOperation* op = NULL;
1159 if (partition == 0) {
1160 graph->resize(graph->size() + 1);
1161 graph->back().file_name = path + StringPrintf("-%" PRIi64, counter);
1162 op = &graph->back().op;
1163 final_order->push_back(graph->size() - 1);
1164 } else {
1165 kernel_ops->resize(kernel_ops->size() + 1);
1166 op = &kernel_ops->back();
1167 }
1168 LOG(INFO) << "have an op";
1169
1170 vector<char> buf(min(bytes_left, chunk_size));
1171 LOG(INFO) << "buf size: " << buf.size();
1172 ssize_t bytes_read = -1;
1173
1174 TEST_AND_RETURN_FALSE(utils::PReadAll(
1175 in_fd, &buf[0], buf.size(), offset, &bytes_read));
1176 TEST_AND_RETURN_FALSE(bytes_read == static_cast<ssize_t>(buf.size()));
1177
1178 vector<char> buf_compressed;
1179
1180 TEST_AND_RETURN_FALSE(BzipCompress(buf, &buf_compressed));
1181 const bool compress = buf_compressed.size() < buf.size();
1182 const vector<char>& use_buf = compress ? buf_compressed : buf;
1183 if (compress) {
1184 op->set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
1185 } else {
1186 op->set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE);
1187 }
1188 op->set_data_offset(*data_file_size);
1189 *data_file_size += use_buf.size();
1190 op->set_data_length(use_buf.size());
1191 Extent* dst_extent = op->add_dst_extents();
1192 dst_extent->set_start_block(offset / kBlockSize);
1193 dst_extent->set_num_blocks(chunk_size / kBlockSize);
1194 }
1195 }
1196
1197 return true;
1198 }
1199
1122 bool DeltaDiffGenerator::GenerateDeltaUpdateFile( 1200 bool DeltaDiffGenerator::GenerateDeltaUpdateFile(
1123 const string& old_root, 1201 const string& old_root,
1124 const string& old_image, 1202 const string& old_image,
1125 const string& new_root, 1203 const string& new_root,
1126 const string& new_image, 1204 const string& new_image,
1127 const string& old_kernel_part, 1205 const string& old_kernel_part,
1128 const string& new_kernel_part, 1206 const string& new_kernel_part,
1129 const string& output_path, 1207 const string& output_path,
1130 const string& private_key_path) { 1208 const string& private_key_path) {
1131 struct stat old_image_stbuf; 1209 struct stat old_image_stbuf;
1132 TEST_AND_RETURN_FALSE_ERRNO(stat(old_image.c_str(), &old_image_stbuf) == 0);
1133 struct stat new_image_stbuf; 1210 struct stat new_image_stbuf;
1134 TEST_AND_RETURN_FALSE_ERRNO(stat(new_image.c_str(), &new_image_stbuf) == 0); 1211 TEST_AND_RETURN_FALSE_ERRNO(stat(new_image.c_str(), &new_image_stbuf) == 0);
1135 LOG_IF(WARNING, new_image_stbuf.st_size != old_image_stbuf.st_size) 1212 if (!old_image.empty()) {
1136 << "Old and new images are different sizes."; 1213 TEST_AND_RETURN_FALSE_ERRNO(stat(old_image.c_str(), &old_image_stbuf) == 0);
1214 LOG_IF(WARNING, new_image_stbuf.st_size != old_image_stbuf.st_size)
1215 << "Old and new images are different sizes.";
1216 LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize)
1217 << "Old image not a multiple of block size " << kBlockSize;
1218 // Sanity check kernel partition arg
1219 TEST_AND_RETURN_FALSE(utils::FileSize(old_kernel_part) >= 0);
1220 } else {
1221 old_image_stbuf.st_size = 0;
1222 }
1137 LOG_IF(FATAL, new_image_stbuf.st_size % kBlockSize) 1223 LOG_IF(FATAL, new_image_stbuf.st_size % kBlockSize)
1138 << "New image not a multiple of block size " << kBlockSize; 1224 << "New image not a multiple of block size " << kBlockSize;
1139 LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize)
1140 << "Old image not a multiple of block size " << kBlockSize;
1141 1225
1142 // Sanity check kernel partition args 1226 // Sanity check kernel partition arg
1143 TEST_AND_RETURN_FALSE(utils::FileSize(old_kernel_part) >= 0);
1144 TEST_AND_RETURN_FALSE(utils::FileSize(new_kernel_part) >= 0); 1227 TEST_AND_RETURN_FALSE(utils::FileSize(new_kernel_part) >= 0);
1145 1228
1146 vector<Block> blocks(max(old_image_stbuf.st_size / kBlockSize, 1229 vector<Block> blocks(max(old_image_stbuf.st_size / kBlockSize,
1147 new_image_stbuf.st_size / kBlockSize)); 1230 new_image_stbuf.st_size / kBlockSize));
1148 LOG(INFO) << "invalid: " << Vertex::kInvalidIndex; 1231 LOG(INFO) << "invalid: " << Vertex::kInvalidIndex;
1149 LOG(INFO) << "len: " << blocks.size(); 1232 LOG(INFO) << "len: " << blocks.size();
1150 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) { 1233 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) {
1151 CHECK(blocks[i].reader == Vertex::kInvalidIndex); 1234 CHECK(blocks[i].reader == Vertex::kInvalidIndex);
1152 CHECK(blocks[i].writer == Vertex::kInvalidIndex); 1235 CHECK(blocks[i].writer == Vertex::kInvalidIndex);
1153 } 1236 }
1154 Graph graph; 1237 Graph graph;
1155 CheckGraph(graph); 1238 CheckGraph(graph);
1156 1239
1157 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX"); 1240 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX");
1158 string temp_file_path; 1241 string temp_file_path;
1159 off_t data_file_size = 0; 1242 off_t data_file_size = 0;
1160 1243
1161 LOG(INFO) << "Reading files..."; 1244 LOG(INFO) << "Reading files...";
1162 1245
1163 vector<DeltaArchiveManifest_InstallOperation> kernel_ops; 1246 vector<DeltaArchiveManifest_InstallOperation> kernel_ops;
1164 1247
1165 vector<Vertex::Index> final_order; 1248 vector<Vertex::Index> final_order;
1166 { 1249 if (!old_image.empty()) {
1250 // Delta update
1167 int fd; 1251 int fd;
1168 TEST_AND_RETURN_FALSE( 1252 TEST_AND_RETURN_FALSE(
1169 utils::MakeTempFile(kTempFileTemplate, &temp_file_path, &fd)); 1253 utils::MakeTempFile(kTempFileTemplate, &temp_file_path, &fd));
1170 TEST_AND_RETURN_FALSE(fd >= 0); 1254 TEST_AND_RETURN_FALSE(fd >= 0);
1171 ScopedFdCloser fd_closer(&fd); 1255 ScopedFdCloser fd_closer(&fd);
1172 1256
1173 TEST_AND_RETURN_FALSE(DeltaReadFiles(&graph, 1257 TEST_AND_RETURN_FALSE(DeltaReadFiles(&graph,
1174 &blocks, 1258 &blocks,
1175 old_root, 1259 old_root,
1176 new_root, 1260 new_root,
(...skipping 22 matching lines...) Expand all
1199 LOG(INFO) << "Creating edges..."; 1283 LOG(INFO) << "Creating edges...";
1200 CreateEdges(&graph, blocks); 1284 CreateEdges(&graph, blocks);
1201 LOG(INFO) << "Done creating edges"; 1285 LOG(INFO) << "Done creating edges";
1202 CheckGraph(graph); 1286 CheckGraph(graph);
1203 1287
1204 TEST_AND_RETURN_FALSE(ConvertGraphToDag(&graph, 1288 TEST_AND_RETURN_FALSE(ConvertGraphToDag(&graph,
1205 new_root, 1289 new_root,
1206 fd, 1290 fd,
1207 &data_file_size, 1291 &data_file_size,
1208 &final_order)); 1292 &final_order));
1293 } else {
1294 // Full update
1295 int fd = 0;
1296 TEST_AND_RETURN_FALSE(ReadFullUpdateFromDisk(&graph,
1297 new_kernel_part,
1298 new_image,
1299 fd,
1300 &data_file_size,
1301 kFullUpdateChunkSize,
1302 &kernel_ops,
1303 &final_order));
1209 } 1304 }
1210 1305
1211 // Convert to protobuf Manifest object 1306 // Convert to protobuf Manifest object
1212 DeltaArchiveManifest manifest; 1307 DeltaArchiveManifest manifest;
1213 CheckGraph(graph); 1308 CheckGraph(graph);
1214 InstallOperationsToManifest(graph, final_order, kernel_ops, &manifest); 1309 InstallOperationsToManifest(graph, final_order, kernel_ops, &manifest);
1215 1310
1216 CheckGraph(graph); 1311 CheckGraph(graph);
1217 manifest.set_block_size(kBlockSize); 1312 manifest.set_block_size(kBlockSize);
1218 1313
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1350 1445
1351 LOG(INFO) << "All done. Successfully created delta file."; 1446 LOG(INFO) << "All done. Successfully created delta file.";
1352 return true; 1447 return true;
1353 } 1448 }
1354 1449
1355 const char* const kBsdiffPath = "/usr/bin/bsdiff"; 1450 const char* const kBsdiffPath = "/usr/bin/bsdiff";
1356 const char* const kBspatchPath = "/usr/bin/bspatch"; 1451 const char* const kBspatchPath = "/usr/bin/bspatch";
1357 const char* const kDeltaMagic = "CrAU"; 1452 const char* const kDeltaMagic = "CrAU";
1358 1453
1359 }; // namespace chromeos_update_engine 1454 }; // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « delta_diff_generator.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698