mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
When managing a MIDX chain with many layers, it is convenient to combine a sequence of adjacent layers into a single layer to prevent the chain from growing too long. While it is conceptually possible to "compact" a sequence of MIDX layers together by running "git multi-pack-index write --stdin-packs", there are a few drawbacks that make this less than desirable: - Preserving the MIDX chain is impossible, since there is no way to write a MIDX layer that contains objects or packs found in an earlier MIDX layer already part of the chain. So callers would have to write an entirely new (non-incremental) MIDX containing only the compacted layers, discarding all other objects/packs from the MIDX. - There is (currently) no way to write a MIDX layer outside of the MIDX chain to work around the above, such that the MIDX chain could be reassembled substituting the compacted layers with the MIDX that was written. - The `--stdin-packs` command-line option does not allow us to specify the order of packs as they appear in the MIDX. Therefore, even if there were workarounds for the previous two challenges, any bitmaps belonging to layers which come after the compacted layer(s) would no longer be valid. This commit introduces a way to compact a sequence of adjacent MIDX layers into a single layer while preserving the MIDX chain, as well as any bitmap(s) in layers which are newer than the compacted ones. Implementing MIDX compaction does not require a significant number of changes to how MIDX layers are written. The main changes are as follows: - Instead of calling `fill_packs_from_midx()`, we call a new function `fill_packs_from_midx_range()`, which walks backwards along the portion of the MIDX chain which we are compacting, and adds packs one layer a time. In order to preserve the pseudo-pack order, the concatenated pack order is preserved, with the exception of preferred packs which are always added first. - After adding entries from the set of packs in the compaction range, `compute_sorted_entries()` must adjust the `pack_int_id`'s for all objects added in each fanout layer to match their original `pack_int_id`'s (as opposed to the index at which each pack appears in `ctx.info`). - When writing out the new 'multi-pack-index-chain' file, discard any layers in the compaction range, replacing them with the newly written layer, instead of keeping them and placing the new layer at the end of the chain. This ends up being sufficient to implement MIDX compaction in such a way that preserves bitmaps corresponding to more recent layers in the MIDX chain. The tests for MIDX compaction are so far fairly spartan, since the main interesting behavior here is ensuring that the right packs/objects are selected from each layer, and that the pack order is preserved despite whether or not they are sorted in lexicographic order in the original MIDX chain. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
146 lines
5.2 KiB
C
146 lines
5.2 KiB
C
#ifndef MIDX_H
|
|
#define MIDX_H
|
|
|
|
#include "string-list.h"
|
|
|
|
struct object_id;
|
|
struct pack_entry;
|
|
struct repository;
|
|
struct bitmapped_pack;
|
|
struct git_hash_algo;
|
|
struct odb_source;
|
|
|
|
#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
|
|
#define MIDX_VERSION 1
|
|
#define MIDX_BYTE_FILE_VERSION 4
|
|
#define MIDX_BYTE_HASH_VERSION 5
|
|
#define MIDX_BYTE_NUM_CHUNKS 6
|
|
#define MIDX_BYTE_NUM_PACKS 8
|
|
#define MIDX_HEADER_SIZE 12
|
|
|
|
#define MIDX_CHUNK_ALIGNMENT 4
|
|
#define MIDX_CHUNKID_PACKNAMES 0x504e414d /* "PNAM" */
|
|
#define MIDX_CHUNKID_BITMAPPEDPACKS 0x42544d50 /* "BTMP" */
|
|
#define MIDX_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
|
|
#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
|
|
#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */
|
|
#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */
|
|
#define MIDX_CHUNKID_REVINDEX 0x52494458 /* "RIDX" */
|
|
#define MIDX_CHUNKID_BASE 0x42415345 /* "BASE" */
|
|
#define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t))
|
|
#define MIDX_LARGE_OFFSET_NEEDED 0x80000000
|
|
|
|
#define GIT_TEST_MULTI_PACK_INDEX "GIT_TEST_MULTI_PACK_INDEX"
|
|
#define GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL \
|
|
"GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL"
|
|
|
|
struct multi_pack_index {
|
|
struct odb_source *source;
|
|
|
|
const unsigned char *data;
|
|
size_t data_len;
|
|
|
|
const uint32_t *revindex_data;
|
|
const uint32_t *revindex_map;
|
|
size_t revindex_len;
|
|
|
|
uint32_t signature;
|
|
unsigned char version;
|
|
unsigned char hash_len;
|
|
unsigned char num_chunks;
|
|
uint32_t num_packs;
|
|
uint32_t num_objects;
|
|
int preferred_pack_idx;
|
|
|
|
int has_chain;
|
|
|
|
const unsigned char *chunk_pack_names;
|
|
size_t chunk_pack_names_len;
|
|
const uint32_t *chunk_bitmapped_packs;
|
|
size_t chunk_bitmapped_packs_len;
|
|
const uint32_t *chunk_oid_fanout;
|
|
const unsigned char *chunk_oid_lookup;
|
|
const unsigned char *chunk_object_offsets;
|
|
const unsigned char *chunk_large_offsets;
|
|
size_t chunk_large_offsets_len;
|
|
const unsigned char *chunk_revindex;
|
|
size_t chunk_revindex_len;
|
|
|
|
struct multi_pack_index *base_midx;
|
|
uint32_t num_objects_in_base;
|
|
uint32_t num_packs_in_base;
|
|
|
|
const char **pack_names;
|
|
size_t *pack_names_sorted;
|
|
struct packed_git **packs;
|
|
};
|
|
|
|
#define MIDX_PROGRESS (1 << 0)
|
|
#define MIDX_WRITE_REV_INDEX (1 << 1)
|
|
#define MIDX_WRITE_BITMAP (1 << 2)
|
|
#define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3)
|
|
#define MIDX_WRITE_BITMAP_LOOKUP_TABLE (1 << 4)
|
|
#define MIDX_WRITE_INCREMENTAL (1 << 5)
|
|
#define MIDX_WRITE_COMPACT (1 << 6)
|
|
|
|
#define MIDX_EXT_REV "rev"
|
|
#define MIDX_EXT_BITMAP "bitmap"
|
|
#define MIDX_EXT_MIDX "midx"
|
|
|
|
const char *get_midx_checksum(const struct multi_pack_index *m) /* static buffer */;
|
|
const unsigned char *get_midx_hash(const struct multi_pack_index *m);
|
|
void get_midx_filename(struct odb_source *source, struct strbuf *out);
|
|
void get_midx_filename_ext(struct odb_source *source, struct strbuf *out,
|
|
const unsigned char *hash, const char *ext);
|
|
void get_midx_chain_dirname(struct odb_source *source, struct strbuf *out);
|
|
void get_midx_chain_filename(struct odb_source *source, struct strbuf *out);
|
|
void get_split_midx_filename_ext(struct odb_source *source, struct strbuf *buf,
|
|
const unsigned char *hash, const char *ext);
|
|
|
|
struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
|
|
struct multi_pack_index *load_multi_pack_index(struct odb_source *source);
|
|
int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id);
|
|
struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
|
|
uint32_t pack_int_id);
|
|
int nth_bitmapped_pack(struct multi_pack_index *m,
|
|
struct bitmapped_pack *bp, uint32_t pack_int_id);
|
|
int bsearch_one_midx(const struct object_id *oid, struct multi_pack_index *m,
|
|
uint32_t *result);
|
|
int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m,
|
|
uint32_t *result);
|
|
int midx_has_oid(struct multi_pack_index *m, const struct object_id *oid);
|
|
off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos);
|
|
uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos);
|
|
struct object_id *nth_midxed_object_oid(struct object_id *oid,
|
|
struct multi_pack_index *m,
|
|
uint32_t n);
|
|
int fill_midx_entry(struct multi_pack_index *m, const struct object_id *oid, struct pack_entry *e);
|
|
int midx_contains_pack(struct multi_pack_index *m,
|
|
const char *idx_or_pack_name);
|
|
int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
|
|
int prepare_multi_pack_index_one(struct odb_source *source);
|
|
|
|
/*
|
|
* Variant of write_midx_file which writes a MIDX containing only the packs
|
|
* specified in packs_to_include.
|
|
*/
|
|
int write_midx_file(struct odb_source *source,
|
|
const char *preferred_pack_name, const char *refs_snapshot,
|
|
unsigned flags);
|
|
int write_midx_file_only(struct odb_source *source,
|
|
struct string_list *packs_to_include,
|
|
const char *preferred_pack_name,
|
|
const char *refs_snapshot, unsigned flags);
|
|
int write_midx_file_compact(struct odb_source *source,
|
|
struct multi_pack_index *from,
|
|
struct multi_pack_index *to,
|
|
unsigned flags);
|
|
void clear_midx_file(struct repository *r);
|
|
int verify_midx_file(struct odb_source *source, unsigned flags);
|
|
int expire_midx_packs(struct odb_source *source, unsigned flags);
|
|
int midx_repack(struct odb_source *source, size_t batch_size, unsigned flags);
|
|
|
|
void close_midx(struct multi_pack_index *m);
|
|
|
|
#endif
|