@matheusbsbs / matheus-bagliano / commits / 56c6910028
Fork 0

fsmonitor: change last update timestamp on the index_state to opaque token

Some file system monitors might not use or take a timestamp for processing and in the case of watchman could have race conditions with using a timestamp. Watchman uses something called a clockid that is used for race free queries to it. The clockid for watchman is simply a string. Change the fsmonitor_last_update from being a uint64_t to a char pointer so that any arbitrary data can be stored in it and passed back to the fsmonitor. Signed-off-by: Kevin Willford <Kevin.Willford@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Kevin Willford committed Jan 7, 2020 at 19:04 UTC 56c6910028a0468761b0cd9ee5c0946ce637b586
3 files changed +34 -19
cache.h
+1 -1
@@ -324,7 +324,7 @@ struct index_state {
324 struct hashmap dir_hash;
325 struct object_id oid;
326 struct untracked_cache *untracked;
327 - uint64_t fsmonitor_last_update;
327 + char *fsmonitor_last_update;
328 struct ewah_bitmap *fsmonitor_dirty;
329 struct mem_pool *ce_mem_pool;
330 struct progress *progress;
fsmonitor.c
+32 -17
@@ -6,8 +6,9 @@
6 #include "run-command.h"
7 #include "strbuf.h"
8
9 -#define INDEX_EXTENSION_VERSION (1)
10 -#define HOOK_INTERFACE_VERSION (1)
9 +#define INDEX_EXTENSION_VERSION1 (1)
10 +#define INDEX_EXTENSION_VERSION2 (2)
11 +#define HOOK_INTERFACE_VERSION (1)
12
13 struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
14
@@ -32,17 +33,26 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data,
33 uint32_t ewah_size;
34 struct ewah_bitmap *fsmonitor_dirty;
35 int ret;
36 + uint64_t timestamp;
37 + struct strbuf last_update = STRBUF_INIT;
38
36 - if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t))
39 + if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
40 return error("corrupt fsmonitor extension (too short)");
41
42 hdr_version = get_be32(index);
43 index += sizeof(uint32_t);
41 - if (hdr_version != INDEX_EXTENSION_VERSION)
44 + if (hdr_version == INDEX_EXTENSION_VERSION1) {
45 + timestamp = get_be64(index);
46 + strbuf_addf(&last_update, "%"PRIu64"", timestamp);
47 + index += sizeof(uint64_t);
48 + } else if (hdr_version == INDEX_EXTENSION_VERSION2) {
49 + strbuf_addstr(&last_update, index);
50 + index += last_update.len + 1;
51 + } else {
52 return error("bad fsmonitor version %d", hdr_version);
53 + }
54
44 - istate->fsmonitor_last_update = get_be64(index);
45 - index += sizeof(uint64_t);
55 + istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
56
57 ewah_size = get_be32(index);
58 index += sizeof(uint32_t);
@@ -79,7 +89,6 @@ void fill_fsmonitor_bitmap(struct index_state *istate)
89 void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
90 {
91 uint32_t hdr_version;
82 - uint64_t tm;
92 uint32_t ewah_start;
93 uint32_t ewah_size = 0;
94 int fixup = 0;
@@ -89,11 +98,12 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
98 BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
99 (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
100
92 - put_be32(&hdr_version, INDEX_EXTENSION_VERSION);
101 + put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
102 strbuf_add(sb, &hdr_version, sizeof(uint32_t));
103
95 - put_be64(&tm, istate->fsmonitor_last_update);
96 - strbuf_add(sb, &tm, sizeof(uint64_t));
104 + strbuf_addstr(sb, istate->fsmonitor_last_update);
105 + strbuf_addch(sb, 0); /* Want to keep a NUL */
106 +
107 fixup = sb->len;
108 strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
109
@@ -110,9 +120,9 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
120 }
121
122 /*
113 - * Call the query-fsmonitor hook passing the time of the last saved results.
123 + * Call the query-fsmonitor hook passing the last update token of the saved results.
124 */
115 -static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *query_result)
125 +static int query_fsmonitor(int version, const char *last_update, struct strbuf *query_result)
126 {
127 struct child_process cp = CHILD_PROCESS_INIT;
128
@@ -121,7 +131,7 @@ static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *que
131
132 argv_array_push(&cp.args, core_fsmonitor);
133 argv_array_pushf(&cp.args, "%d", version);
124 - argv_array_pushf(&cp.args, "%" PRIuMAX, (uintmax_t)last_update);
134 + argv_array_pushf(&cp.args, "%s", last_update);
135 cp.use_shell = 1;
136 cp.dir = get_git_work_tree();
137
@@ -151,6 +161,7 @@ void refresh_fsmonitor(struct index_state *istate)
161 int query_success = 0;
162 size_t bol; /* beginning of line */
163 uint64_t last_update;
164 + struct strbuf last_update_token = STRBUF_INIT;
165 char *buf;
166 unsigned int i;
167
@@ -164,6 +175,7 @@ void refresh_fsmonitor(struct index_state *istate)
175 * should be inclusive to ensure we don't miss potential changes.
176 */
177 last_update = getnanotime();
178 + strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
179
180 /*
181 * If we have a last update time, call query_fsmonitor for the set of
@@ -217,18 +229,21 @@ void refresh_fsmonitor(struct index_state *istate)
229 }
230 strbuf_release(&query_result);
231
220 - /* Now that we've updated istate, save the last_update time */
221 - istate->fsmonitor_last_update = last_update;
232 + /* Now that we've updated istate, save the last_update_token */
233 + FREE_AND_NULL(istate->fsmonitor_last_update);
234 + istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);
235 }
236
237 void add_fsmonitor(struct index_state *istate)
238 {
239 unsigned int i;
240 + struct strbuf last_update = STRBUF_INIT;
241
242 if (!istate->fsmonitor_last_update) {
243 trace_printf_key(&trace_fsmonitor, "add fsmonitor");
244 istate->cache_changed |= FSMONITOR_CHANGED;
231 - istate->fsmonitor_last_update = getnanotime();
245 + strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
246 + istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
247
248 /* reset the fsmonitor state */
249 for (i = 0; i < istate->cache_nr; i++)
@@ -250,7 +265,7 @@ void remove_fsmonitor(struct index_state *istate)
265 if (istate->fsmonitor_last_update) {
266 trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
267 istate->cache_changed |= FSMONITOR_CHANGED;
253 - istate->fsmonitor_last_update = 0;
268 + FREE_AND_NULL(istate->fsmonitor_last_update);
269 }
270 }
271
t/helper/test-dump-fsmonitor.c
+1 -1
@@ -13,7 +13,7 @@ int cmd__dump_fsmonitor(int ac, const char **av)
13 printf("no fsmonitor\n");
14 return 0;
15 }
16 - printf("fsmonitor last update %"PRIuMAX"\n", (uintmax_t)istate->fsmonitor_last_update);
16 + printf("fsmonitor last update %s\n", istate->fsmonitor_last_update);
17
18 for (i = 0; i < istate->cache_nr; i++)
19 printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+" : "-");