git
/
fsmonitor.c
820 строк · 25.5 Кб
1#define USE_THE_REPOSITORY_VARIABLE2
3#include "git-compat-util.h"4#include "config.h"5#include "dir.h"6#include "environment.h"7#include "ewah/ewok.h"8#include "fsmonitor.h"9#include "fsmonitor-ipc.h"10#include "name-hash.h"11#include "run-command.h"12#include "strbuf.h"13#include "trace2.h"14
15#define INDEX_EXTENSION_VERSION1 (1)16#define INDEX_EXTENSION_VERSION2 (2)17#define HOOK_INTERFACE_VERSION1 (1)18#define HOOK_INTERFACE_VERSION2 (2)19
20struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);21
22static void assert_index_minimum(struct index_state *istate, size_t pos)23{
24if (pos > istate->cache_nr)25BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",26(uintmax_t)pos, istate->cache_nr);27}
28
29static void fsmonitor_ewah_callback(size_t pos, void *is)30{
31struct index_state *istate = (struct index_state *)is;32struct cache_entry *ce;33
34assert_index_minimum(istate, pos + 1);35
36ce = istate->cache[pos];37ce->ce_flags &= ~CE_FSMONITOR_VALID;38}
39
40static int fsmonitor_hook_version(void)41{
42int hook_version;43
44if (git_config_get_int("core.fsmonitorhookversion", &hook_version))45return -1;46
47if (hook_version == HOOK_INTERFACE_VERSION1 ||48hook_version == HOOK_INTERFACE_VERSION2)49return hook_version;50
51warning("Invalid hook version '%i' in core.fsmonitorhookversion. "52"Must be 1 or 2.", hook_version);53return -1;54}
55
56int read_fsmonitor_extension(struct index_state *istate, const void *data,57unsigned long sz)58{
59const char *index = data;60uint32_t hdr_version;61uint32_t ewah_size;62struct ewah_bitmap *fsmonitor_dirty;63int ret;64uint64_t timestamp;65struct strbuf last_update = STRBUF_INIT;66
67if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))68return error("corrupt fsmonitor extension (too short)");69
70hdr_version = get_be32(index);71index += sizeof(uint32_t);72if (hdr_version == INDEX_EXTENSION_VERSION1) {73timestamp = get_be64(index);74strbuf_addf(&last_update, "%"PRIu64"", timestamp);75index += sizeof(uint64_t);76} else if (hdr_version == INDEX_EXTENSION_VERSION2) {77strbuf_addstr(&last_update, index);78index += last_update.len + 1;79} else {80return error("bad fsmonitor version %d", hdr_version);81}82
83istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);84
85ewah_size = get_be32(index);86index += sizeof(uint32_t);87
88fsmonitor_dirty = ewah_new();89ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);90if (ret != ewah_size) {91ewah_free(fsmonitor_dirty);92return error("failed to parse ewah bitmap reading fsmonitor index extension");93}94istate->fsmonitor_dirty = fsmonitor_dirty;95
96if (!istate->split_index)97assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);98
99trace2_data_string("index", NULL, "extension/fsmn/read/token",100istate->fsmonitor_last_update);101trace_printf_key(&trace_fsmonitor,102"read fsmonitor extension successful '%s'",103istate->fsmonitor_last_update);104return 0;105}
106
107void fill_fsmonitor_bitmap(struct index_state *istate)108{
109unsigned int i, skipped = 0;110istate->fsmonitor_dirty = ewah_new();111for (i = 0; i < istate->cache_nr; i++) {112if (istate->cache[i]->ce_flags & CE_REMOVE)113skipped++;114else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))115ewah_set(istate->fsmonitor_dirty, i - skipped);116}117}
118
119void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)120{
121uint32_t hdr_version;122uint32_t ewah_start;123uint32_t ewah_size = 0;124int fixup = 0;125
126if (!istate->split_index)127assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);128
129put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);130strbuf_add(sb, &hdr_version, sizeof(uint32_t));131
132strbuf_addstr(sb, istate->fsmonitor_last_update);133strbuf_addch(sb, 0); /* Want to keep a NUL */134
135fixup = sb->len;136strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */137
138ewah_start = sb->len;139ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);140ewah_free(istate->fsmonitor_dirty);141istate->fsmonitor_dirty = NULL;142
143/* fix up size field */144put_be32(&ewah_size, sb->len - ewah_start);145memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));146
147trace2_data_string("index", NULL, "extension/fsmn/write/token",148istate->fsmonitor_last_update);149trace_printf_key(&trace_fsmonitor,150"write fsmonitor extension successful '%s'",151istate->fsmonitor_last_update);152}
153
154/*
155* Call the query-fsmonitor hook passing the last update token of the saved results.
156*/
157static int query_fsmonitor_hook(struct repository *r,158int version,159const char *last_update,160struct strbuf *query_result)161{
162struct child_process cp = CHILD_PROCESS_INIT;163int result;164
165if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)166return -1;167
168strvec_push(&cp.args, fsm_settings__get_hook_path(r));169strvec_pushf(&cp.args, "%d", version);170strvec_pushf(&cp.args, "%s", last_update);171cp.use_shell = 1;172cp.dir = get_git_work_tree();173
174trace2_region_enter("fsm_hook", "query", NULL);175
176result = capture_command(&cp, query_result, 1024);177
178if (result)179trace2_data_intmax("fsm_hook", NULL, "query/failed", result);180else181trace2_data_intmax("fsm_hook", NULL, "query/response-length",182query_result->len);183
184trace2_region_leave("fsm_hook", "query", NULL);185
186return result;187}
188
189/*
190* Invalidate the FSM bit on this CE. This is like mark_fsmonitor_invalid()
191* but we've already handled the untracked-cache, so let's not repeat that
192* work. This also lets us have a different trace message so that we can
193* see everything that was done as part of the refresh-callback.
194*/
195static void invalidate_ce_fsm(struct cache_entry *ce)196{
197if (ce->ce_flags & CE_FSMONITOR_VALID) {198trace_printf_key(&trace_fsmonitor,199"fsmonitor_refresh_callback INV: '%s'",200ce->name);201ce->ce_flags &= ~CE_FSMONITOR_VALID;202}203}
204
205static size_t handle_path_with_trailing_slash(206struct index_state *istate, const char *name, int pos);207
208/*
209* Use the name-hash to do a case-insensitive cache-entry lookup with
210* the pathname and invalidate the cache-entry.
211*
212* Returns the number of cache-entries that we invalidated.
213*/
214static size_t handle_using_name_hash_icase(215struct index_state *istate, const char *name)216{
217struct cache_entry *ce = NULL;218
219ce = index_file_exists(istate, name, strlen(name), 1);220if (!ce)221return 0;222
223/*224* A case-insensitive search in the name-hash using the
225* observed pathname found a cache-entry, so the observed path
226* is case-incorrect. Invalidate the cache-entry and use the
227* correct spelling from the cache-entry to invalidate the
228* untracked-cache. Since we now have sparse-directories in
229* the index, the observed pathname may represent a regular
230* file or a sparse-index directory.
231*
232* Note that we should not have seen FSEvents for a
233* sparse-index directory, but we handle it just in case.
234*
235* Either way, we know that there are not any cache-entries for
236* children inside the cone of the directory, so we don't need to
237* do the usual scan.
238*/
239trace_printf_key(&trace_fsmonitor,240"fsmonitor_refresh_callback MAP: '%s' '%s'",241name, ce->name);242
243/*244* NEEDSWORK: We used the name-hash to find the correct
245* case-spelling of the pathname in the cache-entry[], so
246* technically this is a tracked file or a sparse-directory.
247* It should not have any entries in the untracked-cache, so
248* we should not need to use the case-corrected spelling to
249* invalidate the the untracked-cache. So we may not need to
250* do this. For now, I'm going to be conservative and always
251* do it; we can revisit this later.
252*/
253untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);254
255invalidate_ce_fsm(ce);256return 1;257}
258
259/*
260* Use the dir-name-hash to find the correct-case spelling of the
261* directory. Use the canonical spelling to invalidate all of the
262* cache-entries within the matching cone.
263*
264* Returns the number of cache-entries that we invalidated.
265*/
266static size_t handle_using_dir_name_hash_icase(267struct index_state *istate, const char *name)268{
269struct strbuf canonical_path = STRBUF_INIT;270int pos;271size_t len = strlen(name);272size_t nr_in_cone;273
274if (name[len - 1] == '/')275len--;276
277if (!index_dir_find(istate, name, len, &canonical_path))278return 0; /* name is untracked */279
280if (!memcmp(name, canonical_path.buf, canonical_path.len)) {281strbuf_release(&canonical_path);282/*283* NEEDSWORK: Our caller already tried an exact match
284* and failed to find one. They called us to do an
285* ICASE match, so we should never get an exact match,
286* so we could promote this to a BUG() here if we
287* wanted to. It doesn't hurt anything to just return
288* 0 and go on because we should never get here. Or we
289* could just get rid of the memcmp() and this "if"
290* clause completely.
291*/
292BUG("handle_using_dir_name_hash_icase(%s) did not exact match",293name);294}295
296trace_printf_key(&trace_fsmonitor,297"fsmonitor_refresh_callback MAP: '%s' '%s'",298name, canonical_path.buf);299
300/*301* The dir-name-hash only tells us the corrected spelling of
302* the prefix. We have to use this canonical path to do a
303* lookup in the cache-entry array so that we repeat the
304* original search using the case-corrected spelling.
305*/
306strbuf_addch(&canonical_path, '/');307pos = index_name_pos(istate, canonical_path.buf,308canonical_path.len);309nr_in_cone = handle_path_with_trailing_slash(310istate, canonical_path.buf, pos);311strbuf_release(&canonical_path);312return nr_in_cone;313}
314
315/*
316* The daemon sent an observed pathname without a trailing slash.
317* (This is the normal case.) We do not know if it is a tracked or
318* untracked file, a sparse-directory, or a populated directory (on a
319* platform such as Windows where FSEvents are not qualified).
320*
321* The pathname contains the observed case reported by the FS. We
322* do not know it is case-correct or -incorrect.
323*
324* Assume it is case-correct and try an exact match.
325*
326* Return the number of cache-entries that we invalidated.
327*/
328static size_t handle_path_without_trailing_slash(329struct index_state *istate, const char *name, int pos)330{
331/*332* Mark the untracked cache dirty for this path (regardless of
333* whether or not we find an exact match for it in the index).
334* Since the path is unqualified (no trailing slash hint in the
335* FSEvent), it may refer to a file or directory. So we should
336* not assume one or the other and should always let the untracked
337* cache decide what needs to invalidated.
338*/
339untracked_cache_invalidate_trimmed_path(istate, name, 0);340
341if (pos >= 0) {342/*343* An exact match on a tracked file. We assume that we
344* do not need to scan forward for a sparse-directory
345* cache-entry with the same pathname, nor for a cone
346* at that directory. (That is, assume no D/F conflicts.)
347*/
348invalidate_ce_fsm(istate->cache[pos]);349return 1;350} else {351size_t nr_in_cone;352struct strbuf work_path = STRBUF_INIT;353
354/*355* The negative "pos" gives us the suggested insertion
356* point for the pathname (without the trailing slash).
357* We need to see if there is a directory with that
358* prefix, but there can be lots of pathnames between
359* "foo" and "foo/" like "foo-" or "foo-bar", so we
360* don't want to do our own scan.
361*/
362strbuf_add(&work_path, name, strlen(name));363strbuf_addch(&work_path, '/');364pos = index_name_pos(istate, work_path.buf, work_path.len);365nr_in_cone = handle_path_with_trailing_slash(366istate, work_path.buf, pos);367strbuf_release(&work_path);368return nr_in_cone;369}370}
371
372/*
373* The daemon can decorate directory events, such as a move or rename,
374* by adding a trailing slash to the observed name. Use this to
375* explicitly invalidate the entire cone under that directory.
376*
377* The daemon can only reliably do that if the OS FSEvent contains
378* sufficient information in the event.
379*
380* macOS FSEvents have enough information.
381*
382* Other platforms may or may not be able to do it (and it might
383* depend on the type of event (for example, a daemon could lstat() an
384* observed pathname after a rename, but not after a delete)).
385*
386* If we find an exact match in the index for a path with a trailing
387* slash, it means that we matched a sparse-index directory in a
388* cone-mode sparse-checkout (since that's the only time we have
389* directories in the index). We should never see this in practice
390* (because sparse directories should not be present and therefore
391* not generating FS events). Either way, we can treat them in the
392* same way and just invalidate the cache-entry and the untracked
393* cache (and in this case, the forward cache-entry scan won't find
394* anything and it doesn't hurt to let it run).
395*
396* Return the number of cache-entries that we invalidated. We will
397* use this later to determine if we need to attempt a second
398* case-insensitive search on case-insensitive file systems. That is,
399* if the search using the observed-case in the FSEvent yields any
400* results, we assume the prefix is case-correct. If there are no
401* matches, we still don't know if the observed path is simply
402* untracked or case-incorrect.
403*/
404static size_t handle_path_with_trailing_slash(405struct index_state *istate, const char *name, int pos)406{
407int i;408size_t nr_in_cone = 0;409
410/*411* Mark the untracked cache dirty for this directory path
412* (regardless of whether or not we find an exact match for it
413* in the index or find it to be proper prefix of one or more
414* files in the index), since the FSEvent is hinting that
415* there may be changes on or within the directory.
416*/
417untracked_cache_invalidate_trimmed_path(istate, name, 0);418
419if (pos < 0)420pos = -pos - 1;421
422/* Mark all entries for the folder invalid */423for (i = pos; i < istate->cache_nr; i++) {424if (!starts_with(istate->cache[i]->name, name))425break;426invalidate_ce_fsm(istate->cache[i]);427nr_in_cone++;428}429
430return nr_in_cone;431}
432
433static void fsmonitor_refresh_callback(struct index_state *istate, char *name)434{
435int len = strlen(name);436int pos = index_name_pos(istate, name, len);437size_t nr_in_cone;438
439trace_printf_key(&trace_fsmonitor,440"fsmonitor_refresh_callback '%s' (pos %d)",441name, pos);442
443if (name[len - 1] == '/')444nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);445else446nr_in_cone = handle_path_without_trailing_slash(istate, name, pos);447
448/*449* If we did not find an exact match for this pathname or any
450* cache-entries with this directory prefix and we're on a
451* case-insensitive file system, try again using the name-hash
452* and dir-name-hash.
453*/
454if (!nr_in_cone && ignore_case) {455nr_in_cone = handle_using_name_hash_icase(istate, name);456if (!nr_in_cone)457nr_in_cone = handle_using_dir_name_hash_icase(458istate, name);459}460
461if (nr_in_cone)462trace_printf_key(&trace_fsmonitor,463"fsmonitor_refresh_callback CNT: %d",464(int)nr_in_cone);465}
466
467/*
468* The number of pathnames that we need to receive from FSMonitor
469* before we force the index to be updated.
470*
471* Note that any pathname within the set of received paths MAY cause
472* cache-entry or istate flag bits to be updated and thus cause the
473* index to be updated on disk.
474*
475* However, the response may contain many paths (such as ignored
476* paths) that will not update any flag bits. And thus not force the
477* index to be updated. (This is fine and normal.) It also means
478* that the token will not be updated in the FSMonitor index
479* extension. So the next Git command will find the same token in the
480* index, make the same token-relative request, and receive the same
481* response (plus any newly changed paths). If this response is large
482* (and continues to grow), performance could be impacted.
483*
484* For example, if the user runs a build and it writes 100K object
485* files but doesn't modify any source files, the index would not need
486* to be updated. The FSMonitor response (after the build and
487* relative to a pre-build token) might be 5MB. Each subsequent Git
488* command will receive that same 100K/5MB response until something
489* causes the index to be updated. And `refresh_fsmonitor()` will
490* have to iterate over those 100K paths each time.
491*
492* Performance could be improved if we optionally force update the
493* index after a very large response and get an updated token into
494* the FSMonitor index extension. This should allow subsequent
495* commands to get smaller and more current responses.
496*
497* The value chosen here does not need to be precise. The index
498* will be updated automatically the first time the user touches
499* a tracked file and causes a command like `git status` to
500* update an mtime to be updated and/or set a flag bit.
501*/
502static int fsmonitor_force_update_threshold = 100;503
504void refresh_fsmonitor(struct index_state *istate)505{
506static int warn_once = 0;507struct strbuf query_result = STRBUF_INIT;508int query_success = 0, hook_version = -1;509size_t bol = 0; /* beginning of line */510uint64_t last_update;511struct strbuf last_update_token = STRBUF_INIT;512char *buf;513unsigned int i;514int is_trivial = 0;515struct repository *r = istate->repo;516enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);517enum fsmonitor_reason reason = fsm_settings__get_reason(r);518
519if (!warn_once && reason > FSMONITOR_REASON_OK) {520char *msg = fsm_settings__get_incompatible_msg(r, reason);521warn_once = 1;522warning("%s", msg);523free(msg);524}525
526if (fsm_mode <= FSMONITOR_MODE_DISABLED ||527istate->fsmonitor_has_run_once)528return;529
530istate->fsmonitor_has_run_once = 1;531
532trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");533
534if (fsm_mode == FSMONITOR_MODE_IPC) {535query_success = !fsmonitor_ipc__send_query(536istate->fsmonitor_last_update ?537istate->fsmonitor_last_update : "builtin:fake",538&query_result);539if (query_success) {540/*541* The response contains a series of nul terminated
542* strings. The first is the new token.
543*
544* Use `char *buf` as an interlude to trick the CI
545* static analysis to let us use `strbuf_addstr()`
546* here (and only copy the token) rather than
547* `strbuf_addbuf()`.
548*/
549buf = query_result.buf;550strbuf_addstr(&last_update_token, buf);551bol = last_update_token.len + 1;552is_trivial = query_result.buf[bol] == '/';553if (is_trivial)554trace2_data_intmax("fsm_client", NULL,555"query/trivial-response", 1);556} else {557/*558* The builtin daemon is not available on this
559* platform -OR- we failed to get a response.
560*
561* Generate a fake token (rather than a V1
562* timestamp) for the index extension. (If
563* they switch back to the hook API, we don't
564* want ambiguous state.)
565*/
566strbuf_addstr(&last_update_token, "builtin:fake");567}568
569goto apply_results;570}571
572assert(fsm_mode == FSMONITOR_MODE_HOOK);573
574hook_version = fsmonitor_hook_version();575
576/*577* This could be racy so save the date/time now and query_fsmonitor_hook
578* should be inclusive to ensure we don't miss potential changes.
579*/
580last_update = getnanotime();581if (hook_version == HOOK_INTERFACE_VERSION1)582strbuf_addf(&last_update_token, "%"PRIu64"", last_update);583
584/*585* If we have a last update token, call query_fsmonitor_hook for the set of
586* changes since that token, else assume everything is possibly dirty
587* and check it all.
588*/
589if (istate->fsmonitor_last_update) {590if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {591query_success = !query_fsmonitor_hook(592r, HOOK_INTERFACE_VERSION2,593istate->fsmonitor_last_update, &query_result);594
595if (query_success) {596if (hook_version < 0)597hook_version = HOOK_INTERFACE_VERSION2;598
599/*600* First entry will be the last update token
601* Need to use a char * variable because static
602* analysis was suggesting to use strbuf_addbuf
603* but we don't want to copy the entire strbuf
604* only the chars up to the first NUL
605*/
606buf = query_result.buf;607strbuf_addstr(&last_update_token, buf);608if (!last_update_token.len) {609warning("Empty last update token.");610query_success = 0;611} else {612bol = last_update_token.len + 1;613is_trivial = query_result.buf[bol] == '/';614}615} else if (hook_version < 0) {616hook_version = HOOK_INTERFACE_VERSION1;617if (!last_update_token.len)618strbuf_addf(&last_update_token, "%"PRIu64"", last_update);619}620}621
622if (hook_version == HOOK_INTERFACE_VERSION1) {623query_success = !query_fsmonitor_hook(624r, HOOK_INTERFACE_VERSION1,625istate->fsmonitor_last_update, &query_result);626if (query_success)627is_trivial = query_result.buf[0] == '/';628}629
630if (is_trivial)631trace2_data_intmax("fsm_hook", NULL,632"query/trivial-response", 1);633
634trace_performance_since(last_update, "fsmonitor process '%s'",635fsm_settings__get_hook_path(r));636trace_printf_key(&trace_fsmonitor,637"fsmonitor process '%s' returned %s",638fsm_settings__get_hook_path(r),639query_success ? "success" : "failure");640}641
642apply_results:643/*644* The response from FSMonitor (excluding the header token) is
645* either:
646*
647* [a] a (possibly empty) list of NUL delimited relative
648* pathnames of changed paths. This list can contain
649* files and directories. Directories have a trailing
650* slash.
651*
652* [b] a single '/' to indicate the provider had no
653* information and that we should consider everything
654* invalid. We call this a trivial response.
655*/
656trace2_region_enter("fsmonitor", "apply_results", istate->repo);657
658if (query_success && !is_trivial) {659/*660* Mark all pathnames returned by the monitor as dirty.
661*
662* This updates both the cache-entries and the untracked-cache.
663*/
664int count = 0;665
666buf = query_result.buf;667for (i = bol; i < query_result.len; i++) {668if (buf[i] != '\0')669continue;670fsmonitor_refresh_callback(istate, buf + bol);671bol = i + 1;672count++;673}674if (bol < query_result.len) {675fsmonitor_refresh_callback(istate, buf + bol);676count++;677}678
679/* Now mark the untracked cache for fsmonitor usage */680if (istate->untracked)681istate->untracked->use_fsmonitor = 1;682
683if (count > fsmonitor_force_update_threshold)684istate->cache_changed |= FSMONITOR_CHANGED;685
686trace2_data_intmax("fsmonitor", istate->repo, "apply_count",687count);688
689} else {690/*691* We failed to get a response or received a trivial response,
692* so invalidate everything.
693*
694* We only want to run the post index changed hook if
695* we've actually changed entries, so keep track if we
696* actually changed entries or not.
697*/
698int is_cache_changed = 0;699
700for (i = 0; i < istate->cache_nr; i++) {701if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {702is_cache_changed = 1;703istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;704}705}706
707/*708* If we're going to check every file, ensure we save
709* the results.
710*/
711if (is_cache_changed)712istate->cache_changed |= FSMONITOR_CHANGED;713
714if (istate->untracked)715istate->untracked->use_fsmonitor = 0;716}717trace2_region_leave("fsmonitor", "apply_results", istate->repo);718
719strbuf_release(&query_result);720
721/* Now that we've updated istate, save the last_update_token */722FREE_AND_NULL(istate->fsmonitor_last_update);723istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);724}
725
726/*
727* The caller wants to turn on FSMonitor. And when the caller writes
728* the index to disk, a FSMonitor extension should be included. This
729* requires that `istate->fsmonitor_last_update` not be NULL. But we
730* have not actually talked to a FSMonitor process yet, so we don't
731* have an initial value for this field.
732*
733* For a protocol V1 FSMonitor process, this field is a formatted
734* "nanoseconds since epoch" field. However, for a protocol V2
735* FSMonitor process, this field is an opaque token.
736*
737* Historically, `add_fsmonitor()` has initialized this field to the
738* current time for protocol V1 processes. There are lots of race
739* conditions here, but that code has shipped...
740*
741* The only true solution is to use a V2 FSMonitor and get a current
742* or default token value (that it understands), but we cannot do that
743* until we have actually talked to an instance of the FSMonitor process
744* (but the protocol requires that we send a token first...).
745*
746* For simplicity, just initialize like we have a V1 process and require
747* that V2 processes adapt.
748*/
749static void initialize_fsmonitor_last_update(struct index_state *istate)750{
751struct strbuf last_update = STRBUF_INIT;752
753strbuf_addf(&last_update, "%"PRIu64"", getnanotime());754istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);755}
756
757void add_fsmonitor(struct index_state *istate)758{
759unsigned int i;760
761if (!istate->fsmonitor_last_update) {762trace_printf_key(&trace_fsmonitor, "add fsmonitor");763istate->cache_changed |= FSMONITOR_CHANGED;764initialize_fsmonitor_last_update(istate);765
766/* reset the fsmonitor state */767for (i = 0; i < istate->cache_nr; i++)768istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;769
770/* reset the untracked cache */771if (istate->untracked) {772add_untracked_cache(istate);773istate->untracked->use_fsmonitor = 1;774}775
776/* Update the fsmonitor state */777refresh_fsmonitor(istate);778}779}
780
781void remove_fsmonitor(struct index_state *istate)782{
783if (istate->fsmonitor_last_update) {784trace_printf_key(&trace_fsmonitor, "remove fsmonitor");785istate->cache_changed |= FSMONITOR_CHANGED;786FREE_AND_NULL(istate->fsmonitor_last_update);787}788}
789
790void tweak_fsmonitor(struct index_state *istate)791{
792unsigned int i;793int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)794> FSMONITOR_MODE_DISABLED);795
796if (istate->fsmonitor_dirty) {797if (fsmonitor_enabled) {798/* Mark all entries valid */799for (i = 0; i < istate->cache_nr; i++) {800if (S_ISGITLINK(istate->cache[i]->ce_mode))801continue;802istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;803}804
805/* Mark all previously saved entries as dirty */806assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);807ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);808
809refresh_fsmonitor(istate);810}811
812ewah_free(istate->fsmonitor_dirty);813istate->fsmonitor_dirty = NULL;814}815
816if (fsmonitor_enabled)817add_fsmonitor(istate);818else819remove_fsmonitor(istate);820}
821