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