Merge branch 'ab/config-based-hooks-base' into seen
[git] / fsmonitor.c
1 #include "cache.h"
2 #include "config.h"
3 #include "dir.h"
4 #include "ewah/ewok.h"
5 #include "fsmonitor.h"
6 #include "fsmonitor-ipc.h"
7 #include "run-command.h"
8 #include "strbuf.h"
9
10 #define INDEX_EXTENSION_VERSION1        (1)
11 #define INDEX_EXTENSION_VERSION2        (2)
12 #define HOOK_INTERFACE_VERSION1         (1)
13 #define HOOK_INTERFACE_VERSION2         (2)
14
15 struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
16
17 static void assert_index_minimum(struct index_state *istate, size_t pos)
18 {
19         if (pos > istate->cache_nr)
20                 BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
21                     (uintmax_t)pos, istate->cache_nr);
22 }
23
24 static void fsmonitor_ewah_callback(size_t pos, void *is)
25 {
26         struct index_state *istate = (struct index_state *)is;
27         struct cache_entry *ce;
28
29         assert_index_minimum(istate, pos + 1);
30
31         ce = istate->cache[pos];
32         ce->ce_flags &= ~CE_FSMONITOR_VALID;
33 }
34
35 static int fsmonitor_hook_version(void)
36 {
37         int hook_version;
38
39         if (git_config_get_int("core.fsmonitorhookversion", &hook_version))
40                 return -1;
41
42         if (hook_version == HOOK_INTERFACE_VERSION1 ||
43             hook_version == HOOK_INTERFACE_VERSION2)
44                 return hook_version;
45
46         warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
47                 "Must be 1 or 2.", hook_version);
48         return -1;
49 }
50
51 int read_fsmonitor_extension(struct index_state *istate, const void *data,
52         unsigned long sz)
53 {
54         const char *index = data;
55         uint32_t hdr_version;
56         uint32_t ewah_size;
57         struct ewah_bitmap *fsmonitor_dirty;
58         int ret;
59         uint64_t timestamp;
60         struct strbuf last_update = STRBUF_INIT;
61
62         if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
63                 return error("corrupt fsmonitor extension (too short)");
64
65         hdr_version = get_be32(index);
66         index += sizeof(uint32_t);
67         if (hdr_version == INDEX_EXTENSION_VERSION1) {
68                 timestamp = get_be64(index);
69                 strbuf_addf(&last_update, "%"PRIu64"", timestamp);
70                 index += sizeof(uint64_t);
71         } else if (hdr_version == INDEX_EXTENSION_VERSION2) {
72                 strbuf_addstr(&last_update, index);
73                 index += last_update.len + 1;
74         } else {
75                 return error("bad fsmonitor version %d", hdr_version);
76         }
77
78         istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
79
80         ewah_size = get_be32(index);
81         index += sizeof(uint32_t);
82
83         fsmonitor_dirty = ewah_new();
84         ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
85         if (ret != ewah_size) {
86                 ewah_free(fsmonitor_dirty);
87                 return error("failed to parse ewah bitmap reading fsmonitor index extension");
88         }
89         istate->fsmonitor_dirty = fsmonitor_dirty;
90
91         if (!istate->split_index)
92                 assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
93
94         trace2_data_string("index", NULL, "extension/fsmn/read/token",
95                            istate->fsmonitor_last_update);
96         trace_printf_key(&trace_fsmonitor,
97                          "read fsmonitor extension successful '%s'",
98                          istate->fsmonitor_last_update);
99         return 0;
100 }
101
102 void fill_fsmonitor_bitmap(struct index_state *istate)
103 {
104         unsigned int i, skipped = 0;
105         istate->fsmonitor_dirty = ewah_new();
106         for (i = 0; i < istate->cache_nr; i++) {
107                 if (istate->cache[i]->ce_flags & CE_REMOVE)
108                         skipped++;
109                 else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
110                         ewah_set(istate->fsmonitor_dirty, i - skipped);
111         }
112 }
113
114 void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
115 {
116         uint32_t hdr_version;
117         uint32_t ewah_start;
118         uint32_t ewah_size = 0;
119         int fixup = 0;
120
121         if (!istate->split_index)
122                 assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
123
124         put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
125         strbuf_add(sb, &hdr_version, sizeof(uint32_t));
126
127         strbuf_addstr(sb, istate->fsmonitor_last_update);
128         strbuf_addch(sb, 0); /* Want to keep a NUL */
129
130         fixup = sb->len;
131         strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
132
133         ewah_start = sb->len;
134         ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
135         ewah_free(istate->fsmonitor_dirty);
136         istate->fsmonitor_dirty = NULL;
137
138         /* fix up size field */
139         put_be32(&ewah_size, sb->len - ewah_start);
140         memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
141
142         trace2_data_string("index", NULL, "extension/fsmn/write/token",
143                            istate->fsmonitor_last_update);
144         trace_printf_key(&trace_fsmonitor,
145                          "write fsmonitor extension successful '%s'",
146                          istate->fsmonitor_last_update);
147 }
148
149 /*
150  * Call the query-fsmonitor hook passing the last update token of the saved results.
151  */
152 static int query_fsmonitor(int version, const char *last_update, struct strbuf *query_result)
153 {
154         struct child_process cp = CHILD_PROCESS_INIT;
155         int result;
156
157         if (!core_fsmonitor)
158                 return -1;
159
160         strvec_push(&cp.args, core_fsmonitor);
161         strvec_pushf(&cp.args, "%d", version);
162         strvec_pushf(&cp.args, "%s", last_update);
163         cp.use_shell = 1;
164         cp.dir = get_git_work_tree();
165
166         trace2_region_enter("fsm_hook", "query", NULL);
167
168         result = capture_command(&cp, query_result, 1024);
169
170         if (result)
171                 trace2_data_intmax("fsm_hook", NULL, "query/failed", result);
172         else {
173                 trace2_data_intmax("fsm_hook", NULL, "query/response-length",
174                                    query_result->len);
175
176                 if (fsmonitor_is_trivial_response(query_result))
177                         trace2_data_intmax("fsm_hook", NULL,
178                                            "query/trivial-response", 1);
179         }
180
181         trace2_region_leave("fsm_hook", "query", NULL);
182
183         return result;
184 }
185
186 int fsmonitor_is_trivial_response(const struct strbuf *query_result)
187 {
188         static char trivial_response[3] = { '\0', '/', '\0' };
189
190         return query_result->len >= 3 &&
191                 !memcmp(trivial_response,
192                         &query_result->buf[query_result->len - 3], 3);
193 }
194
195 static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
196 {
197         int i, len = strlen(name);
198         if (name[len - 1] == '/') {
199
200                 /*
201                  * TODO We should binary search to find the first path with
202                  * TODO this directory prefix.  Then linearly update entries
203                  * TODO while the prefix matches.  Taking care to search without
204                  * TODO the trailing slash -- because '/' sorts after a few
205                  * TODO interesting special chars, like '.' and ' '.
206                  */
207
208                 /* Mark all entries for the folder invalid */
209                 for (i = 0; i < istate->cache_nr; i++) {
210                         if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID &&
211                             starts_with(istate->cache[i]->name, name))
212                                 istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
213                 }
214                 /* Need to remove the / from the path for the untracked cache */
215                 name[len - 1] = '\0';
216         } else {
217                 int pos = index_name_pos(istate, name, strlen(name));
218
219                 if (pos >= 0) {
220                         struct cache_entry *ce = istate->cache[pos];
221                         ce->ce_flags &= ~CE_FSMONITOR_VALID;
222                 }
223         }
224
225         /*
226          * Mark the untracked cache dirty even if it wasn't found in the index
227          * as it could be a new untracked file.
228          */
229         trace_printf_key(&trace_fsmonitor, "fsmonitor_refresh_callback '%s'", name);
230         untracked_cache_invalidate_path(istate, name, 0);
231 }
232
233 /*
234  * The number of pathnames that we need to receive from FSMonitor
235  * before we force the index to be updated.
236  *
237  * Note that any pathname within the set of received paths MAY cause
238  * cache-entry or istate flag bits to be updated and thus cause the
239  * index to be updated on disk.
240  *
241  * However, the response may contain many paths (such as ignored
242  * paths) that will not update any flag bits.  And thus not force the
243  * index to be updated.  (This is fine and normal.)  It also means
244  * that the token will not be updated in the FSMonitor index
245  * extension.  So the next Git command will find the same token in the
246  * index, make the same token-relative request, and receive the same
247  * response (plus any newly changed paths).  If this response is large
248  * (and continues to grow), performance could be impacted.
249  *
250  * For example, if the user runs a build and it writes 100K object
251  * files but doesn't modify any source files, the index would not need
252  * to be updated.  The FSMonitor response (after the build and
253  * relative to a pre-build token) might be 5MB.  Each subsequent Git
254  * command will receive that same 100K/5MB response until something
255  * causes the index to be updated.  And `refresh_fsmonitor()` will
256  * have to iterate over those 100K paths each time.
257  *
258  * Performance could be improved if we optionally force update the
259  * index after a very large response and get an updated token into
260  * the FSMonitor index extension.  This should allow subsequent
261  * commands to get smaller and more current responses.
262  *
263  * The value chosen here does not need to be precise.  The index
264  * will be updated automatically the first time the user touches
265  * a tracked file and causes a command like `git status` to
266  * update an mtime to be updated and/or set a flag bit.
267  *
268  * NEEDSWORK: Does this need to be a config value?
269  */
270 static int fsmonitor_force_update_threshold = 100;
271
272 void refresh_fsmonitor(struct index_state *istate)
273 {
274         struct repository *r = istate->repo ? istate->repo : the_repository;
275         struct strbuf query_result = STRBUF_INIT;
276         int query_success = 0, hook_version = -1;
277         size_t bol = 0; /* beginning of line */
278         uint64_t last_update;
279         struct strbuf last_update_token = STRBUF_INIT;
280         char *buf;
281         unsigned int i;
282
283         if (!core_fsmonitor || istate->fsmonitor_has_run_once)
284                 return;
285
286         hook_version = fsmonitor_hook_version();
287
288         istate->fsmonitor_has_run_once = 1;
289
290         trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
291
292         if (r->settings.use_builtin_fsmonitor > 0) {
293                 query_success = !fsmonitor_ipc__send_query(
294                         istate->fsmonitor_last_update, &query_result);
295                 if (query_success) {
296                         /*
297                          * The response contains a series of nul terminated
298                          * strings.  The first is the new token.
299                          *
300                          * Use `char *buf` as an interlude to trick the CI
301                          * static analysis to let us use `strbuf_addstr()`
302                          * here (and only copy the token) rather than
303                          * `strbuf_addbuf()`.
304                          */
305                         buf = query_result.buf;
306                         strbuf_addstr(&last_update_token, buf);
307                         bol = last_update_token.len + 1;
308                 } else {
309                         /*
310                          * The builtin daemon is not available on this
311                          * platform -OR- we failed to get a response.
312                          *
313                          * Generate a fake token (rather than a V1
314                          * timestamp) for the index extension.  (If
315                          * they switch back to the hook API, we don't
316                          * want ambiguous state.)
317                          */
318                         strbuf_addstr(&last_update_token, "builtin:fake");
319                 }
320
321                 /*
322                  * Regardless of whether we successfully talked to a
323                  * fsmonitor daemon or not, we skip over and do not
324                  * try to use the hook.  The "core.useBuiltinFSMonitor"
325                  * config setting ALWAYS overrides the "core.fsmonitor"
326                  * hook setting.
327                  */
328                 goto apply_results;
329         }
330
331         /*
332          * This could be racy so save the date/time now and query_fsmonitor
333          * should be inclusive to ensure we don't miss potential changes.
334          */
335         last_update = getnanotime();
336         if (hook_version == HOOK_INTERFACE_VERSION1)
337                 strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
338
339         /*
340          * If we have a last update token, call query_fsmonitor for the set of
341          * changes since that token, else assume everything is possibly dirty
342          * and check it all.
343          */
344         if (istate->fsmonitor_last_update) {
345                 if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
346                         query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION2,
347                                 istate->fsmonitor_last_update, &query_result);
348
349                         if (query_success) {
350                                 if (hook_version < 0)
351                                         hook_version = HOOK_INTERFACE_VERSION2;
352
353                                 /*
354                                  * First entry will be the last update token
355                                  * Need to use a char * variable because static
356                                  * analysis was suggesting to use strbuf_addbuf
357                                  * but we don't want to copy the entire strbuf
358                                  * only the chars up to the first NUL
359                                  */
360                                 buf = query_result.buf;
361                                 strbuf_addstr(&last_update_token, buf);
362                                 if (!last_update_token.len) {
363                                         warning("Empty last update token.");
364                                         query_success = 0;
365                                 } else {
366                                         bol = last_update_token.len + 1;
367                                 }
368                         } else if (hook_version < 0) {
369                                 hook_version = HOOK_INTERFACE_VERSION1;
370                                 if (!last_update_token.len)
371                                         strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
372                         }
373                 }
374
375                 if (hook_version == HOOK_INTERFACE_VERSION1) {
376                         query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION1,
377                                 istate->fsmonitor_last_update, &query_result);
378                 }
379
380                 trace_performance_since(last_update, "fsmonitor process '%s'", core_fsmonitor);
381                 trace_printf_key(&trace_fsmonitor, "fsmonitor process '%s' returned %s",
382                         core_fsmonitor, query_success ? "success" : "failure");
383         }
384
385 apply_results:
386         /*
387          * The response from FSMonitor (excluding the header token) is
388          * either:
389          *
390          * [a] a (possibly empty) list of NUL delimited relative
391          *     pathnames of changed paths.  This list can contain
392          *     files and directories.  Directories have a trailing
393          *     slash.
394          *
395          * [b] a single '/' to indicate the provider had no
396          *     information and that we should consider everything
397          *     invalid.  We call this a trivial response.
398          */
399         if (query_success && query_result.buf[bol] != '/') {
400                 /*
401                  * Mark all pathnames returned by the monitor as dirty.
402                  *
403                  * This updates both the cache-entries and the untracked-cache.
404                  */
405                 int count = 0;
406
407                 buf = query_result.buf;
408                 for (i = bol; i < query_result.len; i++) {
409                         if (buf[i] != '\0')
410                                 continue;
411                         fsmonitor_refresh_callback(istate, buf + bol);
412                         bol = i + 1;
413                         count++;
414                 }
415                 if (bol < query_result.len) {
416                         fsmonitor_refresh_callback(istate, buf + bol);
417                         count++;
418                 }
419
420                 /* Now mark the untracked cache for fsmonitor usage */
421                 if (istate->untracked)
422                         istate->untracked->use_fsmonitor = 1;
423
424                 if (count > fsmonitor_force_update_threshold)
425                         istate->cache_changed |= FSMONITOR_CHANGED;
426
427         } else {
428                 /*
429                  * We received a trivial response, so invalidate everything.
430                  *
431                  * We only want to run the post index changed hook if
432                  * we've actually changed entries, so keep track if we
433                  * actually changed entries or not.
434                  */
435                 int is_cache_changed = 0;
436
437                 for (i = 0; i < istate->cache_nr; i++) {
438                         if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {
439                                 is_cache_changed = 1;
440                                 istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
441                         }
442                 }
443
444                 /*
445                  * If we're going to check every file, ensure we save
446                  * the results.
447                  */
448                 if (is_cache_changed)
449                         istate->cache_changed |= FSMONITOR_CHANGED;
450
451                 if (istate->untracked)
452                         istate->untracked->use_fsmonitor = 0;
453         }
454         strbuf_release(&query_result);
455
456         /* Now that we've updated istate, save the last_update_token */
457         FREE_AND_NULL(istate->fsmonitor_last_update);
458         istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);
459 }
460
461 /*
462  * The caller wants to turn on FSMonitor.  And when the caller writes
463  * the index to disk, a FSMonitor extension should be included.  This
464  * requires that `istate->fsmonitor_last_update` not be NULL.  But we
465  * have not actually talked to a FSMonitor process yet, so we don't
466  * have an initial value for this field.
467  *
468  * For a protocol V1 FSMonitor process, this field is a formatted
469  * "nanoseconds since epoch" field.  However, for a protocol V2
470  * FSMonitor process, this field is an opaque token.
471  *
472  * Historically, `add_fsmonitor()` has initialized this field to the
473  * current time for protocol V1 processes.  There are lots of race
474  * conditions here, but that code has shipped...
475  *
476  * The only true solution is to use a V2 FSMonitor and get a current
477  * or default token value (that it understands), but we cannot do that
478  * until we have actually talked to an instance of the FSMonitor process
479  * (but the protocol requires that we send a token first...).
480  *
481  * For simplicity, just initialize like we have a V1 process and require
482  * that V2 processes adapt.
483  */
484 static void initialize_fsmonitor_last_update(struct index_state *istate)
485 {
486         struct strbuf last_update = STRBUF_INIT;
487
488         strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
489         istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
490 }
491
492 void add_fsmonitor(struct index_state *istate)
493 {
494         unsigned int i;
495
496         if (!istate->fsmonitor_last_update) {
497                 trace_printf_key(&trace_fsmonitor, "add fsmonitor");
498                 istate->cache_changed |= FSMONITOR_CHANGED;
499                 initialize_fsmonitor_last_update(istate);
500
501                 /* reset the fsmonitor state */
502                 for (i = 0; i < istate->cache_nr; i++)
503                         istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
504
505                 /* reset the untracked cache */
506                 if (istate->untracked) {
507                         add_untracked_cache(istate);
508                         istate->untracked->use_fsmonitor = 1;
509                 }
510
511                 /* Update the fsmonitor state */
512                 refresh_fsmonitor(istate);
513         }
514 }
515
516 void remove_fsmonitor(struct index_state *istate)
517 {
518         if (istate->fsmonitor_last_update) {
519                 trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
520                 istate->cache_changed |= FSMONITOR_CHANGED;
521                 FREE_AND_NULL(istate->fsmonitor_last_update);
522         }
523 }
524
525 void tweak_fsmonitor(struct index_state *istate)
526 {
527         unsigned int i;
528         int fsmonitor_enabled = repo_config_get_fsmonitor(istate->repo ? istate->repo : the_repository);
529
530         if (istate->fsmonitor_dirty) {
531                 if (fsmonitor_enabled) {
532                         /* Mark all entries valid */
533                         for (i = 0; i < istate->cache_nr; i++) {
534                                 istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
535                         }
536
537                         /* Mark all previously saved entries as dirty */
538                         assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
539                         ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
540
541                         refresh_fsmonitor(istate);
542                 }
543
544                 ewah_free(istate->fsmonitor_dirty);
545                 istate->fsmonitor_dirty = NULL;
546         }
547
548         switch (fsmonitor_enabled) {
549         case -1: /* keep: do nothing */
550                 break;
551         case 0: /* false */
552                 remove_fsmonitor(istate);
553                 break;
554         case 1: /* true */
555                 add_fsmonitor(istate);
556                 break;
557         default: /* unknown value: do nothing */
558                 break;
559         }
560 }