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