git

Форк
0
/
fsmonitor.c 
820 строк · 25.5 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

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

20
struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
21

22
static void assert_index_minimum(struct index_state *istate, size_t pos)
23
{
24
	if (pos > istate->cache_nr)
25
		BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
26
		    (uintmax_t)pos, istate->cache_nr);
27
}
28

29
static void fsmonitor_ewah_callback(size_t pos, void *is)
30
{
31
	struct index_state *istate = (struct index_state *)is;
32
	struct cache_entry *ce;
33

34
	assert_index_minimum(istate, pos + 1);
35

36
	ce = istate->cache[pos];
37
	ce->ce_flags &= ~CE_FSMONITOR_VALID;
38
}
39

40
static int fsmonitor_hook_version(void)
41
{
42
	int hook_version;
43

44
	if (git_config_get_int("core.fsmonitorhookversion", &hook_version))
45
		return -1;
46

47
	if (hook_version == HOOK_INTERFACE_VERSION1 ||
48
	    hook_version == HOOK_INTERFACE_VERSION2)
49
		return hook_version;
50

51
	warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
52
		"Must be 1 or 2.", hook_version);
53
	return -1;
54
}
55

56
int read_fsmonitor_extension(struct index_state *istate, const void *data,
57
	unsigned long sz)
58
{
59
	const char *index = data;
60
	uint32_t hdr_version;
61
	uint32_t ewah_size;
62
	struct ewah_bitmap *fsmonitor_dirty;
63
	int ret;
64
	uint64_t timestamp;
65
	struct strbuf last_update = STRBUF_INIT;
66

67
	if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
68
		return error("corrupt fsmonitor extension (too short)");
69

70
	hdr_version = get_be32(index);
71
	index += sizeof(uint32_t);
72
	if (hdr_version == INDEX_EXTENSION_VERSION1) {
73
		timestamp = get_be64(index);
74
		strbuf_addf(&last_update, "%"PRIu64"", timestamp);
75
		index += sizeof(uint64_t);
76
	} else if (hdr_version == INDEX_EXTENSION_VERSION2) {
77
		strbuf_addstr(&last_update, index);
78
		index += last_update.len + 1;
79
	} else {
80
		return error("bad fsmonitor version %d", hdr_version);
81
	}
82

83
	istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
84

85
	ewah_size = get_be32(index);
86
	index += sizeof(uint32_t);
87

88
	fsmonitor_dirty = ewah_new();
89
	ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
90
	if (ret != ewah_size) {
91
		ewah_free(fsmonitor_dirty);
92
		return error("failed to parse ewah bitmap reading fsmonitor index extension");
93
	}
94
	istate->fsmonitor_dirty = fsmonitor_dirty;
95

96
	if (!istate->split_index)
97
		assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
98

99
	trace2_data_string("index", NULL, "extension/fsmn/read/token",
100
			   istate->fsmonitor_last_update);
101
	trace_printf_key(&trace_fsmonitor,
102
			 "read fsmonitor extension successful '%s'",
103
			 istate->fsmonitor_last_update);
104
	return 0;
105
}
106

107
void fill_fsmonitor_bitmap(struct index_state *istate)
108
{
109
	unsigned int i, skipped = 0;
110
	istate->fsmonitor_dirty = ewah_new();
111
	for (i = 0; i < istate->cache_nr; i++) {
112
		if (istate->cache[i]->ce_flags & CE_REMOVE)
113
			skipped++;
114
		else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
115
			ewah_set(istate->fsmonitor_dirty, i - skipped);
116
	}
117
}
118

119
void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
120
{
121
	uint32_t hdr_version;
122
	uint32_t ewah_start;
123
	uint32_t ewah_size = 0;
124
	int fixup = 0;
125

126
	if (!istate->split_index)
127
		assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
128

129
	put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
130
	strbuf_add(sb, &hdr_version, sizeof(uint32_t));
131

132
	strbuf_addstr(sb, istate->fsmonitor_last_update);
133
	strbuf_addch(sb, 0); /* Want to keep a NUL */
134

135
	fixup = sb->len;
136
	strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
137

138
	ewah_start = sb->len;
139
	ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
140
	ewah_free(istate->fsmonitor_dirty);
141
	istate->fsmonitor_dirty = NULL;
142

143
	/* fix up size field */
144
	put_be32(&ewah_size, sb->len - ewah_start);
145
	memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
146

147
	trace2_data_string("index", NULL, "extension/fsmn/write/token",
148
			   istate->fsmonitor_last_update);
149
	trace_printf_key(&trace_fsmonitor,
150
			 "write fsmonitor extension successful '%s'",
151
			 istate->fsmonitor_last_update);
152
}
153

154
/*
155
 * Call the query-fsmonitor hook passing the last update token of the saved results.
156
 */
157
static int query_fsmonitor_hook(struct repository *r,
158
				int version,
159
				const char *last_update,
160
				struct strbuf *query_result)
161
{
162
	struct child_process cp = CHILD_PROCESS_INIT;
163
	int result;
164

165
	if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)
166
		return -1;
167

168
	strvec_push(&cp.args, fsm_settings__get_hook_path(r));
169
	strvec_pushf(&cp.args, "%d", version);
170
	strvec_pushf(&cp.args, "%s", last_update);
171
	cp.use_shell = 1;
172
	cp.dir = get_git_work_tree();
173

174
	trace2_region_enter("fsm_hook", "query", NULL);
175

176
	result = capture_command(&cp, query_result, 1024);
177

178
	if (result)
179
		trace2_data_intmax("fsm_hook", NULL, "query/failed", result);
180
	else
181
		trace2_data_intmax("fsm_hook", NULL, "query/response-length",
182
				   query_result->len);
183

184
	trace2_region_leave("fsm_hook", "query", NULL);
185

186
	return 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
 */
195
static void invalidate_ce_fsm(struct cache_entry *ce)
196
{
197
	if (ce->ce_flags & CE_FSMONITOR_VALID) {
198
		trace_printf_key(&trace_fsmonitor,
199
				 "fsmonitor_refresh_callback INV: '%s'",
200
				 ce->name);
201
		ce->ce_flags &= ~CE_FSMONITOR_VALID;
202
	}
203
}
204

205
static size_t handle_path_with_trailing_slash(
206
	struct 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
 */
214
static size_t handle_using_name_hash_icase(
215
	struct index_state *istate, const char *name)
216
{
217
	struct cache_entry *ce = NULL;
218

219
	ce = index_file_exists(istate, name, strlen(name), 1);
220
	if (!ce)
221
		return 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
	 */
239
	trace_printf_key(&trace_fsmonitor,
240
			 "fsmonitor_refresh_callback MAP: '%s' '%s'",
241
			 name, 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
	 */
253
	untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);
254

255
	invalidate_ce_fsm(ce);
256
	return 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
 */
266
static size_t handle_using_dir_name_hash_icase(
267
	struct index_state *istate, const char *name)
268
{
269
	struct strbuf canonical_path = STRBUF_INIT;
270
	int pos;
271
	size_t len = strlen(name);
272
	size_t nr_in_cone;
273

274
	if (name[len - 1] == '/')
275
		len--;
276

277
	if (!index_dir_find(istate, name, len, &canonical_path))
278
		return 0; /* name is untracked */
279

280
	if (!memcmp(name, canonical_path.buf, canonical_path.len)) {
281
		strbuf_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
		 */
292
		BUG("handle_using_dir_name_hash_icase(%s) did not exact match",
293
		    name);
294
	}
295

296
	trace_printf_key(&trace_fsmonitor,
297
			 "fsmonitor_refresh_callback MAP: '%s' '%s'",
298
			 name, 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
	 */
306
	strbuf_addch(&canonical_path, '/');
307
	pos = index_name_pos(istate, canonical_path.buf,
308
			     canonical_path.len);
309
	nr_in_cone = handle_path_with_trailing_slash(
310
		istate, canonical_path.buf, pos);
311
	strbuf_release(&canonical_path);
312
	return 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
 */
328
static size_t handle_path_without_trailing_slash(
329
	struct 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
	 */
339
	untracked_cache_invalidate_trimmed_path(istate, name, 0);
340

341
	if (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
		 */
348
		invalidate_ce_fsm(istate->cache[pos]);
349
		return 1;
350
	} else {
351
		size_t nr_in_cone;
352
		struct 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
		 */
362
		strbuf_add(&work_path, name, strlen(name));
363
		strbuf_addch(&work_path, '/');
364
		pos = index_name_pos(istate, work_path.buf, work_path.len);
365
		nr_in_cone = handle_path_with_trailing_slash(
366
			istate, work_path.buf, pos);
367
		strbuf_release(&work_path);
368
		return 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
 */
404
static size_t handle_path_with_trailing_slash(
405
	struct index_state *istate, const char *name, int pos)
406
{
407
	int i;
408
	size_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
	 */
417
	untracked_cache_invalidate_trimmed_path(istate, name, 0);
418

419
	if (pos < 0)
420
		pos = -pos - 1;
421

422
	/* Mark all entries for the folder invalid */
423
	for (i = pos; i < istate->cache_nr; i++) {
424
		if (!starts_with(istate->cache[i]->name, name))
425
			break;
426
		invalidate_ce_fsm(istate->cache[i]);
427
		nr_in_cone++;
428
	}
429

430
	return nr_in_cone;
431
}
432

433
static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
434
{
435
	int len = strlen(name);
436
	int pos = index_name_pos(istate, name, len);
437
	size_t nr_in_cone;
438

439
	trace_printf_key(&trace_fsmonitor,
440
			 "fsmonitor_refresh_callback '%s' (pos %d)",
441
			 name, pos);
442

443
	if (name[len - 1] == '/')
444
		nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);
445
	else
446
		nr_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
	 */
454
	if (!nr_in_cone && ignore_case) {
455
		nr_in_cone = handle_using_name_hash_icase(istate, name);
456
		if (!nr_in_cone)
457
			nr_in_cone = handle_using_dir_name_hash_icase(
458
				istate, name);
459
	}
460

461
	if (nr_in_cone)
462
		trace_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
 */
502
static int fsmonitor_force_update_threshold = 100;
503

504
void refresh_fsmonitor(struct index_state *istate)
505
{
506
	static int warn_once = 0;
507
	struct strbuf query_result = STRBUF_INIT;
508
	int query_success = 0, hook_version = -1;
509
	size_t bol = 0; /* beginning of line */
510
	uint64_t last_update;
511
	struct strbuf last_update_token = STRBUF_INIT;
512
	char *buf;
513
	unsigned int i;
514
	int is_trivial = 0;
515
	struct repository *r = istate->repo;
516
	enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
517
	enum fsmonitor_reason reason = fsm_settings__get_reason(r);
518

519
	if (!warn_once && reason > FSMONITOR_REASON_OK) {
520
		char *msg = fsm_settings__get_incompatible_msg(r, reason);
521
		warn_once = 1;
522
		warning("%s", msg);
523
		free(msg);
524
	}
525

526
	if (fsm_mode <= FSMONITOR_MODE_DISABLED ||
527
	    istate->fsmonitor_has_run_once)
528
		return;
529

530
	istate->fsmonitor_has_run_once = 1;
531

532
	trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
533

534
	if (fsm_mode == FSMONITOR_MODE_IPC) {
535
		query_success = !fsmonitor_ipc__send_query(
536
			istate->fsmonitor_last_update ?
537
			istate->fsmonitor_last_update : "builtin:fake",
538
			&query_result);
539
		if (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
			 */
549
			buf = query_result.buf;
550
			strbuf_addstr(&last_update_token, buf);
551
			bol = last_update_token.len + 1;
552
			is_trivial = query_result.buf[bol] == '/';
553
			if (is_trivial)
554
				trace2_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
			 */
566
			strbuf_addstr(&last_update_token, "builtin:fake");
567
		}
568

569
		goto apply_results;
570
	}
571

572
	assert(fsm_mode == FSMONITOR_MODE_HOOK);
573

574
	hook_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
	 */
580
	last_update = getnanotime();
581
	if (hook_version == HOOK_INTERFACE_VERSION1)
582
		strbuf_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
	 */
589
	if (istate->fsmonitor_last_update) {
590
		if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
591
			query_success = !query_fsmonitor_hook(
592
				r, HOOK_INTERFACE_VERSION2,
593
				istate->fsmonitor_last_update, &query_result);
594

595
			if (query_success) {
596
				if (hook_version < 0)
597
					hook_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
				 */
606
				buf = query_result.buf;
607
				strbuf_addstr(&last_update_token, buf);
608
				if (!last_update_token.len) {
609
					warning("Empty last update token.");
610
					query_success = 0;
611
				} else {
612
					bol = last_update_token.len + 1;
613
					is_trivial = query_result.buf[bol] == '/';
614
				}
615
			} else if (hook_version < 0) {
616
				hook_version = HOOK_INTERFACE_VERSION1;
617
				if (!last_update_token.len)
618
					strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
619
			}
620
		}
621

622
		if (hook_version == HOOK_INTERFACE_VERSION1) {
623
			query_success = !query_fsmonitor_hook(
624
				r, HOOK_INTERFACE_VERSION1,
625
				istate->fsmonitor_last_update, &query_result);
626
			if (query_success)
627
				is_trivial = query_result.buf[0] == '/';
628
		}
629

630
		if (is_trivial)
631
			trace2_data_intmax("fsm_hook", NULL,
632
					   "query/trivial-response", 1);
633

634
		trace_performance_since(last_update, "fsmonitor process '%s'",
635
					fsm_settings__get_hook_path(r));
636
		trace_printf_key(&trace_fsmonitor,
637
				 "fsmonitor process '%s' returned %s",
638
				 fsm_settings__get_hook_path(r),
639
				 query_success ? "success" : "failure");
640
	}
641

642
apply_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
	 */
656
	trace2_region_enter("fsmonitor", "apply_results", istate->repo);
657

658
	if (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
		 */
664
		int count = 0;
665

666
		buf = query_result.buf;
667
		for (i = bol; i < query_result.len; i++) {
668
			if (buf[i] != '\0')
669
				continue;
670
			fsmonitor_refresh_callback(istate, buf + bol);
671
			bol = i + 1;
672
			count++;
673
		}
674
		if (bol < query_result.len) {
675
			fsmonitor_refresh_callback(istate, buf + bol);
676
			count++;
677
		}
678

679
		/* Now mark the untracked cache for fsmonitor usage */
680
		if (istate->untracked)
681
			istate->untracked->use_fsmonitor = 1;
682

683
		if (count > fsmonitor_force_update_threshold)
684
			istate->cache_changed |= FSMONITOR_CHANGED;
685

686
		trace2_data_intmax("fsmonitor", istate->repo, "apply_count",
687
				   count);
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
		 */
698
		int is_cache_changed = 0;
699

700
		for (i = 0; i < istate->cache_nr; i++) {
701
			if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {
702
				is_cache_changed = 1;
703
				istate->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
		 */
711
		if (is_cache_changed)
712
			istate->cache_changed |= FSMONITOR_CHANGED;
713

714
		if (istate->untracked)
715
			istate->untracked->use_fsmonitor = 0;
716
	}
717
	trace2_region_leave("fsmonitor", "apply_results", istate->repo);
718

719
	strbuf_release(&query_result);
720

721
	/* Now that we've updated istate, save the last_update_token */
722
	FREE_AND_NULL(istate->fsmonitor_last_update);
723
	istate->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
 */
749
static void initialize_fsmonitor_last_update(struct index_state *istate)
750
{
751
	struct strbuf last_update = STRBUF_INIT;
752

753
	strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
754
	istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
755
}
756

757
void add_fsmonitor(struct index_state *istate)
758
{
759
	unsigned int i;
760

761
	if (!istate->fsmonitor_last_update) {
762
		trace_printf_key(&trace_fsmonitor, "add fsmonitor");
763
		istate->cache_changed |= FSMONITOR_CHANGED;
764
		initialize_fsmonitor_last_update(istate);
765

766
		/* reset the fsmonitor state */
767
		for (i = 0; i < istate->cache_nr; i++)
768
			istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
769

770
		/* reset the untracked cache */
771
		if (istate->untracked) {
772
			add_untracked_cache(istate);
773
			istate->untracked->use_fsmonitor = 1;
774
		}
775

776
		/* Update the fsmonitor state */
777
		refresh_fsmonitor(istate);
778
	}
779
}
780

781
void remove_fsmonitor(struct index_state *istate)
782
{
783
	if (istate->fsmonitor_last_update) {
784
		trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
785
		istate->cache_changed |= FSMONITOR_CHANGED;
786
		FREE_AND_NULL(istate->fsmonitor_last_update);
787
	}
788
}
789

790
void tweak_fsmonitor(struct index_state *istate)
791
{
792
	unsigned int i;
793
	int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)
794
				 > FSMONITOR_MODE_DISABLED);
795

796
	if (istate->fsmonitor_dirty) {
797
		if (fsmonitor_enabled) {
798
			/* Mark all entries valid */
799
			for (i = 0; i < istate->cache_nr; i++) {
800
				if (S_ISGITLINK(istate->cache[i]->ce_mode))
801
					continue;
802
				istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
803
			}
804

805
			/* Mark all previously saved entries as dirty */
806
			assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
807
			ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
808

809
			refresh_fsmonitor(istate);
810
		}
811

812
		ewah_free(istate->fsmonitor_dirty);
813
		istate->fsmonitor_dirty = NULL;
814
	}
815

816
	if (fsmonitor_enabled)
817
		add_fsmonitor(istate);
818
	else
819
		remove_fsmonitor(istate);
820
}
821

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.