|
9 | 9 | #include "midx.h"
|
10 | 10 | #include "progress.h"
|
11 | 11 | #include "trace2.h"
|
| 12 | +#include "run-command.h" |
12 | 13 |
|
13 | 14 | #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
|
14 | 15 | #define MIDX_VERSION 1
|
@@ -1227,7 +1228,155 @@ int expire_midx_packs(struct repository *r, const char *object_dir)
|
1227 | 1228 | return result;
|
1228 | 1229 | }
|
1229 | 1230 |
|
1230 |
| -int midx_repack(struct repository *r, const char *object_dir, size_t batch_size) |
| 1231 | +struct repack_info { |
| 1232 | + timestamp_t mtime; |
| 1233 | + uint32_t referenced_objects; |
| 1234 | + uint32_t pack_int_id; |
| 1235 | +}; |
| 1236 | + |
| 1237 | +static int compare_by_mtime(const void *a_, const void *b_) |
1231 | 1238 | {
|
| 1239 | + const struct repack_info *a, *b; |
| 1240 | + |
| 1241 | + a = (const struct repack_info *)a_; |
| 1242 | + b = (const struct repack_info *)b_; |
| 1243 | + |
| 1244 | + if (a->mtime < b->mtime) |
| 1245 | + return -1; |
| 1246 | + if (a->mtime > b->mtime) |
| 1247 | + return 1; |
| 1248 | + return 0; |
| 1249 | +} |
| 1250 | + |
| 1251 | +static int fill_included_packs_all(struct multi_pack_index *m, |
| 1252 | + unsigned char *include_pack) |
| 1253 | +{ |
| 1254 | + uint32_t i; |
| 1255 | + |
| 1256 | + for (i = 0; i < m->num_packs; i++) |
| 1257 | + include_pack[i] = 1; |
| 1258 | + |
| 1259 | + return m->num_packs < 2; |
| 1260 | +} |
| 1261 | + |
| 1262 | +static int fill_included_packs_batch(struct repository *r, |
| 1263 | + struct multi_pack_index *m, |
| 1264 | + unsigned char *include_pack, |
| 1265 | + size_t batch_size) |
| 1266 | +{ |
| 1267 | + uint32_t i, packs_to_repack; |
| 1268 | + size_t total_size; |
| 1269 | + struct repack_info *pack_info = xcalloc(m->num_packs, sizeof(struct repack_info)); |
| 1270 | + |
| 1271 | + for (i = 0; i < m->num_packs; i++) { |
| 1272 | + pack_info[i].pack_int_id = i; |
| 1273 | + |
| 1274 | + if (prepare_midx_pack(r, m, i)) |
| 1275 | + continue; |
| 1276 | + |
| 1277 | + pack_info[i].mtime = m->packs[i]->mtime; |
| 1278 | + } |
| 1279 | + |
| 1280 | + for (i = 0; batch_size && i < m->num_objects; i++) { |
| 1281 | + uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); |
| 1282 | + pack_info[pack_int_id].referenced_objects++; |
| 1283 | + } |
| 1284 | + |
| 1285 | + QSORT(pack_info, m->num_packs, compare_by_mtime); |
| 1286 | + |
| 1287 | + total_size = 0; |
| 1288 | + packs_to_repack = 0; |
| 1289 | + for (i = 0; total_size < batch_size && i < m->num_packs; i++) { |
| 1290 | + int pack_int_id = pack_info[i].pack_int_id; |
| 1291 | + struct packed_git *p = m->packs[pack_int_id]; |
| 1292 | + size_t expected_size; |
| 1293 | + |
| 1294 | + if (!p) |
| 1295 | + continue; |
| 1296 | + if (open_pack_index(p) || !p->num_objects) |
| 1297 | + continue; |
| 1298 | + |
| 1299 | + expected_size = (size_t)(p->pack_size |
| 1300 | + * pack_info[i].referenced_objects); |
| 1301 | + expected_size /= p->num_objects; |
| 1302 | + |
| 1303 | + if (expected_size >= batch_size) |
| 1304 | + continue; |
| 1305 | + |
| 1306 | + packs_to_repack++; |
| 1307 | + total_size += expected_size; |
| 1308 | + include_pack[pack_int_id] = 1; |
| 1309 | + } |
| 1310 | + |
| 1311 | + free(pack_info); |
| 1312 | + |
| 1313 | + if (total_size < batch_size || packs_to_repack < 2) |
| 1314 | + return 1; |
| 1315 | + |
1232 | 1316 | return 0;
|
1233 | 1317 | }
|
| 1318 | + |
| 1319 | +int midx_repack(struct repository *r, const char *object_dir, size_t batch_size) |
| 1320 | +{ |
| 1321 | + int result = 0; |
| 1322 | + uint32_t i; |
| 1323 | + unsigned char *include_pack; |
| 1324 | + struct child_process cmd = CHILD_PROCESS_INIT; |
| 1325 | + struct strbuf base_name = STRBUF_INIT; |
| 1326 | + struct multi_pack_index *m = load_multi_pack_index(object_dir, 1); |
| 1327 | + |
| 1328 | + if (!m) |
| 1329 | + return 0; |
| 1330 | + |
| 1331 | + include_pack = xcalloc(m->num_packs, sizeof(unsigned char)); |
| 1332 | + |
| 1333 | + if (batch_size) { |
| 1334 | + if (fill_included_packs_batch(r, m, include_pack, batch_size)) |
| 1335 | + goto cleanup; |
| 1336 | + } else if (fill_included_packs_all(m, include_pack)) |
| 1337 | + goto cleanup; |
| 1338 | + |
| 1339 | + argv_array_push(&cmd.args, "pack-objects"); |
| 1340 | + |
| 1341 | + strbuf_addstr(&base_name, object_dir); |
| 1342 | + strbuf_addstr(&base_name, "/pack/pack"); |
| 1343 | + argv_array_push(&cmd.args, base_name.buf); |
| 1344 | + strbuf_release(&base_name); |
| 1345 | + |
| 1346 | + cmd.git_cmd = 1; |
| 1347 | + cmd.in = cmd.out = -1; |
| 1348 | + |
| 1349 | + if (start_command(&cmd)) { |
| 1350 | + error(_("could not start pack-objects")); |
| 1351 | + result = 1; |
| 1352 | + goto cleanup; |
| 1353 | + } |
| 1354 | + |
| 1355 | + for (i = 0; i < m->num_objects; i++) { |
| 1356 | + struct object_id oid; |
| 1357 | + uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); |
| 1358 | + |
| 1359 | + if (!include_pack[pack_int_id]) |
| 1360 | + continue; |
| 1361 | + |
| 1362 | + nth_midxed_object_oid(&oid, m, i); |
| 1363 | + xwrite(cmd.in, oid_to_hex(&oid), the_hash_algo->hexsz); |
| 1364 | + xwrite(cmd.in, "\n", 1); |
| 1365 | + } |
| 1366 | + close(cmd.in); |
| 1367 | + |
| 1368 | + if (finish_command(&cmd)) { |
| 1369 | + error(_("could not finish pack-objects")); |
| 1370 | + result = 1; |
| 1371 | + goto cleanup; |
| 1372 | + } |
| 1373 | + |
| 1374 | + result = write_midx_internal(object_dir, m, NULL); |
| 1375 | + m = NULL; |
| 1376 | + |
| 1377 | +cleanup: |
| 1378 | + if (m) |
| 1379 | + close_midx(m); |
| 1380 | + free(include_pack); |
| 1381 | + return result; |
| 1382 | +} |
0 commit comments