3
3
#include "parse-options.h"
4
4
#include "fsmonitor.h"
5
5
#include "fsmonitor-ipc.h"
6
- #include "compat/fsmonitor/fsm-listen.h"
7
- #include "fsmonitor--daemon.h"
8
6
#include "simple-ipc.h"
9
7
#include "khash.h"
10
8
11
9
static const char * const builtin_fsmonitor__daemon_usage [] = {
12
- N_ ("git fsmonitor--daemon run [<options>]" ),
13
10
N_ ("git fsmonitor--daemon stop" ),
14
11
N_ ("git fsmonitor--daemon status" ),
15
12
NULL
16
13
};
17
14
18
15
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
19
- /*
20
- * Global state loaded from config.
21
- */
22
- #define FSMONITOR__IPC_THREADS "fsmonitor.ipcthreads"
23
- static int fsmonitor__ipc_threads = 8 ;
24
-
25
- static int fsmonitor_config (const char * var , const char * value , void * cb )
26
- {
27
- if (!strcmp (var , FSMONITOR__IPC_THREADS )) {
28
- int i = git_config_int (var , value );
29
- if (i < 1 )
30
- return error (_ ("value of '%s' out of range: %d" ),
31
- FSMONITOR__IPC_THREADS , i );
32
- fsmonitor__ipc_threads = i ;
33
- return 0 ;
34
- }
35
-
36
- return git_default_config (var , value , cb );
37
- }
38
-
39
16
/*
40
17
* Acting as a CLIENT.
41
18
*
@@ -80,190 +57,11 @@ static int do_as_client__status(void)
80
57
}
81
58
}
82
59
83
- static ipc_server_application_cb handle_client ;
84
-
85
- static int handle_client (void * data ,
86
- const char * command , size_t command_len ,
87
- ipc_server_reply_cb * reply ,
88
- struct ipc_server_reply_data * reply_data )
89
- {
90
- /* struct fsmonitor_daemon_state *state = data; */
91
- int result ;
92
-
93
- /*
94
- * The Simple IPC API now supports {char*, len} arguments, but
95
- * FSMonitor always uses proper null-terminated strings, so
96
- * we can ignore the command_len argument. (Trust, but verify.)
97
- */
98
- if (command_len != strlen (command ))
99
- BUG ("FSMonitor assumes text messages" );
100
-
101
- trace2_region_enter ("fsmonitor" , "handle_client" , the_repository );
102
- trace2_data_string ("fsmonitor" , the_repository , "request" , command );
103
-
104
- result = 0 ; /* TODO Do something here. */
105
-
106
- trace2_region_leave ("fsmonitor" , "handle_client" , the_repository );
107
-
108
- return result ;
109
- }
110
-
111
- static void * fsm_listen__thread_proc (void * _state )
112
- {
113
- struct fsmonitor_daemon_state * state = _state ;
114
-
115
- trace2_thread_start ("fsm-listen" );
116
-
117
- trace_printf_key (& trace_fsmonitor , "Watching: worktree '%s'" ,
118
- state -> path_worktree_watch .buf );
119
- if (state -> nr_paths_watching > 1 )
120
- trace_printf_key (& trace_fsmonitor , "Watching: gitdir '%s'" ,
121
- state -> path_gitdir_watch .buf );
122
-
123
- fsm_listen__loop (state );
124
-
125
- trace2_thread_exit ();
126
- return NULL ;
127
- }
128
-
129
- static int fsmonitor_run_daemon_1 (struct fsmonitor_daemon_state * state )
130
- {
131
- struct ipc_server_opts ipc_opts = {
132
- .nr_threads = fsmonitor__ipc_threads ,
133
-
134
- /*
135
- * We know that there are no other active threads yet,
136
- * so we can let the IPC layer temporarily chdir() if
137
- * it needs to when creating the server side of the
138
- * Unix domain socket.
139
- */
140
- .uds_disallow_chdir = 0
141
- };
142
-
143
- /*
144
- * Start the IPC thread pool before the we've started the file
145
- * system event listener thread so that we have the IPC handle
146
- * before we need it.
147
- */
148
- if (ipc_server_run_async (& state -> ipc_server_data ,
149
- fsmonitor_ipc__get_path (), & ipc_opts ,
150
- handle_client , state ))
151
- return error (_ ("could not start IPC thread pool" ));
152
-
153
- /*
154
- * Start the fsmonitor listener thread to collect filesystem
155
- * events.
156
- */
157
- if (pthread_create (& state -> listener_thread , NULL ,
158
- fsm_listen__thread_proc , state ) < 0 ) {
159
- ipc_server_stop_async (state -> ipc_server_data );
160
- ipc_server_await (state -> ipc_server_data );
161
-
162
- return error (_ ("could not start fsmonitor listener thread" ));
163
- }
164
-
165
- /*
166
- * The daemon is now fully functional in background threads.
167
- * Wait for the IPC thread pool to shutdown (whether by client
168
- * request or from filesystem activity).
169
- */
170
- ipc_server_await (state -> ipc_server_data );
171
-
172
- /*
173
- * The fsmonitor listener thread may have received a shutdown
174
- * event from the IPC thread pool, but it doesn't hurt to tell
175
- * it again. And wait for it to shutdown.
176
- */
177
- fsm_listen__stop_async (state );
178
- pthread_join (state -> listener_thread , NULL );
179
-
180
- return state -> error_code ;
181
- }
182
-
183
- static int fsmonitor_run_daemon (void )
184
- {
185
- struct fsmonitor_daemon_state state ;
186
- int err ;
187
-
188
- memset (& state , 0 , sizeof (state ));
189
-
190
- pthread_mutex_init (& state .main_lock , NULL );
191
- state .error_code = 0 ;
192
- state .current_token_data = NULL ;
193
-
194
- /* Prepare to (recursively) watch the <worktree-root> directory. */
195
- strbuf_init (& state .path_worktree_watch , 0 );
196
- strbuf_addstr (& state .path_worktree_watch , absolute_path (get_git_work_tree ()));
197
- state .nr_paths_watching = 1 ;
198
-
199
- /*
200
- * We create and delete cookie files somewhere inside the .git
201
- * directory to help us keep sync with the file system. If
202
- * ".git" is not a directory, then <gitdir> is not inside the
203
- * cone of <worktree-root>, so set up a second watch to watch
204
- * the <gitdir> so that we get events for the cookie files.
205
- */
206
- strbuf_init (& state .path_gitdir_watch , 0 );
207
- strbuf_addbuf (& state .path_gitdir_watch , & state .path_worktree_watch );
208
- strbuf_addstr (& state .path_gitdir_watch , "/.git" );
209
- if (!is_directory (state .path_gitdir_watch .buf )) {
210
- strbuf_reset (& state .path_gitdir_watch );
211
- strbuf_addstr (& state .path_gitdir_watch , absolute_path (get_git_dir ()));
212
- state .nr_paths_watching = 2 ;
213
- }
214
-
215
- /*
216
- * Confirm that we can create platform-specific resources for the
217
- * filesystem listener before we bother starting all the threads.
218
- */
219
- if (fsm_listen__ctor (& state )) {
220
- err = error (_ ("could not initialize listener thread" ));
221
- goto done ;
222
- }
223
-
224
- err = fsmonitor_run_daemon_1 (& state );
225
-
226
- done :
227
- pthread_mutex_destroy (& state .main_lock );
228
- fsm_listen__dtor (& state );
229
-
230
- ipc_server_free (state .ipc_server_data );
231
-
232
- strbuf_release (& state .path_worktree_watch );
233
- strbuf_release (& state .path_gitdir_watch );
234
-
235
- return err ;
236
- }
237
-
238
- static int try_to_run_foreground_daemon (void )
239
- {
240
- /*
241
- * Technically, we don't need to probe for an existing daemon
242
- * process, since we could just call `fsmonitor_run_daemon()`
243
- * and let it fail if the pipe/socket is busy.
244
- *
245
- * However, this method gives us a nicer error message for a
246
- * common error case.
247
- */
248
- if (fsmonitor_ipc__get_state () == IPC_STATE__LISTENING )
249
- die ("fsmonitor--daemon is already running '%s'" ,
250
- the_repository -> worktree );
251
-
252
- printf (_ ("running fsmonitor-daemon in '%s'\n" ),
253
- the_repository -> worktree );
254
- fflush (stdout );
255
-
256
- return !!fsmonitor_run_daemon ();
257
- }
258
-
259
60
int cmd_fsmonitor__daemon (int argc , const char * * argv , const char * prefix )
260
61
{
261
62
const char * subcmd ;
262
63
263
64
struct option options [] = {
264
- OPT_INTEGER (0 , "ipc-threads" ,
265
- & fsmonitor__ipc_threads ,
266
- N_ ("use <n> ipc worker threads" )),
267
65
OPT_END ()
268
66
};
269
67
@@ -273,20 +71,14 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
273
71
if (argc == 2 && !strcmp (argv [1 ], "-h" ))
274
72
usage_with_options (builtin_fsmonitor__daemon_usage , options );
275
73
276
- git_config (fsmonitor_config , NULL );
74
+ git_config (git_default_config , NULL );
277
75
278
76
subcmd = argv [1 ];
279
77
argv -- ;
280
78
argc ++ ;
281
79
282
80
argc = parse_options (argc , argv , prefix , options ,
283
81
builtin_fsmonitor__daemon_usage , 0 );
284
- if (fsmonitor__ipc_threads < 1 )
285
- die (_ ("invalid 'ipc-threads' value (%d)" ),
286
- fsmonitor__ipc_threads );
287
-
288
- if (!strcmp (subcmd , "run" ))
289
- return !!try_to_run_foreground_daemon ();
290
82
291
83
if (!strcmp (subcmd , "stop" ))
292
84
return !!do_as_client__send_stop ();
0 commit comments