commit-graph: add a slab to store topological levels

In a later commit we will introduce corrected commit date as the generation number v2. Corrected commit dates will be stored in the new seperate Generation Data chunk. However, to ensure backwards compatibility with "Old" Git we need to continue to write generation number v1 (topological levels) to the commit data chunk. Thus, we need to compute and store both versions of generation numbers to write the commit-graph file. Therefore, let's introduce a commit-slab `topo_level_slab` to store topological levels; corrected commit date will be stored in the member `generation` of struct commit_graph_data. The macros `GENERATION_NUMBER_INFINITY` and `GENERATION_NUMBER_ZERO` mark commits not in the commit-graph file and commits written by a version of Git that did not compute generation numbers respectively. Generation numbers are computed identically for both kinds of commits. A "slab-miss" should return `GENERATION_NUMBER_INFINITY` as the commit is not in the commit-graph file. However, since the slab is zero-initialized, it returns 0 (or rather `GENERATION_NUMBER_ZERO`). Thus, we no longer need to check if the topological level of a commit is `GENERATION_NUMBER_INFINITY`. We will add a pointer to the slab in `struct write_commit_graph_context` and `struct commit_graph` to populate the slab in `fill_commit_graph_info` if the commit has a pre-computed topological level as in case of split commit-graphs. Signed-off-by: Abhishek Kumar <abhishekkumar8222@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Reviewed-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Abhishek Kumar committed Jan 16, 2021 at 18:11 UTC 72a2bfcaf01860ce8dd6921490d903dc0ad59c89
2 files changed +31 -15
commit-graph.c
+30 -15
@@ -64,6 +64,8 @@ void git_test_write_commit_graph_or_die(void)
64 /* Remember to update object flag allocation in object.h */
65 #define REACHABLE (1u<<15)
66
67 +define_commit_slab(topo_level_slab, uint32_t);
68 +
69 /* Keep track of the order in which commits are added to our list. */
70 define_commit_slab(commit_pos, int);
71 static struct commit_pos commit_pos = COMMIT_SLAB_INIT(1, commit_pos);
@@ -772,6 +774,9 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g,
774 item->date = (timestamp_t)((date_high << 32) | date_low);
775
776 graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
777 +
778 + if (g->topo_levels)
779 + *topo_level_slab_at(g->topo_levels, item) = get_be32(commit_data + g->hash_len + 8) >> 2;
780 }
781
782 static inline void set_commit_tree(struct commit *c, struct tree *t)
@@ -960,6 +965,7 @@ struct write_commit_graph_context {
965 changed_paths:1,
966 order_by_pack:1;
967
968 + struct topo_level_slab *topo_levels;
969 const struct commit_graph_opts *opts;
970 size_t total_bloom_filter_data_size;
971 const struct bloom_filter_settings *bloom_settings;
@@ -1106,7 +1112,7 @@ static int write_graph_chunk_data(struct hashfile *f,
1112 else
1113 packedDate[0] = 0;
1114
1109 - packedDate[0] |= htonl(commit_graph_data_at(*list)->generation << 2);
1115 + packedDate[0] |= htonl(*topo_level_slab_at(ctx->topo_levels, *list) << 2);
1116
1117 packedDate[1] = htonl((*list)->date);
1118 hashwrite(f, packedDate, 8);
@@ -1336,11 +1342,10 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1342 _("Computing commit graph generation numbers"),
1343 ctx->commits.nr);
1344 for (i = 0; i < ctx->commits.nr; i++) {
1339 - uint32_t generation = commit_graph_data_at(ctx->commits.list[i])->generation;
1345 + uint32_t level = *topo_level_slab_at(ctx->topo_levels, ctx->commits.list[i]);
1346
1347 display_progress(ctx->progress, i + 1);
1342 - if (generation != GENERATION_NUMBER_INFINITY &&
1343 - generation != GENERATION_NUMBER_ZERO)
1348 + if (level != GENERATION_NUMBER_ZERO)
1349 continue;
1350
1351 commit_list_insert(ctx->commits.list[i], &list);
@@ -1348,29 +1353,26 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1353 struct commit *current = list->item;
1354 struct commit_list *parent;
1355 int all_parents_computed = 1;
1351 - uint32_t max_generation = 0;
1356 + uint32_t max_level = 0;
1357
1358 for (parent = current->parents; parent; parent = parent->next) {
1354 - generation = commit_graph_data_at(parent->item)->generation;
1359 + level = *topo_level_slab_at(ctx->topo_levels, parent->item);
1360
1356 - if (generation == GENERATION_NUMBER_INFINITY ||
1357 - generation == GENERATION_NUMBER_ZERO) {
1361 + if (level == GENERATION_NUMBER_ZERO) {
1362 all_parents_computed = 0;
1363 commit_list_insert(parent->item, &list);
1364 break;
1361 - } else if (generation > max_generation) {
1362 - max_generation = generation;
1365 + } else if (level > max_level) {
1366 + max_level = level;
1367 }
1368 }
1369
1370 if (all_parents_computed) {
1367 - struct commit_graph_data *data = commit_graph_data_at(current);
1368 -
1369 - data->generation = max_generation + 1;
1371 pop_commit(&list);
1372
1372 - if (data->generation > GENERATION_NUMBER_MAX)
1373 - data->generation = GENERATION_NUMBER_MAX;
1373 + if (max_level > GENERATION_NUMBER_MAX - 1)
1374 + max_level = GENERATION_NUMBER_MAX - 1;
1375 + *topo_level_slab_at(ctx->topo_levels, current) = max_level + 1;
1376 }
1377 }
1378 }
@@ -2106,6 +2108,7 @@ int write_commit_graph(struct object_directory *odb,
2108 int res = 0;
2109 int replace = 0;
2110 struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
2111 + struct topo_level_slab topo_levels;
2112
2113 prepare_repo_settings(the_repository);
2114 if (!the_repository->settings.core_commit_graph) {
@@ -2132,6 +2135,18 @@ int write_commit_graph(struct object_directory *odb,
2135 bloom_settings.max_changed_paths);
2136 ctx->bloom_settings = &bloom_settings;
2137
2138 + init_topo_level_slab(&topo_levels);
2139 + ctx->topo_levels = &topo_levels;
2140 +
2141 + if (ctx->r->objects->commit_graph) {
2142 + struct commit_graph *g = ctx->r->objects->commit_graph;
2143 +
2144 + while (g) {
2145 + g->topo_levels = &topo_levels;
2146 + g = g->base_graph;
2147 + }
2148 + }
2149 +
2150 if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS)
2151 ctx->changed_paths = 1;
2152 if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
commit-graph.h
+1
@@ -73,6 +73,7 @@ struct commit_graph {
73 const unsigned char *chunk_bloom_indexes;
74 const unsigned char *chunk_bloom_data;
75
76 + struct topo_level_slab *topo_levels;
77 struct bloom_filter_settings *bloom_filter_settings;
78 };
79