aboutsummaryrefslogtreecommitdiff
path: root/packfile.h
diff options
context:
space:
mode:
Diffstat (limited to 'packfile.h')
-rw-r--r--packfile.h234
1 files changed, 179 insertions, 55 deletions
diff --git a/packfile.h b/packfile.h
index c9d0b93446..9b647da7dd 100644
--- a/packfile.h
+++ b/packfile.h
@@ -4,15 +4,16 @@
#include "list.h"
#include "object.h"
#include "odb.h"
+#include "odb/source-files.h"
#include "oidset.h"
+#include "repository.h"
+#include "strmap.h"
/* in odb.h */
struct object_info;
+struct odb_read_stream;
struct packed_git {
- struct hashmap_entry packmap_ent;
- struct packed_git *next;
- struct list_head mru;
struct pack_window *windows;
off_t pack_size;
const void *index_data;
@@ -27,6 +28,7 @@ struct packed_git {
unsigned pack_local:1,
pack_keep:1,
pack_keep_in_core:1,
+ pack_keep_in_core_open:1,
freshened:1,
do_not_close:1,
pack_promisor:1,
@@ -52,53 +54,91 @@ struct packed_git {
char pack_name[FLEX_ARRAY]; /* more */
};
+struct packfile_list {
+ struct packfile_list_entry *head, *tail;
+};
+
+struct packfile_list_entry {
+ struct packfile_list_entry *next;
+ struct packed_git *pack;
+};
+
+void packfile_list_clear(struct packfile_list *list);
+void packfile_list_remove(struct packfile_list *list, struct packed_git *pack);
+void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack);
+void packfile_list_append(struct packfile_list *list, struct packed_git *pack);
+
+/*
+ * Find the pack within the "packs" list whose index contains the object
+ * "oid". For general object lookups, you probably don't want this; use
+ * find_pack_entry() instead.
+ */
+struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
+ const struct object_id *oid);
+
/*
* A store that manages packfiles for a given object database.
*/
struct packfile_store {
- struct object_database *odb;
+ struct odb_source *source;
/*
- * The list of packfiles in the order in which they are being added to
- * the store.
+ * The list of packfiles in the order in which they have been most
+ * recently used.
*/
- struct packed_git *packs;
+ 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 `kept_pack_cache()`. The
- * list of packs gets invalidated when the stored flags and the flags
- * passed to `kept_pack_cache()` mismatch.
+ * 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;
- /* A most-recently-used ordered version of the packs list. */
- struct list_head mru;
+ /* 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 hashmap map;
+ 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 desireable, 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.
+ * database source.
*/
-struct packfile_store *packfile_store_new(struct object_database *odb);
+struct packfile_store *packfile_store_new(struct odb_source *source);
/*
* Free the packfile store and all its associated state. All packfiles
@@ -137,23 +177,81 @@ void packfile_store_add_pack(struct packfile_store *store,
struct packed_git *pack);
/*
+ * Get all packs managed by the given store, including packfiles that are
+ * referenced by multi-pack indices.
+ */
+struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
+
+struct repo_for_each_pack_data {
+ struct odb_source *source;
+ struct packfile_list_entry *entry;
+};
+
+static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct repository *repo)
+{
+ struct repo_for_each_pack_data data = { 0 };
+
+ odb_prepare_alternates(repo->objects);
+
+ for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
+ struct odb_source_files *files = odb_source_files_downcast(source);
+ struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
+ if (!entry)
+ continue;
+ data.source = source;
+ data.entry = entry;
+ break;
+ }
+
+ return data;
+}
+
+static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *data)
+{
+ struct odb_source *source;
+
+ data->entry = data->entry->next;
+ if (data->entry)
+ return;
+
+ for (source = data->source->next; source; source = source->next) {
+ struct odb_source_files *files = odb_source_files_downcast(source);
+ struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
+ if (!entry)
+ continue;
+ data->source = source;
+ data->entry = entry;
+ return;
+ }
+
+ data->source = NULL;
+ data->entry = NULL;
+}
+
+/*
* Load and iterate through all packs of the given repository. This helper
* function will yield packfiles from all object sources connected to the
* repository.
*/
#define repo_for_each_pack(repo, p) \
- for (p = packfile_store_get_packs(repo->objects->packfiles); p; p = p->next)
+ for (struct repo_for_each_pack_data eack_pack_data = repo_for_eack_pack_data_init(repo); \
+ ((p) = (eack_pack_data.entry ? eack_pack_data.entry->pack : NULL)); \
+ repo_for_each_pack_data_next(&eack_pack_data))
-/*
- * Get all packs managed by the given store, including packfiles that are
- * referenced by multi-pack indices.
- */
-struct packed_git *packfile_store_get_packs(struct packfile_store *store);
+int packfile_store_read_object_stream(struct odb_read_stream **out,
+ struct packfile_store *store,
+ const struct object_id *oid);
/*
- * Get all packs in most-recently-used order.
+ * Try to read the object identified by its ID from the object store and
+ * populate the object info with its data. Returns 1 in case the object was
+ * not found, 0 if it was and read successfully, and a negative error code in
+ * case the object was corrupted.
*/
-struct list_head *packfile_store_get_packs_mru(struct packfile_store *store);
+int packfile_store_read_object_info(struct packfile_store *store,
+ const struct object_id *oid,
+ struct object_info *oi,
+ enum object_info_flags flags);
/*
* Open the packfile and add it to the store if it isn't yet known. Returns
@@ -163,6 +261,33 @@ struct list_head *packfile_store_get_packs_mru(struct packfile_store *store);
struct packed_git *packfile_store_load_pack(struct packfile_store *store,
const char *idx_path, int local);
+int packfile_store_freshen_object(struct packfile_store *store,
+ const struct object_id *oid);
+
+enum kept_pack_type {
+ KEPT_PACK_ON_DISK = (1 << 0),
+ KEPT_PACK_IN_CORE = (1 << 1),
+ KEPT_PACK_IN_CORE_OPEN = (1 << 2),
+};
+
+/*
+ * Count the number objects contained in the given packfile store. If
+ * successful, the number of objects will be written to the `out` pointer.
+ *
+ * Return 0 on success, a negative error code otherwise.
+ */
+int packfile_store_count_objects(struct packfile_store *store,
+ enum odb_count_objects_flags flags,
+ unsigned long *out);
+
+/*
+ * Retrieve the cache of kept packs from the given packfile store. Accepts a
+ * combination of `kept_pack_type` flags. The cache is computed on demand and
+ * will be recomputed whenever the flags change.
+ */
+struct packed_git **packfile_store_get_kept_pack_cache(struct packfile_store *store,
+ unsigned flags);
+
struct pack_window {
struct pack_window *next;
unsigned char *base;
@@ -229,9 +354,27 @@ typedef int each_packed_object_fn(const struct object_id *oid,
void *data);
int for_each_object_in_pack(struct packed_git *p,
each_packed_object_fn, void *data,
- enum for_each_object_flags flags);
-int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
- void *data, enum for_each_object_flags flags);
+ enum odb_for_each_object_flags flags);
+
+/*
+ * Iterate through all packed objects in the given packfile store and invoke
+ * the callback function for each of them. If an object info request is given,
+ * then the object info will be read for every individual object and passed to
+ * the callback as if `packfile_store_read_object_info()` was called for the
+ * object.
+ *
+ * The flags parameter is a combination of `odb_for_each_object_flags`.
+ */
+int packfile_store_for_each_object(struct packfile_store *store,
+ const struct object_info *request,
+ odb_for_each_object_cb cb,
+ void *cb_data,
+ const struct odb_for_each_object_options *opts);
+
+int packfile_store_find_abbrev_len(struct packfile_store *store,
+ const struct object_id *oid,
+ unsigned min_len,
+ unsigned *out);
/* A hook to report invalid files in pack directory */
#define PACKDIR_FILE_PACK 1
@@ -239,20 +382,6 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
#define PACKDIR_FILE_GARBAGE 4
extern void (*report_garbage)(unsigned seen_bits, const char *path);
-/*
- * Give a rough count of objects in the repository. This sacrifices accuracy
- * for speed.
- */
-unsigned long repo_approximate_object_count(struct repository *r);
-
-/*
- * Find the pack within the "packs" list whose index contains the object "oid".
- * For general object lookups, you probably don't want this; use
- * find_pack_entry() instead.
- */
-struct packed_git *find_oid_pack(const struct object_id *oid,
- struct packed_git *packs);
-
void pack_report(struct repository *repo);
/*
@@ -276,7 +405,6 @@ struct object_database;
unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
void close_pack_windows(struct packed_git *);
void close_pack(struct packed_git *);
-void close_object_store(struct object_database *o);
void unuse_pack(struct pack_window **);
void clear_delta_base_cache(void);
struct packed_git *add_packed_git(struct repository *r, const char *path,
@@ -335,34 +463,30 @@ off_t get_delta_base(struct packed_git *p, struct pack_window **w_curs,
off_t *curpos, enum object_type type,
off_t delta_obj_offset);
+int packfile_read_object_stream(struct odb_read_stream **out,
+ const struct object_id *oid,
+ struct packed_git *pack,
+ off_t offset);
+
void release_pack_memory(size_t);
/* global flag to enable extra checks when accessing packed objects */
extern int do_check_packed_object_crc;
-int packed_object_info(struct repository *r,
- struct packed_git *pack,
+/*
+ * Look up the object info for a specific offset in the packfile.
+ * Returns zero on success, a negative error code otherwise.
+ */
+int packed_object_info(struct packed_git *pack,
off_t offset, struct object_info *);
void mark_bad_packed_object(struct packed_git *, const struct object_id *);
const struct packed_git *has_packed_and_bad(struct repository *, const struct object_id *);
-#define ON_DISK_KEEP_PACKS 1
-#define IN_CORE_KEEP_PACKS 2
-
-/*
- * Iff a pack file in the given repository contains the object named by sha1,
- * return true and store its location to e.
- */
-int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e);
-int find_kept_pack_entry(struct repository *r, const struct object_id *oid, unsigned flags, struct pack_entry *e);
-
int has_object_pack(struct repository *r, const struct object_id *oid);
int has_object_kept_pack(struct repository *r, const struct object_id *oid,
unsigned flags);
-struct packed_git **kept_pack_cache(struct repository *r, unsigned flags);
-
/*
* Return 1 if an object in a promisor packfile is or refers to the given
* object, 0 otherwise.