]>
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 | ||
21 | const char *fsmonitor_ipc__get_path(void) | |
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 | ||
50 | GIT_PATH_FUNC(fsmonitor_ipc__get_path, "fsmonitor--daemon.ipc") | |
51 | ||
52 | enum ipc_active_state fsmonitor_ipc__get_state(void) | |
53 | { | |
54 | return ipc_get_active_state(fsmonitor_ipc__get_path()); | |
55 | } | |
56 | ||
57 | static int spawn_daemon(void) | |
58 | { | |
59 | const char *args[] = { "fsmonitor--daemon", "start", NULL }; | |
60 | ||
61 | return run_command_v_opt_tr2(args, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD, | |
62 | "fsmonitor"); | |
63 | } | |
64 | ||
65 | int fsmonitor_ipc__send_query(const char *since_token, | |
66 | struct strbuf *answer) | |
67 | { | |
68 | int ret = -1; | |
69 | int tried_to_spawn = 0; | |
70 | enum ipc_active_state state = IPC_STATE__OTHER_ERROR; | |
71 | struct ipc_client_connection *connection = NULL; | |
72 | struct ipc_client_connect_options options | |
73 | = IPC_CLIENT_CONNECT_OPTIONS_INIT; | |
74 | const char *tok = since_token ? since_token : ""; | |
75 | size_t tok_len = since_token ? strlen(since_token) : 0; | |
76 | ||
77 | options.wait_if_busy = 1; | |
78 | options.wait_if_not_found = 0; | |
79 | ||
80 | trace2_region_enter("fsm_client", "query", NULL); | |
81 | trace2_data_string("fsm_client", NULL, "query/command", tok); | |
82 | ||
83 | try_again: | |
84 | state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options, | |
85 | &connection); | |
86 | ||
87 | switch (state) { | |
88 | case IPC_STATE__LISTENING: | |
89 | ret = ipc_client_send_command_to_connection( | |
90 | connection, tok, tok_len, answer); | |
91 | ipc_client_close_connection(connection); | |
92 | ||
93 | trace2_data_intmax("fsm_client", NULL, | |
94 | "query/response-length", answer->len); | |
95 | goto done; | |
96 | ||
97 | case IPC_STATE__NOT_LISTENING: | |
98 | case IPC_STATE__PATH_NOT_FOUND: | |
99 | if (tried_to_spawn) | |
100 | goto done; | |
101 | ||
102 | tried_to_spawn++; | |
103 | if (spawn_daemon()) | |
104 | goto done; | |
105 | ||
106 | /* | |
107 | * Try again, but this time give the daemon a chance to | |
108 | * actually create the pipe/socket. | |
109 | * | |
110 | * Granted, the daemon just started so it can't possibly have | |
111 | * any FS cached yet, so we'll always get a trivial answer. | |
112 | * BUT the answer should include a new token that can serve | |
113 | * as the basis for subsequent requests. | |
114 | */ | |
115 | options.wait_if_not_found = 1; | |
116 | goto try_again; | |
117 | ||
118 | case IPC_STATE__INVALID_PATH: | |
119 | ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"), | |
120 | fsmonitor_ipc__get_path()); | |
121 | goto done; | |
122 | ||
123 | case IPC_STATE__OTHER_ERROR: | |
124 | default: | |
125 | ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"), | |
126 | fsmonitor_ipc__get_path()); | |
127 | goto done; | |
128 | } | |
129 | ||
130 | done: | |
131 | trace2_region_leave("fsm_client", "query", NULL); | |
132 | ||
133 | return ret; | |
134 | } | |
135 | ||
136 | int fsmonitor_ipc__send_command(const char *command, | |
137 | struct strbuf *answer) | |
138 | { | |
139 | struct ipc_client_connection *connection = NULL; | |
140 | struct ipc_client_connect_options options | |
141 | = IPC_CLIENT_CONNECT_OPTIONS_INIT; | |
142 | int ret; | |
143 | enum ipc_active_state state; | |
144 | const char *c = command ? command : ""; | |
145 | size_t c_len = command ? strlen(command) : 0; | |
146 | ||
147 | strbuf_reset(answer); | |
148 | ||
149 | options.wait_if_busy = 1; | |
150 | options.wait_if_not_found = 0; | |
151 | ||
152 | state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options, | |
153 | &connection); | |
154 | if (state != IPC_STATE__LISTENING) { | |
155 | die(_("fsmonitor--daemon is not running")); | |
156 | return -1; | |
157 | } | |
158 | ||
159 | ret = ipc_client_send_command_to_connection(connection, c, c_len, | |
160 | answer); | |
161 | ipc_client_close_connection(connection); | |
162 | ||
163 | if (ret == -1) { | |
164 | die(_("could not send '%s' command to fsmonitor--daemon"), c); | |
165 | return -1; | |
166 | } | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
171 | #endif |