]>
Commit | Line | Data |
---|---|---|
bc5c5ec0 | 1 | #include "git-compat-util.h" |
68d68646 | 2 | #include "fsmonitor-ll.h" |
f394e093 | 3 | #include "gettext.h" |
d2bd862e JH |
4 | #include "simple-ipc.h" |
5 | #include "fsmonitor-ipc.h" | |
d1cbe1e6 | 6 | #include "repository.h" |
d2bd862e JH |
7 | #include "run-command.h" |
8 | #include "strbuf.h" | |
9 | #include "trace2.h" | |
10 | ||
11 | #ifndef HAVE_FSMONITOR_DAEMON_BACKEND | |
12 | ||
13 | /* | |
14 | * A trivial implementation of the fsmonitor_ipc__ API for unsupported | |
15 | * platforms. | |
16 | */ | |
17 | ||
18 | int fsmonitor_ipc__is_supported(void) | |
19 | { | |
20 | return 0; | |
21 | } | |
22 | ||
4cb5e0b3 | 23 | const char *fsmonitor_ipc__get_path(struct repository *r UNUSED) |
d2bd862e JH |
24 | { |
25 | return NULL; | |
26 | } | |
27 | ||
28 | enum ipc_active_state fsmonitor_ipc__get_state(void) | |
29 | { | |
30 | return IPC_STATE__OTHER_ERROR; | |
31 | } | |
32 | ||
4cb5e0b3 JK |
33 | int fsmonitor_ipc__send_query(const char *since_token UNUSED, |
34 | struct strbuf *answer UNUSED) | |
d2bd862e JH |
35 | { |
36 | return -1; | |
37 | } | |
38 | ||
4cb5e0b3 JK |
39 | int fsmonitor_ipc__send_command(const char *command UNUSED, |
40 | struct strbuf *answer UNUSED) | |
d2bd862e JH |
41 | { |
42 | return -1; | |
43 | } | |
44 | ||
45 | #else | |
46 | ||
47 | int fsmonitor_ipc__is_supported(void) | |
48 | { | |
49 | return 1; | |
50 | } | |
51 | ||
d2bd862e JH |
52 | enum ipc_active_state fsmonitor_ipc__get_state(void) |
53 | { | |
6beb2688 | 54 | return ipc_get_active_state(fsmonitor_ipc__get_path(the_repository)); |
d2bd862e JH |
55 | } |
56 | ||
57 | static int spawn_daemon(void) | |
58 | { | |
d82dbbd8 | 59 | struct child_process cmd = CHILD_PROCESS_INIT; |
d2bd862e | 60 | |
d82dbbd8 RS |
61 | cmd.git_cmd = 1; |
62 | cmd.no_stdin = 1; | |
63 | cmd.trace2_child_class = "fsmonitor"; | |
64 | strvec_pushl(&cmd.args, "fsmonitor--daemon", "start", NULL); | |
65 | ||
66 | return run_command(&cmd); | |
d2bd862e JH |
67 | } |
68 | ||
69 | int fsmonitor_ipc__send_query(const char *since_token, | |
70 | struct strbuf *answer) | |
71 | { | |
72 | int ret = -1; | |
73 | int tried_to_spawn = 0; | |
74 | enum ipc_active_state state = IPC_STATE__OTHER_ERROR; | |
75 | struct ipc_client_connection *connection = NULL; | |
76 | struct ipc_client_connect_options options | |
77 | = IPC_CLIENT_CONNECT_OPTIONS_INIT; | |
78 | const char *tok = since_token ? since_token : ""; | |
79 | size_t tok_len = since_token ? strlen(since_token) : 0; | |
80 | ||
81 | options.wait_if_busy = 1; | |
82 | options.wait_if_not_found = 0; | |
83 | ||
84 | trace2_region_enter("fsm_client", "query", NULL); | |
85 | trace2_data_string("fsm_client", NULL, "query/command", tok); | |
86 | ||
87 | try_again: | |
6beb2688 ED |
88 | state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), |
89 | &options, &connection); | |
d2bd862e JH |
90 | |
91 | switch (state) { | |
92 | case IPC_STATE__LISTENING: | |
93 | ret = ipc_client_send_command_to_connection( | |
94 | connection, tok, tok_len, answer); | |
95 | ipc_client_close_connection(connection); | |
96 | ||
97 | trace2_data_intmax("fsm_client", NULL, | |
98 | "query/response-length", answer->len); | |
99 | goto done; | |
100 | ||
101 | case IPC_STATE__NOT_LISTENING: | |
102 | case IPC_STATE__PATH_NOT_FOUND: | |
103 | if (tried_to_spawn) | |
104 | goto done; | |
105 | ||
106 | tried_to_spawn++; | |
107 | if (spawn_daemon()) | |
108 | goto done; | |
109 | ||
110 | /* | |
111 | * Try again, but this time give the daemon a chance to | |
112 | * actually create the pipe/socket. | |
113 | * | |
114 | * Granted, the daemon just started so it can't possibly have | |
115 | * any FS cached yet, so we'll always get a trivial answer. | |
116 | * BUT the answer should include a new token that can serve | |
117 | * as the basis for subsequent requests. | |
118 | */ | |
119 | options.wait_if_not_found = 1; | |
120 | goto try_again; | |
121 | ||
122 | case IPC_STATE__INVALID_PATH: | |
123 | ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"), | |
6beb2688 | 124 | fsmonitor_ipc__get_path(the_repository)); |
d2bd862e JH |
125 | goto done; |
126 | ||
127 | case IPC_STATE__OTHER_ERROR: | |
128 | default: | |
129 | ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"), | |
6beb2688 | 130 | fsmonitor_ipc__get_path(the_repository)); |
d2bd862e JH |
131 | goto done; |
132 | } | |
133 | ||
134 | done: | |
135 | trace2_region_leave("fsm_client", "query", NULL); | |
136 | ||
137 | return ret; | |
138 | } | |
139 | ||
140 | int fsmonitor_ipc__send_command(const char *command, | |
141 | struct strbuf *answer) | |
142 | { | |
143 | struct ipc_client_connection *connection = NULL; | |
144 | struct ipc_client_connect_options options | |
145 | = IPC_CLIENT_CONNECT_OPTIONS_INIT; | |
146 | int ret; | |
147 | enum ipc_active_state state; | |
148 | const char *c = command ? command : ""; | |
149 | size_t c_len = command ? strlen(command) : 0; | |
150 | ||
151 | strbuf_reset(answer); | |
152 | ||
153 | options.wait_if_busy = 1; | |
154 | options.wait_if_not_found = 0; | |
155 | ||
6beb2688 ED |
156 | state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), |
157 | &options, &connection); | |
d2bd862e JH |
158 | if (state != IPC_STATE__LISTENING) { |
159 | die(_("fsmonitor--daemon is not running")); | |
160 | return -1; | |
161 | } | |
162 | ||
163 | ret = ipc_client_send_command_to_connection(connection, c, c_len, | |
164 | answer); | |
165 | ipc_client_close_connection(connection); | |
166 | ||
167 | if (ret == -1) { | |
168 | die(_("could not send '%s' command to fsmonitor--daemon"), c); | |
169 | return -1; | |
170 | } | |
171 | ||
172 | return 0; | |
173 | } | |
174 | ||
175 | #endif |