]> git.ipfire.org Git - thirdparty/git.git/blobdiff - pack-bitmap-write.c
dir.h: move DTYPE defines from cache.h
[thirdparty/git.git] / pack-bitmap-write.c
index c43375bd344f22473adcd7cac09c9f1572e27079..faf67c94d37e15914f248779f50207ffeb805b72 100644 (file)
@@ -1,4 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "commit.h"
 #include "tag.h"
@@ -13,6 +17,7 @@
 #include "pack-objects.h"
 #include "commit-reach.h"
 #include "prio-queue.h"
+#include "trace2.h"
 
 struct bitmapped_commit {
        struct commit *commit;
@@ -384,6 +389,8 @@ static int fill_bitmap_tree(struct bitmap *bitmap,
        return 0;
 }
 
+static int reused_bitmaps_nr;
+
 static int fill_bitmap_commit(struct bb_commit *ent,
                              struct commit *commit,
                              struct prio_queue *queue,
@@ -409,8 +416,10 @@ static int fill_bitmap_commit(struct bb_commit *ent,
                         * bitmap and add its bits to this one. No need to walk
                         * parents or the tree for this commit.
                         */
-                       if (old && !rebuild_bitmap(mapping, old, ent->bitmap))
+                       if (old && !rebuild_bitmap(mapping, old, ent->bitmap)) {
+                               reused_bitmaps_nr++;
                                continue;
+                       }
                }
 
                /*
@@ -421,7 +430,8 @@ static int fill_bitmap_commit(struct bb_commit *ent,
                if (!found)
                        return -1;
                bitmap_set(ent->bitmap, pos);
-               prio_queue_put(tree_queue, get_commit_tree(c));
+               prio_queue_put(tree_queue,
+                              repo_get_commit_tree(the_repository, c));
 
                for (p = c->parents; p; p = p->next) {
                        pos = find_object_pos(&p->item->object.oid, &found);
@@ -526,6 +536,8 @@ int bitmap_writer_build(struct packing_data *to_pack)
 
        trace2_region_leave("pack-bitmap-write", "building_bitmaps_total",
                            the_repository);
+       trace2_data_intmax("pack-bitmap-write", the_repository,
+                          "building_bitmaps_reused", reused_bitmaps_nr);
 
        stop_progress(&writer.progress);
 
@@ -649,21 +661,18 @@ static const struct object_id *oid_access(size_t pos, const void *table)
 }
 
 static void write_selected_commits_v1(struct hashfile *f,
-                                     struct pack_idx_entry **index,
-                                     uint32_t index_nr)
+                                     uint32_t *commit_positions,
+                                     off_t *offsets)
 {
        int i;
 
        for (i = 0; i < writer.selected_nr; ++i) {
                struct bitmapped_commit *stored = &writer.selected[i];
 
-               int commit_pos =
-                       oid_pos(&stored->commit->object.oid, index, index_nr, oid_access);
+               if (offsets)
+                       offsets[i] = hashfile_total(f);
 
-               if (commit_pos < 0)
-                       BUG("trying to write commit not in index");
-
-               hashwrite_be32(f, commit_pos);
+               hashwrite_be32(f, commit_positions[i]);
                hashwrite_u8(f, stored->xor_offset);
                hashwrite_u8(f, stored->flags);
 
@@ -671,6 +680,79 @@ static void write_selected_commits_v1(struct hashfile *f,
        }
 }
 
+static int table_cmp(const void *_va, const void *_vb, void *_data)
+{
+       uint32_t *commit_positions = _data;
+       uint32_t a = commit_positions[*(uint32_t *)_va];
+       uint32_t b = commit_positions[*(uint32_t *)_vb];
+
+       if (a > b)
+               return 1;
+       else if (a < b)
+               return -1;
+
+       return 0;
+}
+
+static void write_lookup_table(struct hashfile *f,
+                              uint32_t *commit_positions,
+                              off_t *offsets)
+{
+       uint32_t i;
+       uint32_t *table, *table_inv;
+
+       ALLOC_ARRAY(table, writer.selected_nr);
+       ALLOC_ARRAY(table_inv, writer.selected_nr);
+
+       for (i = 0; i < writer.selected_nr; i++)
+               table[i] = i;
+
+       /*
+        * At the end of this sort table[j] = i means that the i'th
+        * bitmap corresponds to j'th bitmapped commit (among the selected
+        * commits) in lex order of OIDs.
+        */
+       QSORT_S(table, writer.selected_nr, table_cmp, commit_positions);
+
+       /* table_inv helps us discover that relationship (i'th bitmap
+        * to j'th commit by j = table_inv[i])
+        */
+       for (i = 0; i < writer.selected_nr; i++)
+               table_inv[table[i]] = i;
+
+       trace2_region_enter("pack-bitmap-write", "writing_lookup_table", the_repository);
+       for (i = 0; i < writer.selected_nr; i++) {
+               struct bitmapped_commit *selected = &writer.selected[table[i]];
+               uint32_t xor_offset = selected->xor_offset;
+               uint32_t xor_row;
+
+               if (xor_offset) {
+                       /*
+                        * xor_index stores the index (in the bitmap entries)
+                        * of the corresponding xor bitmap. But we need to convert
+                        * this index into lookup table's index. So, table_inv[xor_index]
+                        * gives us the index position w.r.t. the lookup table.
+                        *
+                        * If "k = table[i] - xor_offset" then the xor base is the k'th
+                        * bitmap. `table_inv[k]` gives us the position of that bitmap
+                        * in the lookup table.
+                        */
+                       uint32_t xor_index = table[i] - xor_offset;
+                       xor_row = table_inv[xor_index];
+               } else {
+                       xor_row = 0xffffffff;
+               }
+
+               hashwrite_be32(f, commit_positions[table[i]]);
+               hashwrite_be64(f, (uint64_t)offsets[table[i]]);
+               hashwrite_be32(f, xor_row);
+       }
+       trace2_region_leave("pack-bitmap-write", "writing_lookup_table", the_repository);
+
+       free(table);
+       free(table_inv);
+}
+
 static void write_hash_cache(struct hashfile *f,
                             struct pack_idx_entry **index,
                             uint32_t index_nr)
@@ -683,7 +765,7 @@ static void write_hash_cache(struct hashfile *f,
        }
 }
 
-void bitmap_writer_set_checksum(unsigned char *sha1)
+void bitmap_writer_set_checksum(const unsigned char *sha1)
 {
        hashcpy(writer.pack_checksum, sha1);
 }
@@ -697,6 +779,9 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
        static uint16_t flags = BITMAP_OPT_FULL_DAG;
        struct strbuf tmp_file = STRBUF_INIT;
        struct hashfile *f;
+       uint32_t *commit_positions = NULL;
+       off_t *offsets = NULL;
+       uint32_t i;
 
        struct bitmap_disk_header header;
 
@@ -715,7 +800,26 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
        dump_bitmap(f, writer.trees);
        dump_bitmap(f, writer.blobs);
        dump_bitmap(f, writer.tags);
-       write_selected_commits_v1(f, index, index_nr);
+
+       if (options & BITMAP_OPT_LOOKUP_TABLE)
+               CALLOC_ARRAY(offsets, index_nr);
+
+       ALLOC_ARRAY(commit_positions, writer.selected_nr);
+
+       for (i = 0; i < writer.selected_nr; i++) {
+               struct bitmapped_commit *stored = &writer.selected[i];
+               int commit_pos = oid_pos(&stored->commit->object.oid, index, index_nr, oid_access);
+
+               if (commit_pos < 0)
+                       BUG(_("trying to write commit not in index"));
+
+               commit_positions[i] = commit_pos;
+       }
+
+       write_selected_commits_v1(f, commit_positions, offsets);
+
+       if (options & BITMAP_OPT_LOOKUP_TABLE)
+               write_lookup_table(f, commit_positions, offsets);
 
        if (options & BITMAP_OPT_HASH_CACHE)
                write_hash_cache(f, index, index_nr);
@@ -730,4 +834,6 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
                die_errno("unable to rename temporary bitmap file to '%s'", filename);
 
        strbuf_release(&tmp_file);
+       free(commit_positions);
+       free(offsets);
 }