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