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) ? "+" : "-");