}
}
- for (e = the_repository->objects->packfiles->mru.head; e; e = e->next) {
+ for (e = the_repository->objects->packfiles->packs.head; e; e = e->next) {
struct packed_git *p = e->pack;
want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
if (!exclude && want > 0)
- packfile_list_prepend(&the_repository->objects->packfiles->mru, p);
+ packfile_list_prepend(&the_repository->objects->packfiles->packs, p);
if (want != -1)
return want;
}
if (pack->pack_fd != -1)
pack_open_fds++;
- packfile_list_prepend(&store->packs, pack);
- packfile_list_append(&store->mru, pack);
-
+ packfile_list_append(&store->packs, pack);
strmap_put(&store->packs_by_path, pack->pack_name, pack);
}
return -1;
}
-static void packfile_store_prepare_mru(struct packfile_store *store)
-{
- packfile_list_clear(&store->mru);
-
- for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
- packfile_list_append(&store->mru, e->pack);
-}
-
void packfile_store_prepare(struct packfile_store *store)
{
struct odb_source *source;
if (!e->next)
store->packs.tail = e;
- packfile_store_prepare_mru(store);
store->initialized = true;
}
return store->packs.head;
}
-struct packfile_list_entry *packfile_store_get_packs_mru(struct packfile_store *store)
-{
- packfile_store_prepare(store);
- return store->mru.head;
-}
-
/*
* Give a fast, rough count of the number of objects in the repository. This
* ignores loose objects completely. If you have a lot of them, then either
if (!r->objects->packfiles->packs.head)
return 0;
- for (l = r->objects->packfiles->mru.head; l; l = l->next) {
+ for (l = r->objects->packfiles->packs.head; l; l = l->next) {
struct packed_git *p = l->pack;
if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
- packfile_list_prepend(&r->objects->packfiles->mru, p);
+ if (!r->objects->packfiles->skip_mru_updates)
+ packfile_list_prepend(&r->objects->packfiles->packs, p);
return 1;
}
}
int r = 0;
int pack_errors = 0;
+ repo->objects->packfiles->skip_mru_updates = true;
repo_for_each_pack(repo, p) {
if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
continue;
if (r)
break;
}
+ repo->objects->packfiles->skip_mru_updates = false;
+
return r ? r : pack_errors;
}
struct object_database *odb;
/*
- * 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 packfile_list packs;
unsigned flags;
} kept_cache;
- /* A most-recently-used ordered version of the packs list. */
- struct packfile_list mru;
-
/*
* A map of packfile names to packed_git structs for tracking which
* packs have been loaded already.
* 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;
};
/*
*/
struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
-/*
- * Get all packs in most-recently-used order.
- */
-struct packfile_list_entry *packfile_store_get_packs_mru(struct packfile_store *store);
-
/*
* Open the packfile and add it to the store if it isn't yet known. Returns
* either the newly opened packfile or the preexisting packfile. Returns a