Skip to content

Commit 3b7a447

Browse files
dschogitster
authored andcommitted
split-index; stop abusing the base_oid to strip the "link" extension
When a split-index is in effect, the `$GIT_DIR/index` file needs to contain a "link" extension that contains all the information about the split-index, including the information about the shared index. However, in some cases Git needs to suppress writing that "link" extension (i.e. to fall back to writing a full index) even if the in-memory index structure _has_ a `split_index` configured. This is the case e.g. when "too many not shared" index entries exist. In such instances, the current code sets the `base_oid` field of said `split_index` structure to all-zero to indicate that `do_write_index()` should skip writing the "link" extension. This can lead to problems later on, when the in-memory index is still used to perform other operations and eventually wants to write a split-index, detects the presence of the `split_index` and reuses that, too (under the assumption that it has been initialized correctly and still has a non-null `base_oid`). Let's stop zeroing out the `base_oid` to indicate that the "link" extension should not be written. One might be tempted to simply call `discard_split_index()` instead, under the assumption that Git decided to write a non-split index and therefore the `split_index` structure might no longer be wanted. However, that is not possible because that would release index entries in `split_index->base` that are likely to still be in use. Therefore we cannot do that. The next best thing we _can_ do is to introduce a bit field to indicate specifically which index extensions (not) to write. So that's what we do here. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3704fed commit 3b7a447

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

read-cache.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,6 +2868,16 @@ static int record_ieot(void)
28682868
return !git_config_get_index_threads(&val) && val != 1;
28692869
}
28702870

2871+
enum write_extensions {
2872+
WRITE_NO_EXTENSION = 0,
2873+
WRITE_SPLIT_INDEX_EXTENSION = 1<<0,
2874+
WRITE_CACHE_TREE_EXTENSION = 1<<1,
2875+
WRITE_RESOLVE_UNDO_EXTENSION = 1<<2,
2876+
WRITE_UNTRACKED_CACHE_EXTENSION = 1<<3,
2877+
WRITE_FSMONITOR_EXTENSION = 1<<4,
2878+
};
2879+
#define WRITE_ALL_EXTENSIONS ((enum write_extensions)-1)
2880+
28712881
/*
28722882
* On success, `tempfile` is closed. If it is the temporary file
28732883
* of a `struct lock_file`, we will therefore effectively perform
@@ -2876,7 +2886,7 @@ static int record_ieot(void)
28762886
* rely on it.
28772887
*/
28782888
static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2879-
int strip_extensions, unsigned flags)
2889+
enum write_extensions write_extensions, unsigned flags)
28802890
{
28812891
uint64_t start = getnanotime();
28822892
struct hashfile *f;
@@ -3045,8 +3055,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30453055
return -1;
30463056
}
30473057

3048-
if (!strip_extensions && istate->split_index &&
3049-
!is_null_oid(&istate->split_index->base_oid)) {
3058+
if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION &&
3059+
istate->split_index) {
30503060
struct strbuf sb = STRBUF_INIT;
30513061

30523062
if (istate->sparse_index)
@@ -3060,7 +3070,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30603070
if (err)
30613071
return -1;
30623072
}
3063-
if (!strip_extensions && !drop_cache_tree && istate->cache_tree) {
3073+
if (write_extensions & WRITE_CACHE_TREE_EXTENSION &&
3074+
!drop_cache_tree && istate->cache_tree) {
30643075
struct strbuf sb = STRBUF_INIT;
30653076

30663077
cache_tree_write(&sb, istate->cache_tree);
@@ -3070,7 +3081,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30703081
if (err)
30713082
return -1;
30723083
}
3073-
if (!strip_extensions && istate->resolve_undo) {
3084+
if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION &&
3085+
istate->resolve_undo) {
30743086
struct strbuf sb = STRBUF_INIT;
30753087

30763088
resolve_undo_write(&sb, istate->resolve_undo);
@@ -3081,7 +3093,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30813093
if (err)
30823094
return -1;
30833095
}
3084-
if (!strip_extensions && istate->untracked) {
3096+
if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION &&
3097+
istate->untracked) {
30853098
struct strbuf sb = STRBUF_INIT;
30863099

30873100
write_untracked_extension(&sb, istate->untracked);
@@ -3092,7 +3105,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30923105
if (err)
30933106
return -1;
30943107
}
3095-
if (!strip_extensions && istate->fsmonitor_last_update) {
3108+
if (write_extensions & WRITE_FSMONITOR_EXTENSION &&
3109+
istate->fsmonitor_last_update) {
30963110
struct strbuf sb = STRBUF_INIT;
30973111

30983112
write_fsmonitor_extension(&sb, istate);
@@ -3166,8 +3180,10 @@ static int commit_locked_index(struct lock_file *lk)
31663180
return commit_lock_file(lk);
31673181
}
31683182

3169-
static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
3170-
unsigned flags)
3183+
static int do_write_locked_index(struct index_state *istate,
3184+
struct lock_file *lock,
3185+
unsigned flags,
3186+
enum write_extensions write_extensions)
31713187
{
31723188
int ret;
31733189
int was_full = istate->sparse_index == INDEX_EXPANDED;
@@ -3185,7 +3201,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
31853201
*/
31863202
trace2_region_enter_printf("index", "do_write_index", the_repository,
31873203
"%s", get_lock_file_path(lock));
3188-
ret = do_write_index(istate, lock->tempfile, 0, flags);
3204+
ret = do_write_index(istate, lock->tempfile, write_extensions, flags);
31893205
trace2_region_leave_printf("index", "do_write_index", the_repository,
31903206
"%s", get_lock_file_path(lock));
31913207

@@ -3214,7 +3230,7 @@ static int write_split_index(struct index_state *istate,
32143230
{
32153231
int ret;
32163232
prepare_to_write_split_index(istate);
3217-
ret = do_write_locked_index(istate, lock, flags);
3233+
ret = do_write_locked_index(istate, lock, flags, WRITE_ALL_EXTENSIONS);
32183234
finish_writing_split_index(istate);
32193235
return ret;
32203236
}
@@ -3289,7 +3305,7 @@ static int write_shared_index(struct index_state *istate,
32893305

32903306
trace2_region_enter_printf("index", "shared/do_write_index",
32913307
the_repository, "%s", get_tempfile_path(*temp));
3292-
ret = do_write_index(si->base, *temp, 1, flags);
3308+
ret = do_write_index(si->base, *temp, WRITE_NO_EXTENSION, flags);
32933309
trace2_region_leave_printf("index", "shared/do_write_index",
32943310
the_repository, "%s", get_tempfile_path(*temp));
32953311

@@ -3366,9 +3382,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
33663382
if ((!si && !test_split_index_env) ||
33673383
alternate_index_output ||
33683384
(istate->cache_changed & ~EXTMASK)) {
3369-
if (si)
3370-
oidclr(&si->base_oid);
3371-
ret = do_write_locked_index(istate, lock, flags);
3385+
ret = do_write_locked_index(istate, lock, flags,
3386+
~WRITE_SPLIT_INDEX_EXTENSION);
33723387
goto out;
33733388
}
33743389

@@ -3394,8 +3409,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
33943409
/* Same initial permissions as the main .git/index file */
33953410
temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
33963411
if (!temp) {
3397-
oidclr(&si->base_oid);
3398-
ret = do_write_locked_index(istate, lock, flags);
3412+
ret = do_write_locked_index(istate, lock, flags,
3413+
~WRITE_SPLIT_INDEX_EXTENSION);
33993414
goto out;
34003415
}
34013416
ret = write_shared_index(istate, &temp, flags);

t/t7527-builtin-fsmonitor.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' '
10031003
egrep "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
10041004
'
10051005

1006-
test_expect_failure 'split-index and FSMonitor work well together' '
1006+
test_expect_success 'split-index and FSMonitor work well together' '
10071007
git init split-index &&
10081008
test_when_finished "git -C \"$PWD/split-index\" \
10091009
fsmonitor--daemon stop" &&

0 commit comments

Comments
 (0)