mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
packfile: move the MRU list into the packfile store
Packfiles have two lists associated to them:
- A list that keeps track of packfiles in the order that they were
added to a packfile store.
- A list that keeps track of packfiles in most-recently-used order so
that packfiles that are more likely to contain a specific object are
ordered towards the front.
Both of these lists are hosted by `struct packed_git` itself, So to
identify all packfiles in a repository you simply need to grab the first
packfile and then iterate the `->next` pointers or the MRU list. This
pattern has the problem that all packfiles are part of the same list,
regardless of whether or not they belong to the same object source.
With the upcoming pluggable object database effort this needs to change:
packfiles should be contained by a single object source, and reading an
object from any such packfile should use that source to look up the
object. Consequently, we need to break up the global lists of packfiles
into per-object-source lists.
A first step towards this goal is to move those lists out of `struct
packed_git` and into the packfile store. While the packfile store is
currently sitting on the `struct object_database` level, the intent is
to push it down one level into the `struct odb_source` in a subsequent
patch series.
Introduce a new `struct packfile_list` that is used to manage lists of
packfiles and use it to store the list of most-recently-used packfiles
in `struct packfile_store`. For now, the new list type is only used in a
single spot, but we'll expand its usage in subsequent patches.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
e78ab37054
commit
f905a855b1
92
packfile.c
92
packfile.c
@@ -47,6 +47,80 @@ static size_t pack_mapped;
|
||||
#define SZ_FMT PRIuMAX
|
||||
static inline uintmax_t sz_fmt(size_t s) { return s; }
|
||||
|
||||
void packfile_list_clear(struct packfile_list *list)
|
||||
{
|
||||
struct packfile_list_entry *e, *next;
|
||||
|
||||
for (e = list->head; e; e = next) {
|
||||
next = e->next;
|
||||
free(e);
|
||||
}
|
||||
|
||||
list->head = list->tail = NULL;
|
||||
}
|
||||
|
||||
static struct packfile_list_entry *packfile_list_remove_internal(struct packfile_list *list,
|
||||
struct packed_git *pack)
|
||||
{
|
||||
struct packfile_list_entry *e, *prev;
|
||||
|
||||
for (e = list->head, prev = NULL; e; prev = e, e = e->next) {
|
||||
if (e->pack != pack)
|
||||
continue;
|
||||
|
||||
if (prev)
|
||||
prev->next = e->next;
|
||||
if (list->head == e)
|
||||
list->head = e->next;
|
||||
if (list->tail == e)
|
||||
list->tail = prev;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void packfile_list_remove(struct packfile_list *list, struct packed_git *pack)
|
||||
{
|
||||
free(packfile_list_remove_internal(list, pack));
|
||||
}
|
||||
|
||||
void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack)
|
||||
{
|
||||
struct packfile_list_entry *entry;
|
||||
|
||||
entry = packfile_list_remove_internal(list, pack);
|
||||
if (!entry) {
|
||||
entry = xmalloc(sizeof(*entry));
|
||||
entry->pack = pack;
|
||||
}
|
||||
entry->next = list->head;
|
||||
|
||||
list->head = entry;
|
||||
if (!list->tail)
|
||||
list->tail = entry;
|
||||
}
|
||||
|
||||
void packfile_list_append(struct packfile_list *list, struct packed_git *pack)
|
||||
{
|
||||
struct packfile_list_entry *entry;
|
||||
|
||||
entry = packfile_list_remove_internal(list, pack);
|
||||
if (!entry) {
|
||||
entry = xmalloc(sizeof(*entry));
|
||||
entry->pack = pack;
|
||||
}
|
||||
entry->next = NULL;
|
||||
|
||||
if (list->tail) {
|
||||
list->tail->next = entry;
|
||||
list->tail = entry;
|
||||
} else {
|
||||
list->head = list->tail = entry;
|
||||
}
|
||||
}
|
||||
|
||||
void pack_report(struct repository *repo)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@@ -995,10 +1069,10 @@ static void packfile_store_prepare_mru(struct packfile_store *store)
|
||||
{
|
||||
struct packed_git *p;
|
||||
|
||||
INIT_LIST_HEAD(&store->mru);
|
||||
packfile_list_clear(&store->mru);
|
||||
|
||||
for (p = store->packs; p; p = p->next)
|
||||
list_add_tail(&p->mru, &store->mru);
|
||||
packfile_list_append(&store->mru, p);
|
||||
}
|
||||
|
||||
void packfile_store_prepare(struct packfile_store *store)
|
||||
@@ -1040,10 +1114,10 @@ struct packed_git *packfile_store_get_packs(struct packfile_store *store)
|
||||
return store->packs;
|
||||
}
|
||||
|
||||
struct list_head *packfile_store_get_packs_mru(struct packfile_store *store)
|
||||
struct packfile_list_entry *packfile_store_get_packs_mru(struct packfile_store *store)
|
||||
{
|
||||
packfile_store_prepare(store);
|
||||
return &store->mru;
|
||||
return store->mru.head;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2048,7 +2122,7 @@ static int fill_pack_entry(const struct object_id *oid,
|
||||
|
||||
int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct packfile_list_entry *l;
|
||||
|
||||
packfile_store_prepare(r->objects->packfiles);
|
||||
|
||||
@@ -2059,10 +2133,11 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
|
||||
if (!r->objects->packfiles->packs)
|
||||
return 0;
|
||||
|
||||
list_for_each(pos, &r->objects->packfiles->mru) {
|
||||
struct packed_git *p = list_entry(pos, struct packed_git, mru);
|
||||
for (l = r->objects->packfiles->mru.head; l; l = l->next) {
|
||||
struct packed_git *p = l->pack;
|
||||
|
||||
if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
|
||||
list_move(&p->mru, &r->objects->packfiles->mru);
|
||||
packfile_list_prepend(&r->objects->packfiles->mru, p);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2314,7 +2389,6 @@ struct packfile_store *packfile_store_new(struct object_database *odb)
|
||||
struct packfile_store *store;
|
||||
CALLOC_ARRAY(store, 1);
|
||||
store->odb = odb;
|
||||
INIT_LIST_HEAD(&store->mru);
|
||||
strmap_init(&store->packs_by_path);
|
||||
return store;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user