Skip to content

Commit f9d7abe

Browse files
pcloudsgitster
authored andcommitted
split-index: add and use unshare_split_index()
When split-index is being used, we have two cache_entry arrays in index_state->cache[] and index_state->split_index->base->cache[]. index_state->cache[] may share the same entries with base->cache[] so we can quickly determine what entries are shared. This makes memory management tricky, we can't free base->cache[] until we know index_state->cache[] does not point to any of those entries. unshare_split_index() is added for this purpose, to find shared entries and either duplicate them in index_state->cache[], or discard them. Either way it should be safe to free base->cache[] after unshare_split_index(). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 4fa66c8 commit f9d7abe

File tree

3 files changed

+47
-21
lines changed

3 files changed

+47
-21
lines changed

read-cache.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,15 +1877,9 @@ int discard_index(struct index_state *istate)
18771877
{
18781878
int i;
18791879

1880-
for (i = 0; i < istate->cache_nr; i++) {
1881-
if (istate->cache[i]->index &&
1882-
istate->split_index &&
1883-
istate->split_index->base &&
1884-
istate->cache[i]->index <= istate->split_index->base->cache_nr &&
1885-
istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
1886-
continue;
1880+
unshare_split_index(istate, 1);
1881+
for (i = 0; i < istate->cache_nr; i++)
18871882
free(istate->cache[i]);
1888-
}
18891883
resolve_undo_clear_index(istate);
18901884
istate->cache_nr = 0;
18911885
istate->cache_changed = 0;

split-index.c

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,17 @@ void move_cache_to_base_index(struct index_state *istate)
7373
int i;
7474

7575
/*
76-
* do not delete old si->base, its index entries may be shared
77-
* with istate->cache[]. Accept a bit of leaking here because
78-
* this code is only used by short-lived update-index.
76+
* If "si" is shared with another index_state (e.g. by
77+
* unpack-trees code), we will need to duplicate split_index
78+
* struct. It's not happening now though, luckily.
7979
*/
80+
assert(si->refcount <= 1);
81+
82+
unshare_split_index(istate, 0);
83+
if (si->base) {
84+
discard_index(si->base);
85+
free(si->base);
86+
}
8087
si->base = xcalloc(1, sizeof(*si->base));
8188
si->base->version = istate->version;
8289
/* zero timestamp disables racy test in ce_write_index() */
@@ -275,11 +282,41 @@ void finish_writing_split_index(struct index_state *istate)
275282
istate->cache_nr = si->saved_cache_nr;
276283
}
277284

285+
void unshare_split_index(struct index_state *istate, int discard)
286+
{
287+
struct split_index *si = istate->split_index;
288+
int i;
289+
290+
if (!si || !si->base)
291+
return;
292+
293+
for (i = 0; i < istate->cache_nr; i++) {
294+
struct cache_entry *ce = istate->cache[i];
295+
struct cache_entry *new = NULL;
296+
297+
if (!ce->index ||
298+
ce->index > si->base->cache_nr ||
299+
ce != si->base->cache[ce->index - 1])
300+
continue;
301+
302+
if (!discard) {
303+
int len = ce_namelen(ce);
304+
new = xcalloc(1, cache_entry_size(len));
305+
copy_cache_entry(new, ce);
306+
memcpy(new->name, ce->name, len);
307+
new->index = 0;
308+
}
309+
istate->cache[i] = new;
310+
}
311+
}
312+
313+
278314
void discard_split_index(struct index_state *istate)
279315
{
280316
struct split_index *si = istate->split_index;
281317
if (!si)
282318
return;
319+
unshare_split_index(istate, 0);
283320
istate->split_index = NULL;
284321
si->refcount--;
285322
if (si->refcount)
@@ -328,14 +365,8 @@ void add_split_index(struct index_state *istate)
328365

329366
void remove_split_index(struct index_state *istate)
330367
{
331-
if (istate->split_index) {
332-
/*
333-
* can't discard_split_index(&the_index); because that
334-
* will destroy split_index->base->cache[], which may
335-
* be shared with the_index.cache[]. So yeah we're
336-
* leaking a bit here.
337-
*/
338-
istate->split_index = NULL;
339-
istate->cache_changed |= SOMETHING_CHANGED;
340-
}
368+
if (!istate->split_index)
369+
return;
370+
discard_split_index(istate);
371+
istate->cache_changed |= SOMETHING_CHANGED;
341372
}

split-index.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ void finish_writing_split_index(struct index_state *istate);
3333
void discard_split_index(struct index_state *istate);
3434
void add_split_index(struct index_state *istate);
3535
void remove_split_index(struct index_state *istate);
36+
void unshare_split_index(struct index_state *istate, int discard);
3637

3738
#endif

0 commit comments

Comments
 (0)