index: make index.threads=true enable ieot and eoie

If a user explicitly sets [index] threads = true to read the index using multiple threads, ensure that index writes include the offset table by default to make that possible. This ensures that the user's intent of turning on threading is respected. In other words, permit the following configurations: - index.threads and index.recordOffsetTable unspecified: do not write the offset table yet (to avoid alarming the user with "ignoring IEOT extension" messages when an older version of Git accesses the repository) but do make use of multiple threads to read the index if the supporting offset table is present. This can also be requested explicitly by setting index.threads=true, 0, or >1 and index.recordOffsetTable=false. - index.threads=false or 1: do not write the offset table, and do not make use of the offset table. One can set index.recordOffsetTable=false as well, to be more explicit. - index.threads=true, 0, or >1 and index.recordOffsetTable unspecified: write the offset table and make use of threads at read time. This can also be requested by setting index.threads=true, 0, >1, or unspecified and index.recordOffsetTable=true. Fortunately the complication is temporary: once most Git installations have upgraded to a version with support for the IEOT and EOIE extensions, we can flip the defaults for index.recordEndOfIndexEntries and index.recordOffsetTable to true and eliminate the settings. Helped-by: Ben Peart <benpeart@microsoft.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed Nov 19, 2018 at 22:14 UTC 2a9dedef2ef76916be4a314a7e739f253eaf05db
4 files changed +32 -16
Documentation/config/index.txt
+4 -2
@@ -3,14 +3,16 @@ index.recordEndOfIndexEntries::
3 Entry" section. This reduces index load time on multiprocessor
4 machines but produces a message "ignoring EOIE extension" when
5 reading the index using Git versions before 2.20. Defaults to
6 - 'false'.
6 + 'true' if index.threads has been explicitly enabled, 'false'
7 + otherwise.
8
9 index.recordOffsetTable::
10 Specifies whether the index file should include an "Index Entry
11 Offset Table" section. This reduces index load time on
12 multiprocessor machines but produces a message "ignoring IEOT
13 extension" when reading the index using Git versions before 2.20.
13 - Defaults to 'false'.
14 + Defaults to 'true' if index.threads has been explicitly enabled,
15 + 'false' otherwise.
16
17 index.threads::
18 Specifies the number of threads to spawn when loading the index.
config.c
+10 -7
@@ -2294,22 +2294,25 @@ int git_config_get_fsmonitor(void)
2294 return 0;
2295 }
2296
2297 -int git_config_get_index_threads(void)
2297 +int git_config_get_index_threads(int *dest)
2298 {
2299 - int is_bool, val = 0;
2299 + int is_bool, val;
2300
2301 val = git_env_ulong("GIT_TEST_INDEX_THREADS", 0);
2302 - if (val)
2303 - return val;
2302 + if (val) {
2303 + *dest = val;
2304 + return 0;
2305 + }
2306
2307 if (!git_config_get_bool_or_int("index.threads", &is_bool, &val)) {
2308 if (is_bool)
2307 - return val ? 0 : 1;
2309 + *dest = val ? 0 : 1;
2310 else
2309 - return val;
2311 + *dest = val;
2312 + return 0;
2313 }
2314
2312 - return 0; /* auto */
2315 + return 1;
2316 }
2317
2318 NORETURN
config.h
+1 -1
@@ -246,11 +246,11 @@ extern int git_config_get_bool(const char *key, int *dest);
246 extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
247 extern int git_config_get_maybe_bool(const char *key, int *dest);
248 extern int git_config_get_pathname(const char *key, const char **dest);
249 +extern int git_config_get_index_threads(int *dest);
250 extern int git_config_get_untracked_cache(void);
251 extern int git_config_get_split_index(void);
252 extern int git_config_get_max_percent_split_change(void);
253 extern int git_config_get_fsmonitor(void);
253 -extern int git_config_get_index_threads(void);
254
255 /* This dies if the configured or default date is in the future */
256 extern int git_config_get_expiry(const char *key, const char **output);
read-cache.c
+17 -6
@@ -2176,7 +2176,8 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
2176
2177 src_offset = sizeof(*hdr);
2178
2179 - nr_threads = git_config_get_index_threads();
2179 + if (git_config_get_index_threads(&nr_threads))
2180 + nr_threads = 1;
2181
2182 /* TODO: does creating more threads than cores help? */
2183 if (!nr_threads) {
@@ -2695,7 +2696,13 @@ static int record_eoie(void)
2696
2697 if (!git_config_get_bool("index.recordendofindexentries", &val))
2698 return val;
2698 - return 0;
2699 +
2700 + /*
2701 + * As a convenience, the end of index entries extension
2702 + * used for threading is written by default if the user
2703 + * explicitly requested threaded index reads.
2704 + */
2705 + return !git_config_get_index_threads(&val) && val != 1;
2706 }
2707
2708 static int record_ieot(void)
@@ -2704,7 +2711,13 @@ static int record_ieot(void)
2711
2712 if (!git_config_get_bool("index.recordoffsettable", &val))
2713 return val;
2707 - return 0;
2714 +
2715 + /*
2716 + * As a convenience, the offset table used for threading is
2717 + * written by default if the user explicitly requested
2718 + * threaded index reads.
2719 + */
2720 + return !git_config_get_index_threads(&val) && val != 1;
2721 }
2722
2723 /*
@@ -2765,9 +2778,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2778 if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
2779 return -1;
2780
2768 - if (HAVE_THREADS)
2769 - nr_threads = git_config_get_index_threads();
2770 - else
2781 + if (!HAVE_THREADS || git_config_get_index_threads(&nr_threads))
2782 nr_threads = 1;
2783
2784 if (nr_threads != 1 && record_ieot()) {