]> git.ipfire.org Git - thirdparty/git.git/blobdiff - pack-revindex.c
Merge branch 'en/ort-perf-batch-9'
[thirdparty/git.git] / pack-revindex.c
index 4262530449aa05c566aa231d26bb592d307e2bc1..0e4a31d9db9e71aa67ac6812241b064f01bb02a2 100644 (file)
@@ -3,6 +3,7 @@
 #include "object-store.h"
 #include "packfile.h"
 #include "config.h"
+#include "midx.h"
 
 struct revindex_entry {
        off_t offset;
@@ -293,6 +294,43 @@ int load_pack_revindex(struct packed_git *p)
        return -1;
 }
 
+int load_midx_revindex(struct multi_pack_index *m)
+{
+       char *revindex_name;
+       int ret;
+       if (m->revindex_data)
+               return 0;
+
+       revindex_name = get_midx_rev_filename(m);
+
+       ret = load_revindex_from_disk(revindex_name,
+                                     m->num_objects,
+                                     &m->revindex_map,
+                                     &m->revindex_len);
+       if (ret)
+               goto cleanup;
+
+       m->revindex_data = (const uint32_t *)((const char *)m->revindex_map + RIDX_HEADER_SIZE);
+
+cleanup:
+       free(revindex_name);
+       return ret;
+}
+
+int close_midx_revindex(struct multi_pack_index *m)
+{
+       if (!m || !m->revindex_map)
+               return 0;
+
+       munmap((void*)m->revindex_map, m->revindex_len);
+
+       m->revindex_map = NULL;
+       m->revindex_data = NULL;
+       m->revindex_len = 0;
+
+       return 0;
+}
+
 int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)
 {
        unsigned lo, hi;
@@ -347,3 +385,91 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)
        else
                return nth_packed_object_offset(p, pack_pos_to_index(p, pos));
 }
+
+uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos)
+{
+       if (!m->revindex_data)
+               BUG("pack_pos_to_midx: reverse index not yet loaded");
+       if (m->num_objects <= pos)
+               BUG("pack_pos_to_midx: out-of-bounds object at %"PRIu32, pos);
+       return get_be32(m->revindex_data + pos);
+}
+
+struct midx_pack_key {
+       uint32_t pack;
+       off_t offset;
+
+       uint32_t preferred_pack;
+       struct multi_pack_index *midx;
+};
+
+static int midx_pack_order_cmp(const void *va, const void *vb)
+{
+       const struct midx_pack_key *key = va;
+       struct multi_pack_index *midx = key->midx;
+
+       uint32_t versus = pack_pos_to_midx(midx, (uint32_t*)vb - (const uint32_t *)midx->revindex_data);
+       uint32_t versus_pack = nth_midxed_pack_int_id(midx, versus);
+       off_t versus_offset;
+
+       uint32_t key_preferred = key->pack == key->preferred_pack;
+       uint32_t versus_preferred = versus_pack == key->preferred_pack;
+
+       /*
+        * First, compare the preferred-ness, noting that the preferred pack
+        * comes first.
+        */
+       if (key_preferred && !versus_preferred)
+               return -1;
+       else if (!key_preferred && versus_preferred)
+               return 1;
+
+       /* Then, break ties first by comparing the pack IDs. */
+       if (key->pack < versus_pack)
+               return -1;
+       else if (key->pack > versus_pack)
+               return 1;
+
+       /* Finally, break ties by comparing offsets within a pack. */
+       versus_offset = nth_midxed_offset(midx, versus);
+       if (key->offset < versus_offset)
+               return -1;
+       else if (key->offset > versus_offset)
+               return 1;
+
+       return 0;
+}
+
+int midx_to_pack_pos(struct multi_pack_index *m, uint32_t at, uint32_t *pos)
+{
+       struct midx_pack_key key;
+       uint32_t *found;
+
+       if (!m->revindex_data)
+               BUG("midx_to_pack_pos: reverse index not yet loaded");
+       if (m->num_objects <= at)
+               BUG("midx_to_pack_pos: out-of-bounds object at %"PRIu32, at);
+
+       key.pack = nth_midxed_pack_int_id(m, at);
+       key.offset = nth_midxed_offset(m, at);
+       key.midx = m;
+       /*
+        * The preferred pack sorts first, so determine its identifier by
+        * looking at the first object in pseudo-pack order.
+        *
+        * Note that if no --preferred-pack is explicitly given when writing a
+        * multi-pack index, then whichever pack has the lowest identifier
+        * implicitly is preferred (and includes all its objects, since ties are
+        * broken first by pack identifier).
+        */
+       key.preferred_pack = nth_midxed_pack_int_id(m, pack_pos_to_midx(m, 0));
+
+       found = bsearch(&key, m->revindex_data, m->num_objects,
+                       sizeof(*m->revindex_data), midx_pack_order_cmp);
+
+       if (!found)
+               return error("bad offset for revindex");
+
+       *pos = found - m->revindex_data;
+       return 0;
+}