Skip to content

Commit 87422f2

Browse files
jeffhostetlervdye
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 <jeffhost@microsoft.com>
1 parent 86c7169 commit 87422f2

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
@@ -176,6 +176,7 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
176176
static int do_serialize = 0;
177177
static char *serialize_path = NULL;
178178

179+
static int reject_implicit = 0;
179180
static int do_implicit_deserialize = 0;
180181
static int do_explicit_deserialize = 0;
181182
static char *deserialize_path = NULL;
@@ -239,7 +240,7 @@ static int opt_parse_deserialize(const struct option *opt, const char *arg, int
239240
}
240241
if (!deserialize_path || !*deserialize_path)
241242
do_explicit_deserialize = 1; /* read stdin */
242-
else if (access(deserialize_path, R_OK) == 0)
243+
else if (wt_status_deserialize_access(deserialize_path, R_OK) == 0)
243244
do_explicit_deserialize = 1; /* can read from this file */
244245
else {
245246
/*
@@ -1587,6 +1588,8 @@ static int git_status_config(const char *k, const char *v, void *cb)
15871588
if (v && *v && access(v, R_OK) == 0) {
15881589
do_implicit_deserialize = 1;
15891590
deserialize_path = xstrdup(v);
1591+
} else {
1592+
reject_implicit = 1;
15901593
}
15911594
return 0;
15921595
}
@@ -1741,6 +1744,17 @@ int cmd_status(int argc, const char **argv, const char *prefix)
17411744

17421745
if (try_deserialize)
17431746
goto skip_init;
1747+
/*
1748+
* If we implicitly received a status cache pathname from the config
1749+
* and the file does not exist, we silently reject it and do the normal
1750+
* status "collect". Fake up some trace2 messages to reflect this and
1751+
* assist post-processors know this case is different.
1752+
*/
1753+
if (!do_serialize && reject_implicit) {
1754+
trace2_cmd_mode("implicit-deserialize");
1755+
trace2_data_string("status", the_repository, "deserialize/reject",
1756+
"status-cache/access");
1757+
}
17441758

17451759
enable_fscache(0);
17461760
if (status_format != STATUS_FORMAT_PORCELAIN &&
@@ -1784,6 +1798,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
17841798
if (s.relative_paths)
17851799
s.prefix = prefix;
17861800

1801+
trace2_cmd_mode("deserialize");
17871802
result = wt_status_deserialize(&s, deserialize_path, dw);
17881803
if (result == DESERIALIZE_OK)
17891804
return 0;
@@ -1801,6 +1816,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
18011816
fd = -1;
18021817
}
18031818

1819+
trace2_cmd_mode("collect");
18041820
wt_status_collect(&s);
18051821

18061822
if (0 <= fd)
@@ -1815,6 +1831,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
18151831
if (fd_serialize < 0)
18161832
die_errno(_("could not serialize to '%s'"),
18171833
serialize_path);
1834+
trace2_cmd_mode("serialize");
18181835
wt_status_serialize_v1(fd_serialize, &s);
18191836
close(fd_serialize);
18201837
}

wt-status-deserialize.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@
66
#include "wt-status.h"
77
#include "pkt-line.h"
88
#include "trace.h"
9+
#include "trace2.h"
10+
11+
static void set_deserialize_reject_reason(const char *reason)
12+
{
13+
trace2_data_string("status", the_repository, "deserialize/reject",
14+
reason);
15+
}
16+
17+
int wt_status_deserialize_access(const char *path, int mode)
18+
{
19+
int a = access(path, mode);
20+
21+
if (a != 0)
22+
set_deserialize_reject_reason("status-cache/access");
23+
24+
return a;
25+
}
926

1027
static struct trace_key trace_deserialize = TRACE_KEY_INIT(DESERIALIZE);
1128

@@ -53,13 +70,15 @@ static int my_validate_index(const struct cache_time *mtime_reported)
5370
struct cache_time mtime_observed_on_disk;
5471

5572
if (lstat(path, &st)) {
73+
set_deserialize_reject_reason("index/not-found");
5674
trace_printf_key(&trace_deserialize, "could not stat index");
5775
return DESERIALIZE_ERR;
5876
}
5977
mtime_observed_on_disk.sec = st.st_mtime;
6078
mtime_observed_on_disk.nsec = ST_MTIME_NSEC(st);
6179
if ((mtime_observed_on_disk.sec != mtime_reported->sec) ||
6280
(mtime_observed_on_disk.nsec != mtime_reported->nsec)) {
81+
set_deserialize_reject_reason("index/mtime-changed");
6382
trace_printf_key(&trace_deserialize,
6483
"index mtime changed [des %d %d][obs %d %d]",
6584
mtime_reported->sec, mtime_reported->nsec,
@@ -85,10 +104,12 @@ static int my_validate_excludes(const char *path, const char *key, const char *l
85104

86105
r = (strcmp(line, sb.buf) ? DESERIALIZE_ERR : DESERIALIZE_OK);
87106

88-
if (r == DESERIALIZE_ERR)
107+
if (r == DESERIALIZE_ERR) {
108+
set_deserialize_reject_reason("excludes/changed");
89109
trace_printf_key(&trace_deserialize,
90110
"%s changed [cached '%s'][observed '%s']",
91111
key, line, sb.buf);
112+
}
92113

93114
strbuf_release(&sb);
94115
return r;
@@ -144,6 +165,7 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
144165
&index_mtime.sec,
145166
&index_mtime.nsec);
146167
if (nr_fields != 2) {
168+
set_deserialize_reject_reason("v1-header/invalid-index-mtime");
147169
trace_printf_key(&trace_deserialize, "invalid index_mtime (%d) '%s'",
148170
nr_fields, line);
149171
return DESERIALIZE_ERR;
@@ -227,6 +249,7 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
227249
/* status_format */
228250
if (skip_prefix(line, "sha1_commit ", &arg)) {
229251
if (get_oid_hex(arg, &s->oid_commit)) {
252+
set_deserialize_reject_reason("v1-header/invalid-commit-sha");
230253
trace_printf_key(&trace_deserialize, "invalid sha1_commit");
231254
return DESERIALIZE_ERR;
232255
}
@@ -242,19 +265,23 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
242265
}
243266
/* prefix */
244267

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

249273
if (!have_required_index_mtime) {
274+
set_deserialize_reject_reason("v1-header/missing-index-mtime");
250275
trace_printf_key(&trace_deserialize, "missing '%s'", "index_mtime");
251276
return DESERIALIZE_ERR;
252277
}
253278
if (!have_required_core_excludes) {
279+
set_deserialize_reject_reason("v1-header/missing-core-excludes");
254280
trace_printf_key(&trace_deserialize, "missing '%s'", "core_excludes");
255281
return DESERIALIZE_ERR;
256282
}
257283
if (!have_required_repo_excludes) {
284+
set_deserialize_reject_reason("v1-header/missing-repo-excludes");
258285
trace_printf_key(&trace_deserialize, "missing '%s'", "repo_excludes");
259286
return DESERIALIZE_ERR;
260287
}
@@ -341,6 +368,7 @@ static int wt_deserialize_v1_changed_items(const struct wt_status *cmd_s,
341368
* So we reject the status cache and let the fallback
342369
* code run.
343370
*/
371+
set_deserialize_reject_reason("v1-data/unmerged");
344372
trace_printf_key(
345373
&trace_deserialize,
346374
"reject: V2 format and umerged file: %s",
@@ -482,13 +510,15 @@ static int wt_deserialize_v1(const struct wt_status *cmd_s, struct wt_status *s,
482510
* the serialized data
483511
*/
484512
if (validate_untracked_files_arg(cmd_s->show_untracked_files, &s->show_untracked_files, &untracked_strategy)) {
513+
set_deserialize_reject_reason("args/untracked-files");
485514
trace_printf_key(&trace_deserialize, "reject: show_untracked_file: command: %d, serialized : %d",
486515
cmd_s->show_untracked_files,
487516
s->show_untracked_files);
488517
return DESERIALIZE_ERR;
489518
}
490519

491520
if (validate_ignored_files_arg(cmd_s->show_ignored_mode, s->show_ignored_mode, &ignored_strategy)) {
521+
set_deserialize_reject_reason("args/ignored-mode");
492522
trace_printf_key(&trace_deserialize, "reject: show_ignored_mode: command: %d, serialized: %d",
493523
cmd_s->show_ignored_mode,
494524
s->show_ignored_mode);
@@ -522,6 +552,7 @@ static int wt_deserialize_v1(const struct wt_status *cmd_s, struct wt_status *s,
522552
return DESERIALIZE_ERR;
523553
continue;
524554
}
555+
set_deserialize_reject_reason("v1-data/unexpected-line");
525556
trace_printf_key(&trace_deserialize, "unexpected line '%s'", line);
526557
return DESERIALIZE_ERR;
527558
}
@@ -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
}
@@ -589,20 +623,24 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
589623
* or "--ignored" settings).
590624
*/
591625
if (cmd_s->is_initial != des_s->is_initial) {
626+
set_deserialize_reject_reason("args/is-initial-changed");
592627
trace_printf_key(&trace_deserialize, "reject: is_initial");
593628
return DESERIALIZE_ERR;
594629
}
595630
if (my_strcmp_null(cmd_s->branch, des_s->branch)) {
631+
set_deserialize_reject_reason("args/branch-changed");
596632
trace_printf_key(&trace_deserialize, "reject: branch");
597633
return DESERIALIZE_ERR;
598634
}
599635
if (my_strcmp_null(cmd_s->reference, des_s->reference)) {
636+
set_deserialize_reject_reason("args/reference-changed");
600637
trace_printf_key(&trace_deserialize, "reject: reference");
601638
return DESERIALIZE_ERR;
602639
}
603640
/* verbose */
604641
/* amend */
605642
if (cmd_s->whence != des_s->whence) {
643+
set_deserialize_reject_reason("args/whence-changed");
606644
trace_printf_key(&trace_deserialize, "reject: whence");
607645
return DESERIALIZE_ERR;
608646
}
@@ -636,19 +674,23 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
636674
/* hints */
637675
/* ahead_behind_flags */
638676
if (cmd_s->detect_rename != des_s->detect_rename) {
677+
set_deserialize_reject_reason("args/detect-rename-changed");
639678
trace_printf_key(&trace_deserialize, "reject: detect_rename");
640679
return DESERIALIZE_ERR;
641680
}
642681
if (cmd_s->rename_score != des_s->rename_score) {
682+
set_deserialize_reject_reason("args/rename-score-changed");
643683
trace_printf_key(&trace_deserialize, "reject: rename_score");
644684
return DESERIALIZE_ERR;
645685
}
646686
if (cmd_s->rename_limit != des_s->rename_limit) {
687+
set_deserialize_reject_reason("args/rename-limit-changed");
647688
trace_printf_key(&trace_deserialize, "reject: rename_limit");
648689
return DESERIALIZE_ERR;
649690
}
650691
/* status_format */
651692
if (!oideq(&cmd_s->oid_commit, &des_s->oid_commit)) {
693+
set_deserialize_reject_reason("args/commit-changed");
652694
trace_printf_key(&trace_deserialize, "reject: sha1_commit");
653695
return DESERIALIZE_ERR;
654696
}
@@ -737,15 +779,18 @@ static int try_deserialize_read_from_file(const struct wt_status *cmd_s,
737779
enum wt_status_deserialize_wait dw,
738780
struct wt_status *des_s)
739781
{
740-
int k, limit;
782+
int k = 0;
783+
int limit;
741784
int result = DESERIALIZE_ERR;
742785

743786
/*
744787
* For "fail" or "no", try exactly once to read the status cache.
745788
* Return an error if the file is stale.
746789
*/
747-
if (dw == DESERIALIZE_WAIT__FAIL || dw == DESERIALIZE_WAIT__NO)
748-
return try_deserialize_read_from_file_1(cmd_s, path, des_s);
790+
if (dw == DESERIALIZE_WAIT__FAIL || dw == DESERIALIZE_WAIT__NO) {
791+
result = try_deserialize_read_from_file_1(cmd_s, path, des_s);
792+
goto done;
793+
}
749794

750795
/*
751796
* Wait for the status cache file to refresh. Wait duration can
@@ -770,6 +815,12 @@ static int try_deserialize_read_from_file(const struct wt_status *cmd_s,
770815
sleep_millisec(100);
771816
}
772817

818+
done:
819+
trace2_data_string("status", the_repository, "deserialize/path", path);
820+
trace2_data_intmax("status", the_repository, "deserialize/polled", k);
821+
trace2_data_string("status", the_repository, "deserialize/result",
822+
((result == DESERIALIZE_OK) ? "ok" : "reject"));
823+
773824
trace_printf_key(&trace_deserialize,
774825
"wait polled=%d result=%d '%s'",
775826
k, result, path);
@@ -795,6 +846,8 @@ int wt_status_deserialize(const struct wt_status *cmd_s,
795846
struct wt_status des_s;
796847
int result;
797848

849+
trace2_region_enter("status", "deserialize", the_repository);
850+
798851
if (path && *path && strcmp(path, "0")) {
799852
result = try_deserialize_read_from_file(cmd_s, path, dw, &des_s);
800853
} else {
@@ -805,8 +858,14 @@ int wt_status_deserialize(const struct wt_status *cmd_s,
805858
* term, since we cannot read stdin multiple times.
806859
*/
807860
result = wt_deserialize_fd(cmd_s, &des_s, 0);
861+
862+
trace2_data_string("status", the_repository, "deserialize/path", "STDIN");
863+
trace2_data_string("status", the_repository, "deserialize/result",
864+
((result == DESERIALIZE_OK) ? "ok" : "reject"));
808865
}
809866

867+
trace2_region_leave("status", "deserialize", the_repository);
868+
810869
if (result == DESERIALIZE_OK) {
811870
wt_status_get_state(cmd_s->repo, &des_s.state, des_s.branch &&
812871
!strcmp(des_s.branch, "HEAD"));

wt-status.h

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

246+
int wt_status_deserialize_access(const char *path, int mode);
247+
246248
/*
247249
* A helper routine for serialize and deserialize to compute
248250
* metadata for the user-global and repo-local excludes files.

0 commit comments

Comments
 (0)