Skip to content

Commit 679bf4e

Browse files
committed
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 <[email protected]>
1 parent 0a76bd7 commit 679bf4e

File tree

3 files changed

+34
-19
lines changed

3 files changed

+34
-19
lines changed

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ struct index_state {
324324
struct hashmap dir_hash;
325325
struct object_id oid;
326326
struct untracked_cache *untracked;
327-
uint64_t fsmonitor_last_update;
327+
char *fsmonitor_last_update;
328328
struct ewah_bitmap *fsmonitor_dirty;
329329
struct mem_pool *ce_mem_pool;
330330
struct progress *progress;

fsmonitor.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
#include "run-command.h"
77
#include "strbuf.h"
88

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)
1112

1213
struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
1314

@@ -32,17 +33,26 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data,
3233
uint32_t ewah_size;
3334
struct ewah_bitmap *fsmonitor_dirty;
3435
int ret;
36+
uint64_t timestamp;
37+
struct strbuf last_update = STRBUF_INIT;
3538

36-
if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t))
39+
if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
3740
return error("corrupt fsmonitor extension (too short)");
3841

3942
hdr_version = get_be32(index);
4043
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 {
4252
return error("bad fsmonitor version %d", hdr_version);
53+
}
4354

44-
istate->fsmonitor_last_update = get_be64(index);
45-
index += sizeof(uint64_t);
55+
istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
4656

4757
ewah_size = get_be32(index);
4858
index += sizeof(uint32_t);
@@ -79,7 +89,6 @@ void fill_fsmonitor_bitmap(struct index_state *istate)
7989
void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
8090
{
8191
uint32_t hdr_version;
82-
uint64_t tm;
8392
uint32_t ewah_start;
8493
uint32_t ewah_size = 0;
8594
int fixup = 0;
@@ -89,11 +98,12 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
8998
BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
9099
(uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
91100

92-
put_be32(&hdr_version, INDEX_EXTENSION_VERSION);
101+
put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
93102
strbuf_add(sb, &hdr_version, sizeof(uint32_t));
94103

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+
97107
fixup = sb->len;
98108
strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
99109

@@ -110,9 +120,9 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
110120
}
111121

112122
/*
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.
114124
*/
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)
116126
{
117127
struct child_process cp = CHILD_PROCESS_INIT;
118128

@@ -121,7 +131,7 @@ static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *que
121131

122132
argv_array_push(&cp.args, core_fsmonitor);
123133
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);
125135
cp.use_shell = 1;
126136
cp.dir = get_git_work_tree();
127137

@@ -151,6 +161,7 @@ void refresh_fsmonitor(struct index_state *istate)
151161
int query_success = 0;
152162
size_t bol; /* beginning of line */
153163
uint64_t last_update;
164+
struct strbuf last_update_token = STRBUF_INIT;
154165
char *buf;
155166
unsigned int i;
156167

@@ -164,6 +175,7 @@ void refresh_fsmonitor(struct index_state *istate)
164175
* should be inclusive to ensure we don't miss potential changes.
165176
*/
166177
last_update = getnanotime();
178+
strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
167179

168180
/*
169181
* 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)
217229
}
218230
strbuf_release(&query_result);
219231

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);
222235
}
223236

224237
void add_fsmonitor(struct index_state *istate)
225238
{
226239
unsigned int i;
240+
struct strbuf last_update = STRBUF_INIT;
227241

228242
if (!istate->fsmonitor_last_update) {
229243
trace_printf_key(&trace_fsmonitor, "add fsmonitor");
230244
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);
232247

233248
/* reset the fsmonitor state */
234249
for (i = 0; i < istate->cache_nr; i++)
@@ -250,7 +265,7 @@ void remove_fsmonitor(struct index_state *istate)
250265
if (istate->fsmonitor_last_update) {
251266
trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
252267
istate->cache_changed |= FSMONITOR_CHANGED;
253-
istate->fsmonitor_last_update = 0;
268+
FREE_AND_NULL(istate->fsmonitor_last_update);
254269
}
255270
}
256271

t/helper/test-dump-fsmonitor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ int cmd__dump_fsmonitor(int ac, const char **av)
1313
printf("no fsmonitor\n");
1414
return 0;
1515
}
16-
printf("fsmonitor last update %"PRIuMAX"\n", (uintmax_t)istate->fsmonitor_last_update);
16+
printf("fsmonitor last update %s\n", istate->fsmonitor_last_update);
1717

1818
for (i = 0; i < istate->cache_nr; i++)
1919
printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+" : "-");

0 commit comments

Comments
 (0)