Skip to content

Commit f0f1acf

Browse files
jeffhostetlerdscho
authored andcommitted
gvfs-helper: add prefetch .keep file for last packfile
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
1 parent 1065f33 commit f0f1acf

File tree

2 files changed

+109
-3
lines changed

2 files changed

+109
-3
lines changed

gvfs-helper.c

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,7 @@ static void my_run_index_pack(struct gh__request_params *params,
18711871

18721872
static void my_finalize_packfile(struct gh__request_params *params,
18731873
struct gh__response_status *status,
1874+
int b_keep,
18741875
const struct strbuf *temp_path_pack,
18751876
const struct strbuf *temp_path_idx,
18761877
struct strbuf *final_path_pack,
@@ -1890,6 +1891,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
18901891
return;
18911892
}
18921893

1894+
if (b_keep) {
1895+
struct strbuf keep = STRBUF_INIT;
1896+
int fd_keep;
1897+
1898+
strbuf_addbuf(&keep, final_path_pack);
1899+
strbuf_strip_suffix(&keep, ".pack");
1900+
strbuf_addstr(&keep, ".keep");
1901+
1902+
fd_keep = xopen(keep.buf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
1903+
if (fd_keep >= 0)
1904+
close(fd_keep);
1905+
1906+
strbuf_release(&keep);
1907+
}
1908+
18931909
if (params->result_list) {
18941910
struct strbuf result_msg = STRBUF_INIT;
18951911

@@ -1942,7 +1958,7 @@ static void install_packfile(struct gh__request_params *params,
19421958
create_final_packfile_pathnames("vfs", packfile_checksum.buf, NULL,
19431959
&final_path_pack, &final_path_idx,
19441960
&final_filename);
1945-
my_finalize_packfile(params, status,
1961+
my_finalize_packfile(params, status, 0,
19461962
&temp_path_pack, &temp_path_idx,
19471963
&final_path_pack, &final_path_idx,
19481964
&final_filename);
@@ -2038,6 +2054,12 @@ struct ph {
20382054

20392055
/*
20402056
* Extract the next packfile from the multipack.
2057+
* Install {.pack, .idx, .keep} set.
2058+
*
2059+
* Mark each successfully installed prefetch pack as .keep it as installed
2060+
* in case we have errors decoding/indexing later packs within the received
2061+
* multipart file. (A later pass can delete the unnecessary .keep files
2062+
* from this and any previous invocations.)
20412063
*/
20422064
static void extract_packfile_from_multipack(
20432065
struct gh__request_params *params,
@@ -2134,7 +2156,7 @@ static void extract_packfile_from_multipack(
21342156

21352157
} else {
21362158
/*
2137-
* Server send the .idx immediately after the .pack in the
2159+
* Server sent the .idx immediately after the .pack in the
21382160
* data stream. I'm tempted to verify it, but that defeats
21392161
* the purpose of having it cached...
21402162
*/
@@ -2156,7 +2178,7 @@ static void extract_packfile_from_multipack(
21562178
&final_path_pack, &final_path_idx,
21572179
&final_filename);
21582180

2159-
my_finalize_packfile(params, status,
2181+
my_finalize_packfile(params, status, 1,
21602182
&temp_path_pack, &temp_path_idx,
21612183
&final_path_pack, &final_path_idx,
21622184
&final_filename);
@@ -2171,6 +2193,56 @@ static void extract_packfile_from_multipack(
21712193
strbuf_release(&final_filename);
21722194
}
21732195

2196+
struct keep_files_data {
2197+
timestamp_t max_timestamp;
2198+
int pos_of_max;
2199+
struct string_list *keep_files;
2200+
};
2201+
2202+
static void cb_keep_files(const char *full_path, size_t full_path_len,
2203+
const char *file_path, void *void_data)
2204+
{
2205+
struct keep_files_data *data = void_data;
2206+
const char *val;
2207+
timestamp_t t;
2208+
2209+
/*
2210+
* We expect prefetch packfiles named like:
2211+
*
2212+
* prefetch-<seconds>-<checksum>.keep
2213+
*/
2214+
if (!skip_prefix(file_path, "prefetch-", &val))
2215+
return;
2216+
if (!ends_with(val, ".keep"))
2217+
return;
2218+
2219+
t = strtol(val, NULL, 10);
2220+
if (t > data->max_timestamp) {
2221+
data->pos_of_max = data->keep_files->nr;
2222+
data->max_timestamp = t;
2223+
}
2224+
2225+
string_list_append(data->keep_files, full_path);
2226+
}
2227+
2228+
static void delete_stale_keep_files(
2229+
struct gh__request_params *params,
2230+
struct gh__response_status *status)
2231+
{
2232+
struct string_list keep_files = STRING_LIST_INIT_DUP;
2233+
struct keep_files_data data = { 0, 0, &keep_files };
2234+
int k;
2235+
2236+
for_each_file_in_pack_dir(gh__global.buf_odb_path.buf,
2237+
cb_keep_files, &data);
2238+
for (k = 0; k < keep_files.nr; k++) {
2239+
if (k != data.pos_of_max)
2240+
unlink(keep_files.items[k].string);
2241+
}
2242+
2243+
string_list_clear(&keep_files, 0);
2244+
}
2245+
21742246
/*
21752247
* Cut apart the received multipart response into individual packfiles
21762248
* and install each one.
@@ -2189,6 +2261,7 @@ static void install_prefetch(struct gh__request_params *params,
21892261
unsigned short np;
21902262
unsigned short k;
21912263
int fd = -1;
2264+
int nr_installed = 0;
21922265

21932266
struct strbuf temp_path_mp = STRBUF_INIT;
21942267

@@ -2229,8 +2302,12 @@ static void install_prefetch(struct gh__request_params *params,
22292302
extract_packfile_from_multipack(params, status, fd, k);
22302303
if (status->ec != GH__ERROR_CODE__OK)
22312304
break;
2305+
nr_installed++;
22322306
}
22332307

2308+
if (nr_installed)
2309+
delete_stale_keep_files(params, status);
2310+
22342311
cleanup:
22352312
if (fd != -1)
22362313
close(fd);

t/t5799-gvfs-helper.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,30 @@ verify_received_packfile_count () {
390390
return 0
391391
}
392392

393+
# Verify that we have exactly 1 prefetch .keep file.
394+
# Optionally, verify that it has the given timestamp.
395+
#
396+
verify_prefetch_keeps () {
397+
count=$(( $(ls -1 "$SHARED_CACHE_T1"/pack/prefetch-*.keep | wc -l) ))
398+
if test $count -ne 1
399+
then
400+
echo "verify_prefetch_keep_file_count: found $count, expected 1."
401+
return 1
402+
fi
403+
404+
if test $# -eq 1
405+
then
406+
count=$(( $(ls -1 "$SHARED_CACHE_T1"/pack/prefetch-$1-*.keep | wc -l) ))
407+
if test $count -ne 1
408+
then
409+
echo "verify_prefetch_keep_file_count: did not find expected keep file."
410+
return 1
411+
fi
412+
fi
413+
414+
return 0
415+
}
416+
393417
per_test_cleanup () {
394418
stop_gvfs_protocol_server
395419

@@ -643,6 +667,7 @@ test_expect_success 'basic: PREFETCH w/o arg gets all' '
643667
# packfile.
644668
#
645669
verify_received_packfile_count 3 &&
670+
verify_prefetch_keeps 1200000000 &&
646671
647672
stop_gvfs_protocol_server &&
648673
verify_connection_count 1
@@ -664,6 +689,7 @@ test_expect_success 'basic: PREFETCH w/ arg' '
664689
# packfile.
665690
#
666691
verify_received_packfile_count 2 &&
692+
verify_prefetch_keeps 1200000000 &&
667693
668694
stop_gvfs_protocol_server &&
669695
verify_connection_count 1
@@ -686,6 +712,7 @@ test_expect_success 'basic: PREFETCH mayhem no_prefetch_idx' '
686712
# packfile.
687713
#
688714
verify_received_packfile_count 2 &&
715+
verify_prefetch_keeps 1200000000 &&
689716
690717
stop_gvfs_protocol_server &&
691718
verify_connection_count 1
@@ -707,6 +734,7 @@ test_expect_success 'basic: PREFETCH up-to-date' '
707734
# packfile.
708735
#
709736
verify_received_packfile_count 2 &&
737+
verify_prefetch_keeps 1200000000 &&
710738
711739
# Ask again for any packfiles newer than what we have cached locally.
712740
#
@@ -720,6 +748,7 @@ test_expect_success 'basic: PREFETCH up-to-date' '
720748
# packfile.
721749
#
722750
verify_received_packfile_count 0 &&
751+
verify_prefetch_keeps 1200000000 &&
723752
724753
stop_gvfs_protocol_server &&
725754
verify_connection_count 2

0 commit comments

Comments
 (0)