refs: store submodule ref stores in a hashmap

Aside from scaling better, this means that the submodule name needn't be stored in the ref_store instance anymore (which will be changed in a moment). This, in turn, will help loosen the strict 1:1 relationship between ref_stores and submodules. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Feb 10, 2017 at 12:16 UTC 7d4558c462f0d1a280abec59e8c64a2f2b42a9f2
2 files changed +45 -19
refs.c
+45 -13
@@ -3,6 +3,7 @@
3 */
4
5 #include "cache.h"
6 +#include "hashmap.h"
7 #include "lockfile.h"
8 #include "refs.h"
9 #include "refs/refs-internal.h"
@@ -1352,11 +1353,41 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
1353 return 0;
1354 }
1355
1356 +struct submodule_hash_entry
1357 +{
1358 + struct hashmap_entry ent; /* must be the first member! */
1359 +
1360 + struct ref_store *refs;
1361 +
1362 + /* NUL-terminated name of submodule: */
1363 + char submodule[FLEX_ARRAY];
1364 +};
1365 +
1366 +static int submodule_hash_cmp(const void *entry, const void *entry_or_key,
1367 + const void *keydata)
1368 +{
1369 + const struct submodule_hash_entry *e1 = entry, *e2 = entry_or_key;
1370 + const char *submodule = keydata ? keydata : e2->submodule;
1371 +
1372 + return strcmp(e1->submodule, submodule);
1373 +}
1374 +
1375 +static struct submodule_hash_entry *alloc_submodule_hash_entry(
1376 + const char *submodule, struct ref_store *refs)
1377 +{
1378 + struct submodule_hash_entry *entry;
1379 +
1380 + FLEX_ALLOC_STR(entry, submodule, submodule);
1381 + hashmap_entry_init(entry, strhash(submodule));
1382 + entry->refs = refs;
1383 + return entry;
1384 +}
1385 +
1386 /* A pointer to the ref_store for the main repository: */
1387 static struct ref_store *main_ref_store;
1388
1358 -/* A linked list of ref_stores for submodules: */
1359 -static struct ref_store *submodule_ref_stores;
1389 +/* A hashmap of ref_stores, stored by submodule name: */
1390 +static struct hashmap submodule_ref_stores;
1391
1392 /*
1393 * Return the ref_store instance for the specified submodule (or the
@@ -1365,17 +1396,18 @@ static struct ref_store *submodule_ref_stores;
1396 */
1397 static struct ref_store *lookup_ref_store(const char *submodule)
1398 {
1368 - struct ref_store *refs;
1399 + struct submodule_hash_entry *entry;
1400
1401 if (!submodule)
1402 return main_ref_store;
1403
1373 - for (refs = submodule_ref_stores; refs; refs = refs->next) {
1374 - if (!strcmp(submodule, refs->submodule))
1375 - return refs;
1376 - }
1404 + if (!submodule_ref_stores.tablesize)
1405 + /* It's initialized on demand in register_ref_store(). */
1406 + return NULL;
1407
1378 - return NULL;
1408 + entry = hashmap_get_from_hash(&submodule_ref_stores,
1409 + strhash(submodule), submodule);
1410 + return entry ? entry->refs : NULL;
1411 }
1412
1413 /*
@@ -1389,15 +1421,15 @@ static void register_ref_store(struct ref_store *refs, const char *submodule)
1421 if (main_ref_store)
1422 die("BUG: main_ref_store initialized twice");
1423
1392 - refs->next = NULL;
1424 main_ref_store = refs;
1425 } else {
1395 - if (lookup_ref_store(submodule))
1426 + if (!submodule_ref_stores.tablesize)
1427 + hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
1428 +
1429 + if (hashmap_put(&submodule_ref_stores,
1430 + alloc_submodule_hash_entry(submodule, refs)))
1431 die("BUG: ref_store for submodule '%s' initialized twice",
1432 submodule);
1398 -
1399 - refs->next = submodule_ref_stores;
1400 - submodule_ref_stores = refs;
1433 }
1434 }
1435
refs/refs-internal.h
-6
@@ -636,12 +636,6 @@ struct ref_store {
636 * reference store:
637 */
638 const char *submodule;
639 -
640 - /*
641 - * Submodule reference store instances are stored in a linked
642 - * list using this pointer.
643 - */
644 - struct ref_store *next;
639 };
640
641 /*