--- /dev/null
- * This is usually desireable, but there are exceptions. One exception
+ #ifndef ODB_SOURCE_PACKED_H
+ #define ODB_SOURCE_PACKED_H
+
+ #include "odb/source.h"
+ #include "packfile-list.h"
+ #include "strmap.h"
+
+ /*
+ * A store that manages packfiles for a given object database.
+ */
+ struct odb_source_packed {
+ struct odb_source base;
+
+ /*
+ * The list of packfiles in the order in which they have been most
+ * recently used.
+ */
+ struct packfile_list packs;
+
+ /*
+ * Cache of packfiles which are marked as "kept", either because there
+ * is an on-disk ".keep" file or because they are marked as "kept" in
+ * memory.
+ *
+ * Should not be accessed directly, but via
+ * `packfile_store_get_kept_pack_cache()`. The list of packs gets
+ * invalidated when the stored flags and the flags passed to
+ * `packfile_store_get_kept_pack_cache()` mismatch.
+ */
+ struct {
+ struct packed_git **packs;
+ unsigned flags;
+ } kept_cache;
+
+ /* The multi-pack index that belongs to this specific packfile store. */
+ struct multi_pack_index *midx;
+
+ /*
+ * A map of packfile names to packed_git structs for tracking which
+ * packs have been loaded already.
+ */
+ struct strmap packs_by_path;
+
+ /*
+ * Whether packfiles have already been populated with this store's
+ * packs.
+ */
+ bool initialized;
+
+ /*
+ * Usually, packfiles will be reordered to the front of the `packs`
+ * list whenever an object is looked up via them. This has the effect
+ * that packs that contain a lot of accessed objects will be located
+ * towards the front.
+ *
++ * This is usually desirable, but there are exceptions. One exception
+ * is when the looking up multiple objects in a loop for each packfile.
+ * In that case, we may easily end up with an infinite loop as the
+ * packfiles get reordered to the front repeatedly.
+ *
+ * Setting this field to `true` thus disables these reorderings.
+ */
+ bool skip_mru_updates;
+ };
+
+ /*
+ * Allocate and initialize a new empty packfile store for the given object
+ * database.
+ */
+ struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
+ const char *path,
+ bool local);
+
+ /*
+ * Cast the given object database source to the packed backend. This will cause
+ * a BUG in case the source doesn't use this backend.
+ */
+ static inline struct odb_source_packed *odb_source_packed_downcast(struct odb_source *source)
+ {
+ if (source->type != ODB_SOURCE_PACKED)
+ BUG("trying to downcast source of type '%d' to packed", source->type);
+ return container_of(source, struct odb_source_packed, base);
+ }
+
+ /*
+ * Prepare the source by loading packfiles and multi-pack indices for
+ * all alternates. This becomes a no-op if the source is already prepared.
+ *
+ * It shouldn't typically be necessary to call this function directly, as
+ * functions that access the source know to prepare it.
+ */
+ void odb_source_packed_prepare(struct odb_source_packed *source);
+
+ #endif
*/
off_t find_pack_entry_one(const struct object_id *oid, struct packed_git *);
+ int packfile_fill_entry(struct packed_git *p,
+ const struct object_id *oid,
+ struct pack_entry *e);
+
int is_pack_valid(struct packed_git *);
-void *unpack_entry(struct repository *r, struct packed_git *, off_t, enum object_type *, unsigned long *);
+void *unpack_entry(struct repository *r, struct packed_git *, off_t,
+ enum object_type *, size_t *);
unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, size_t *sizep);
-unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
+size_t get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, size_t *);
off_t get_delta_base(struct packed_git *p, struct pack_window **w_curs,
off_t *curpos, enum object_type type,