Skip to content

Commit 4b24b82

Browse files
jeffhostetlerdscho
authored andcommitted
gvfs:trace2:data: status deserialization information
Add trace2 region and data events describing attempts to deserialize status data using a status cache. A category:status, label:deserialize region is pushed around the deserialize code. Deserialization results when reading from a file are: category:status, path = <path> category:status, polled = <number_of_attempts> category:status, result = "ok" | "reject" When reading from STDIN are: category:status, path = "STDIN" category:status, result = "ok" | "reject" Status will fallback and run a normal status scan when a "reject" is reported (unless "--deserialize-wait=fail"). If "ok" is reported, status was able to use the status cache and avoid scanning the workdir. Additionally, a cmd_mode is emitted for each step: collection, deserialization, and serialization. For example, if deserialization is attempted and fails and status falls back to actually computing the status, a cmd_mode message containing "deserialize" is issued and then a cmd_mode for "collect" is issued. Also, if deserialization fails, a data message containing the rejection reason is emitted. Signed-off-by: Jeff Hostetler <[email protected]>
1 parent c9cee1c commit 4b24b82

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

builtin/commit.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
168168
static int do_serialize = 0;
169169
static char *serialize_path = NULL;
170170

171+
static int reject_implicit = 0;
171172
static int do_implicit_deserialize = 0;
172173
static int do_explicit_deserialize = 0;
173174
static char *deserialize_path = NULL;
@@ -231,7 +232,7 @@ static int opt_parse_deserialize(const struct option *opt UNUSED, const char *ar
231232
}
232233
if (!deserialize_path || !*deserialize_path)
233234
do_explicit_deserialize = 1; /* read stdin */
234-
else if (access(deserialize_path, R_OK) == 0)
235+
else if (wt_status_deserialize_access(deserialize_path, R_OK) == 0)
235236
do_explicit_deserialize = 1; /* can read from this file */
236237
else {
237238
/*
@@ -1609,6 +1610,8 @@ static int git_status_config(const char *k, const char *v,
16091610
if (v && *v && access(v, R_OK) == 0) {
16101611
do_implicit_deserialize = 1;
16111612
deserialize_path = xstrdup(v);
1613+
} else {
1614+
reject_implicit = 1;
16121615
}
16131616
return 0;
16141617
}
@@ -1762,6 +1765,17 @@ struct repository *repo UNUSED)
17621765

17631766
if (try_deserialize)
17641767
goto skip_init;
1768+
/*
1769+
* If we implicitly received a status cache pathname from the config
1770+
* and the file does not exist, we silently reject it and do the normal
1771+
* status "collect". Fake up some trace2 messages to reflect this and
1772+
* assist post-processors know this case is different.
1773+
*/
1774+
if (!do_serialize && reject_implicit) {
1775+
trace2_cmd_mode("implicit-deserialize");
1776+
trace2_data_string("status", the_repository, "deserialize/reject",
1777+
"status-cache/access");
1778+
}
17651779

17661780
enable_fscache(0);
17671781
if (status_format != STATUS_FORMAT_PORCELAIN &&
@@ -1805,6 +1819,7 @@ struct repository *repo UNUSED)
18051819
if (s.relative_paths)
18061820
s.prefix = prefix;
18071821

1822+
trace2_cmd_mode("deserialize");
18081823
result = wt_status_deserialize(&s, deserialize_path, dw);
18091824
if (result == DESERIALIZE_OK)
18101825
return 0;
@@ -1822,6 +1837,7 @@ struct repository *repo UNUSED)
18221837
fd = -1;
18231838
}
18241839

1840+
trace2_cmd_mode("collect");
18251841
wt_status_collect(&s);
18261842

18271843
if (0 <= fd)
@@ -1836,6 +1852,7 @@ struct repository *repo UNUSED)
18361852
if (fd_serialize < 0)
18371853
die_errno(_("could not serialize to '%s'"),
18381854
serialize_path);
1855+
trace2_cmd_mode("serialize");
18391856
wt_status_serialize_v1(fd_serialize, &s);
18401857
close(fd_serialize);
18411858
}

wt-status-deserialize.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@
99
#include "statinfo.h"
1010
#include "hex.h"
1111
#include "path.h"
12+
#include "trace2.h"
13+
14+
static void set_deserialize_reject_reason(const char *reason)
15+
{
16+
trace2_data_string("status", the_repository, "deserialize/reject",
17+
reason);
18+
}
19+
20+
int wt_status_deserialize_access(const char *path, int mode)
21+
{
22+
int a = access(path, mode);
23+
24+
if (a != 0)
25+
set_deserialize_reject_reason("status-cache/access");
26+
27+
return a;
28+
}
1229

1330
static struct trace_key trace_deserialize = TRACE_KEY_INIT(DESERIALIZE);
1431

@@ -55,13 +72,15 @@ static int my_validate_index(const char *path, const struct cache_time *mtime_re
5572
struct cache_time mtime_observed_on_disk;
5673

5774
if (lstat(path, &st)) {
75+
set_deserialize_reject_reason("index/not-found");
5876
trace_printf_key(&trace_deserialize, "could not stat index");
5977
return DESERIALIZE_ERR;
6078
}
6179
mtime_observed_on_disk.sec = st.st_mtime;
6280
mtime_observed_on_disk.nsec = ST_MTIME_NSEC(st);
6381
if ((mtime_observed_on_disk.sec != mtime_reported->sec) ||
6482
(mtime_observed_on_disk.nsec != mtime_reported->nsec)) {
83+
set_deserialize_reject_reason("index/mtime-changed");
6584
trace_printf_key(&trace_deserialize,
6685
"index mtime changed [des %d %d][obs %d %d]",
6786
mtime_reported->sec, mtime_reported->nsec,
@@ -87,10 +106,12 @@ static int my_validate_excludes(const char *path, const char *key, const char *l
87106

88107
r = (strcmp(line, sb.buf) ? DESERIALIZE_ERR : DESERIALIZE_OK);
89108

90-
if (r == DESERIALIZE_ERR)
109+
if (r == DESERIALIZE_ERR) {
110+
set_deserialize_reject_reason("excludes/changed");
91111
trace_printf_key(&trace_deserialize,
92112
"%s changed [cached '%s'][observed '%s']",
93113
key, line, sb.buf);
114+
}
94115

95116
strbuf_release(&sb);
96117
return r;
@@ -146,6 +167,7 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
146167
&index_mtime.sec,
147168
&index_mtime.nsec);
148169
if (nr_fields != 2) {
170+
set_deserialize_reject_reason("v1-header/invalid-index-mtime");
149171
trace_printf_key(&trace_deserialize, "invalid index_mtime (%d) '%s'",
150172
nr_fields, line);
151173
return DESERIALIZE_ERR;
@@ -229,6 +251,7 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
229251
/* status_format */
230252
if (skip_prefix(line, "sha1_commit ", &arg)) {
231253
if (get_oid_hex(arg, &s->oid_commit)) {
254+
set_deserialize_reject_reason("v1-header/invalid-commit-sha");
232255
trace_printf_key(&trace_deserialize, "invalid sha1_commit");
233256
return DESERIALIZE_ERR;
234257
}
@@ -244,19 +267,23 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
244267
}
245268
/* prefix */
246269

270+
set_deserialize_reject_reason("v1-header/unexpected-line");
247271
trace_printf_key(&trace_deserialize, "unexpected line '%s'", line);
248272
return DESERIALIZE_ERR;
249273
}
250274

251275
if (!have_required_index_mtime) {
276+
set_deserialize_reject_reason("v1-header/missing-index-mtime");
252277
trace_printf_key(&trace_deserialize, "missing '%s'", "index_mtime");
253278
return DESERIALIZE_ERR;
254279
}
255280
if (!have_required_core_excludes) {
281+
set_deserialize_reject_reason("v1-header/missing-core-excludes");
256282
trace_printf_key(&trace_deserialize, "missing '%s'", "core_excludes");
257283
return DESERIALIZE_ERR;
258284
}
259285
if (!have_required_repo_excludes) {
286+
set_deserialize_reject_reason("v1-header/missing-repo-excludes");
260287
trace_printf_key(&trace_deserialize, "missing '%s'", "repo_excludes");
261288
return DESERIALIZE_ERR;
262289
}
@@ -343,6 +370,7 @@ static int wt_deserialize_v1_changed_items(const struct wt_status *cmd_s,
343370
* So we reject the status cache and let the fallback
344371
* code run.
345372
*/
373+
set_deserialize_reject_reason("v1-data/unmerged");
346374
trace_printf_key(
347375
&trace_deserialize,
348376
"reject: V2 format and umerged file: %s",
@@ -484,13 +512,15 @@ static int wt_deserialize_v1(const struct wt_status *cmd_s, struct wt_status *s,
484512
* the serialized data
485513
*/
486514
if (validate_untracked_files_arg(cmd_s->show_untracked_files, &s->show_untracked_files, &untracked_strategy)) {
515+
set_deserialize_reject_reason("args/untracked-files");
487516
trace_printf_key(&trace_deserialize, "reject: show_untracked_file: command: %d, serialized : %d",
488517
cmd_s->show_untracked_files,
489518
s->show_untracked_files);
490519
return DESERIALIZE_ERR;
491520
}
492521

493522
if (validate_ignored_files_arg(cmd_s->show_ignored_mode, s->show_ignored_mode, &ignored_strategy)) {
523+
set_deserialize_reject_reason("args/ignored-mode");
494524
trace_printf_key(&trace_deserialize, "reject: show_ignored_mode: command: %d, serialized: %d",
495525
cmd_s->show_ignored_mode,
496526
s->show_ignored_mode);
@@ -524,6 +554,7 @@ static int wt_deserialize_v1(const struct wt_status *cmd_s, struct wt_status *s,
524554
return DESERIALIZE_ERR;
525555
continue;
526556
}
557+
set_deserialize_reject_reason("v1-data/unexpected-line");
527558
trace_printf_key(&trace_deserialize, "unexpected line '%s'", line);
528559
return DESERIALIZE_ERR;
529560
}
@@ -543,6 +574,7 @@ static int wt_deserialize_parse(const struct wt_status *cmd_s, struct wt_status
543574
if (version == 1)
544575
return wt_deserialize_v1(cmd_s, s, fd);
545576
}
577+
set_deserialize_reject_reason("status-cache/unsupported-version");
546578
trace_printf_key(&trace_deserialize, "missing/unsupported version");
547579
return DESERIALIZE_ERR;
548580
}
@@ -563,6 +595,7 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
563595
* Check the path spec on the current command
564596
*/
565597
if (cmd_s->pathspec.nr > 1) {
598+
set_deserialize_reject_reason("args/multiple-pathspecs");
566599
trace_printf_key(&trace_deserialize, "reject: multiple pathspecs");
567600
return DESERIALIZE_ERR;
568601
}
@@ -573,6 +606,7 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
573606
*/
574607
if (cmd_s->pathspec.nr == 1 &&
575608
my_strcmp_null(cmd_s->pathspec.items[0].match, "")) {
609+
set_deserialize_reject_reason("args/root-pathspec");
576610
trace_printf_key(&trace_deserialize, "reject: pathspec");
577611
return DESERIALIZE_ERR;
578612
}
@@ -595,20 +629,24 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
595629
* or "--ignored" settings).
596630
*/
597631
if (cmd_s->is_initial != des_s->is_initial) {
632+
set_deserialize_reject_reason("args/is-initial-changed");
598633
trace_printf_key(&trace_deserialize, "reject: is_initial");
599634
return DESERIALIZE_ERR;
600635
}
601636
if (my_strcmp_null(cmd_s->branch, des_s->branch)) {
637+
set_deserialize_reject_reason("args/branch-changed");
602638
trace_printf_key(&trace_deserialize, "reject: branch");
603639
return DESERIALIZE_ERR;
604640
}
605641
if (my_strcmp_null(cmd_s->reference, des_s->reference)) {
642+
set_deserialize_reject_reason("args/reference-changed");
606643
trace_printf_key(&trace_deserialize, "reject: reference");
607644
return DESERIALIZE_ERR;
608645
}
609646
/* verbose */
610647
/* amend */
611648
if (cmd_s->whence != des_s->whence) {
649+
set_deserialize_reject_reason("args/whence-changed");
612650
trace_printf_key(&trace_deserialize, "reject: whence");
613651
return DESERIALIZE_ERR;
614652
}
@@ -642,19 +680,23 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
642680
/* hints */
643681
/* ahead_behind_flags */
644682
if (cmd_s->detect_rename != des_s->detect_rename) {
683+
set_deserialize_reject_reason("args/detect-rename-changed");
645684
trace_printf_key(&trace_deserialize, "reject: detect_rename");
646685
return DESERIALIZE_ERR;
647686
}
648687
if (cmd_s->rename_score != des_s->rename_score) {
688+
set_deserialize_reject_reason("args/rename-score-changed");
649689
trace_printf_key(&trace_deserialize, "reject: rename_score");
650690
return DESERIALIZE_ERR;
651691
}
652692
if (cmd_s->rename_limit != des_s->rename_limit) {
693+
set_deserialize_reject_reason("args/rename-limit-changed");
653694
trace_printf_key(&trace_deserialize, "reject: rename_limit");
654695
return DESERIALIZE_ERR;
655696
}
656697
/* status_format */
657698
if (!oideq(&cmd_s->oid_commit, &des_s->oid_commit)) {
699+
set_deserialize_reject_reason("args/commit-changed");
658700
trace_printf_key(&trace_deserialize, "reject: sha1_commit");
659701
return DESERIALIZE_ERR;
660702
}
@@ -742,15 +784,18 @@ static int try_deserialize_read_from_file(const struct wt_status *cmd_s,
742784
enum wt_status_deserialize_wait dw,
743785
struct wt_status *des_s)
744786
{
745-
int k, limit;
787+
int k = 0;
788+
int limit;
746789
int result = DESERIALIZE_ERR;
747790

748791
/*
749792
* For "fail" or "no", try exactly once to read the status cache.
750793
* Return an error if the file is stale.
751794
*/
752-
if (dw == DESERIALIZE_WAIT__FAIL || dw == DESERIALIZE_WAIT__NO)
753-
return try_deserialize_read_from_file_1(cmd_s, path, des_s);
795+
if (dw == DESERIALIZE_WAIT__FAIL || dw == DESERIALIZE_WAIT__NO) {
796+
result = try_deserialize_read_from_file_1(cmd_s, path, des_s);
797+
goto done;
798+
}
754799

755800
/*
756801
* Wait for the status cache file to refresh. Wait duration can
@@ -775,6 +820,12 @@ static int try_deserialize_read_from_file(const struct wt_status *cmd_s,
775820
sleep_millisec(100);
776821
}
777822

823+
done:
824+
trace2_data_string("status", the_repository, "deserialize/path", path);
825+
trace2_data_intmax("status", the_repository, "deserialize/polled", k);
826+
trace2_data_string("status", the_repository, "deserialize/result",
827+
((result == DESERIALIZE_OK) ? "ok" : "reject"));
828+
778829
trace_printf_key(&trace_deserialize,
779830
"wait polled=%d result=%d '%s'",
780831
k, result, path);
@@ -801,6 +852,8 @@ int wt_status_deserialize(const struct wt_status *cmd_s,
801852
int result;
802853
struct string_list_item *change;
803854

855+
trace2_region_enter("status", "deserialize", the_repository);
856+
804857
if (path && *path && strcmp(path, "0")) {
805858
result = try_deserialize_read_from_file(cmd_s, path, dw, &des_s);
806859
} else {
@@ -811,8 +864,14 @@ int wt_status_deserialize(const struct wt_status *cmd_s,
811864
* term, since we cannot read stdin multiple times.
812865
*/
813866
result = wt_deserialize_fd(cmd_s, &des_s, 0);
867+
868+
trace2_data_string("status", the_repository, "deserialize/path", "STDIN");
869+
trace2_data_string("status", the_repository, "deserialize/result",
870+
((result == DESERIALIZE_OK) ? "ok" : "reject"));
814871
}
815872

873+
trace2_region_leave("status", "deserialize", the_repository);
874+
816875
if (result == DESERIALIZE_OK) {
817876
wt_status_get_state(cmd_s->repo, &des_s.state, des_s.branch &&
818877
!strcmp(des_s.branch, "HEAD"));

wt-status.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ int wt_status_deserialize(const struct wt_status *cmd_s,
246246
const char *path,
247247
enum wt_status_deserialize_wait dw);
248248

249+
int wt_status_deserialize_access(const char *path, int mode);
250+
249251
/*
250252
* A helper routine for serialize and deserialize to compute
251253
* metadata for the user-global and repo-local excludes files.

0 commit comments

Comments
 (0)