Git fork

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>

authored by

Kevin Willford and committed by
Junio C Hamano
56c69100 d0654dc3

+34 -19
+1 -1
cache.h
··· 324 324 struct hashmap dir_hash; 325 325 struct object_id oid; 326 326 struct untracked_cache *untracked; 327 - uint64_t fsmonitor_last_update; 327 + char *fsmonitor_last_update; 328 328 struct ewah_bitmap *fsmonitor_dirty; 329 329 struct mem_pool *ce_mem_pool; 330 330 struct progress *progress;
+32 -17
fsmonitor.c
··· 6 6 #include "run-command.h" 7 7 #include "strbuf.h" 8 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) 11 12 12 13 struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR); 13 14 ··· 32 33 uint32_t ewah_size; 33 34 struct ewah_bitmap *fsmonitor_dirty; 34 35 int ret; 36 + uint64_t timestamp; 37 + struct strbuf last_update = STRBUF_INIT; 35 38 36 - if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t)) 39 + if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t)) 37 40 return error("corrupt fsmonitor extension (too short)"); 38 41 39 42 hdr_version = get_be32(index); 40 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 { 42 52 return error("bad fsmonitor version %d", hdr_version); 53 + } 43 54 44 - istate->fsmonitor_last_update = get_be64(index); 45 - index += sizeof(uint64_t); 55 + istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL); 46 56 47 57 ewah_size = get_be32(index); 48 58 index += sizeof(uint32_t); ··· 79 89 void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) 80 90 { 81 91 uint32_t hdr_version; 82 - uint64_t tm; 83 92 uint32_t ewah_start; 84 93 uint32_t ewah_size = 0; 85 94 int fixup = 0; ··· 89 98 BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)", 90 99 (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr); 91 100 92 - put_be32(&hdr_version, INDEX_EXTENSION_VERSION); 101 + put_be32(&hdr_version, INDEX_EXTENSION_VERSION2); 93 102 strbuf_add(sb, &hdr_version, sizeof(uint32_t)); 94 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 + 97 107 fixup = sb->len; 98 108 strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */ 99 109 ··· 110 120 } 111 121 112 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. 114 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) 116 126 { 117 127 struct child_process cp = CHILD_PROCESS_INIT; 118 128 ··· 121 131 122 132 argv_array_push(&cp.args, core_fsmonitor); 123 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); 125 135 cp.use_shell = 1; 126 136 cp.dir = get_git_work_tree(); 127 137 ··· 151 161 int query_success = 0; 152 162 size_t bol; /* beginning of line */ 153 163 uint64_t last_update; 164 + struct strbuf last_update_token = STRBUF_INIT; 154 165 char *buf; 155 166 unsigned int i; 156 167 ··· 164 175 * should be inclusive to ensure we don't miss potential changes. 165 176 */ 166 177 last_update = getnanotime(); 178 + strbuf_addf(&last_update_token, "%"PRIu64"", last_update); 167 179 168 180 /* 169 181 * If we have a last update time, call query_fsmonitor for the set of ··· 217 229 } 218 230 strbuf_release(&query_result); 219 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); 222 235 } 223 236 224 237 void add_fsmonitor(struct index_state *istate) 225 238 { 226 239 unsigned int i; 240 + struct strbuf last_update = STRBUF_INIT; 227 241 228 242 if (!istate->fsmonitor_last_update) { 229 243 trace_printf_key(&trace_fsmonitor, "add fsmonitor"); 230 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); 232 247 233 248 /* reset the fsmonitor state */ 234 249 for (i = 0; i < istate->cache_nr; i++) ··· 250 265 if (istate->fsmonitor_last_update) { 251 266 trace_printf_key(&trace_fsmonitor, "remove fsmonitor"); 252 267 istate->cache_changed |= FSMONITOR_CHANGED; 253 - istate->fsmonitor_last_update = 0; 268 + FREE_AND_NULL(istate->fsmonitor_last_update); 254 269 } 255 270 } 256 271
+1 -1
t/helper/test-dump-fsmonitor.c
··· 13 13 printf("no fsmonitor\n"); 14 14 return 0; 15 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 17 18 18 for (i = 0; i < istate->cache_nr; i++) 19 19 printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+" : "-");