diff options
| author | ruki <[email protected]> | 2022-05-13 22:39:05 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2022-05-13 22:39:05 +0800 |
| commit | a59bde3f54633aadc858df58a0803f18044d5bcc (patch) | |
| tree | e23066f543b0b543752918da2e7342c670a6e0c0 | |
| parent | b89c0a712d8e6d6fe056723e8c88e223d4b6e0c3 (diff) | |
connect and disconnect distcc
6 files changed, 162 insertions, 88 deletions
diff --git a/xmake/modules/private/service/distcc_build/client.lua b/xmake/modules/private/service/distcc_build/client.lua index 34e590f83..bb910547f 100644 --- a/xmake/modules/private/service/distcc_build/client.lua +++ b/xmake/modules/private/service/distcc_build/client.lua @@ -72,37 +72,159 @@ function distcc_build_client:hosts_set(hosts) local hostinfo = {} local address = assert(host.connect, "connect address not found in hosts configuration!") local addr, port, user = self:address_parse(address) - hostinfo.addr = addr - hostinfo.port = port - hostinfo.user = user - hostinfo.token = host.token - table.insert(hostinfos, hostinfo) + if addr and port then + hostinfo.addr = addr + hostinfo.port = port + hostinfo.user = user + hostinfo.token = host.token + table.insert(hostinfos, hostinfo) + end end self._HOSTS = hostinfos end -- connect to the distcc server function distcc_build_client:connect() + if self:is_connected() then + print("%s: has been connected!", self) + return + end + + -- do connect + local hosts = self:hosts() + assert(hosts and #hosts > 0, "hosts not found!") + local group_name = tostring(self) .. "/connect" + scheduler.co_group_begin(group_name, function () + for _, host in ipairs(hosts) do + scheduler.co_start(self._connect_host, self, host) + end + end) + scheduler.co_group_wait(group_name) + + -- all hosts are connected? + local connected = true + for _, host in ipairs(hosts) do + if not self:_is_connected(host.addr, host.port) then + connected = false + end + end + + -- update status + local status = self:status() + status.connected = connected + self:status_save() end -- disconnect server function distcc_build_client:disconnect() + if not self:is_connected() then + print("%s: has been disconnected!", self) + return + end + + -- do disconnect + local hosts = self:hosts() + assert(hosts and #hosts > 0, "hosts not found!") + local group_name = tostring(self) .. "/connect" + scheduler.co_group_begin(group_name, function () + for _, host in ipairs(hosts) do + scheduler.co_start(self._disconnect_host, self, host) + end + end) + scheduler.co_group_wait(group_name) + + -- all hosts are connected? + local connected = true + for _, host in ipairs(hosts) do + if not self:_is_connected(host.addr, host.port) then + connected = false + end + end + + -- update status + local status = self:status() + status.connected = connected + self:status_save() end ---[[ --- connect to the distcc server -function distcc_build_client:connect() - if self:is_connected() then - print("%s: has been connected!", self) +-- is connected? +function distcc_build_client:is_connected() + return self:status().connected +end + +-- get the status +function distcc_build_client:status() + local status = self._STATUS + local statusfile = self:statusfile() + if not status then + if os.isfile(statusfile) then + status = io.load(statusfile) + end + status = status or {} + self._STATUS = status + end + return status +end + +-- save status +function distcc_build_client:status_save() + io.save(self:statusfile(), self:status()) +end + +-- get the status file +function distcc_build_client:statusfile() + return path.join(self:workdir(), "status.txt") +end + +-- get the project directory +function distcc_build_client:projectdir() + return self._PROJECTDIR +end + +-- get working directory +function distcc_build_client:workdir() + return self._WORKDIR +end + +-- get the session id, only for unique project +function distcc_build_client:_session_id(addr, port) + local hosts = self:status().hosts + if hosts then + local host = hosts[addr .. ":" .. port] + if host then + return host.session_id + end + end + return hash.uuid():split("-", {plain = true})[1]:lower() +end + +-- is connected for the given host +function distcc_build_client:_is_connected(addr, port) + local hosts = self:status().hosts + if hosts then + local host = hosts[addr .. ":" .. port] + if host then + return host.connected + end + end +end + +-- connect to the host +function distcc_build_client:_connect_host(host) + local addr = host.addr + local port = host.port + if self:_is_connected(addr, port) then + print("%s: %s:%d has been connected!", self, addr, port) return end -- we need user authorization? - local token = config.get("distcc_build.token") - if not token and self:user() then + local user = host.user + local token = host.token + if not token and user then -- get user password - cprint("Please input user ${bright}%s${clear} password:", self:user()) + cprint("Please input user ${bright}%s${clear} password to connect <%s:%d>:", user, addr, port) io.flush() local pass = (io.read() or ""):trim() assert(pass ~= "", "password is empty!") @@ -113,10 +235,8 @@ function distcc_build_client:connect() end -- do connect - local addr = self:addr() - local port = self:port() local sock = assert(socket.connect(addr, port), "%s: server unreachable!", self) - local session_id = self:session_id() + local session_id = self:_session_id(addr, port) local ok = false local errors print("%s: connect %s:%d ..", self, addr, port) @@ -135,37 +255,37 @@ function distcc_build_client:connect() end end if ok then - print("%s: connected!", self) + print("%s: %s:%d connected!", self, addr, port) else print("%s: connect %s:%d failed, %s", self, addr, port, errors or "unknown") end -- update status local status = self:status() - status.addr = addr - status.port = port - status.token = token - status.connected = ok - status.session_id = session_id + status.hosts = status.hosts or {} + status.hosts[addr .. ":" .. port] = {addr = addr, port = port, token = token, connected = ok, session_id = session_id} self:status_save() end --- disconnect server -function distcc_build_client:disconnect() - if not self:is_connected() then - print("%s: has been disconnected!", self) +-- disconnect from the host +function distcc_build_client:_disconnect_host(host) + local addr = host.addr + local port = host.port + if not self:_is_connected(addr, port) then + print("%s: %s:%d has been disconnected!", self, addr, port) return end - local addr = self:addr() - local port = self:port() + + -- do disconnect + local token = host.token local sock = socket.connect(addr, port) - local session_id = self:session_id() + local session_id = self:_session_id(addr, port) local errors local ok = false print("%s: disconnect %s:%d ..", self, addr, port) if sock then local stream = socket_stream(sock) - if stream:send_msg(message.new_disconnect(session_id, {token = self:token()})) and stream:flush() then + if stream:send_msg(message.new_disconnect(session_id, {token = token})) and stream:flush() then local msg = stream:recv_msg() if msg then vprint(msg:body()) @@ -182,66 +302,20 @@ function distcc_build_client:disconnect() ok = true end if ok then - print("%s: disconnected!", self) + print("%s: %s:%d disconnected!", self, addr, port) else print("%s: disconnect %s:%d failed, %s", self, addr, port, errors or "unknown") end -- update status local status = self:status() - status.token = nil - status.connected = not ok - self:status_save() -end -]] - --- is connected? -function distcc_build_client:is_connected() - return self:status().connected -end - --- get the status -function distcc_build_client:status() - local status = self._STATUS - local statusfile = self:statusfile() - if not status then - if os.isfile(statusfile) then - status = io.load(statusfile) - end - status = status or {} - self._STATUS = status + status.hosts = status.hosts or {} + local host_status = status.hosts[addr .. ":" .. port] + if host_status then + host_status.token = nil + host_status.connected = not ok end - return status -end - --- save status -function distcc_build_client:status_save() - io.save(self:statusfile(), self:status()) -end - --- get the status file -function distcc_build_client:statusfile() - return path.join(self:workdir(), "status.txt") -end - --- get the project directory -function distcc_build_client:projectdir() - return self._PROJECTDIR -end - --- get working directory -function distcc_build_client:workdir() - return self._WORKDIR -end - --- get user token -function distcc_build_client:token() - return self:status().token -end - --- get the session id, only for unique project -function distcc_build_client:session_id() - return self:status().session_id or hash.uuid():split("-", {plain = true})[1]:lower() + self:status_save() end -- is connected? we cannot depend on client:init when run action diff --git a/xmake/modules/private/service/distcc_build/client_session.lua b/xmake/modules/private/service/distcc_build/client_session.lua index 957e3b550..9f9a36c79 100644 --- a/xmake/modules/private/service/distcc_build/client_session.lua +++ b/xmake/modules/private/service/distcc_build/client_session.lua @@ -86,7 +86,7 @@ end -- get work directory function client_session:workdir() - return path.join(self:workdir(), "sessons", self:id()) + return path.join(self:server():workdir(), "sessons", self:id()) end -- is connected? diff --git a/xmake/modules/private/service/distcc_build/server.lua b/xmake/modules/private/service/distcc_build/server.lua index 80b0e38b3..5d61ab677 100644 --- a/xmake/modules/private/service/distcc_build/server.lua +++ b/xmake/modules/private/service/distcc_build/server.lua @@ -112,7 +112,7 @@ end function distcc_build_server:_session(session_id) local session = self._SESSIONS[session_id] if not session then - session = server_session(server, session_id) + session = server_session(self, session_id) self._SESSIONS[session_id] = session end return session diff --git a/xmake/modules/private/service/distcc_build/server_session.lua b/xmake/modules/private/service/distcc_build/server_session.lua index 9c564f302..5dceedb16 100644 --- a/xmake/modules/private/service/distcc_build/server_session.lua +++ b/xmake/modules/private/service/distcc_build/server_session.lua @@ -86,7 +86,7 @@ end -- get work directory function server_session:workdir() - return path.join(self:server(), "sessons", self:id()) + return path.join(self:server():workdir(), "sessons", self:id()) end -- is connected? diff --git a/xmake/modules/private/service/remote_build/client.lua b/xmake/modules/private/service/remote_build/client.lua index 143ec3d9d..565b0f3c3 100644 --- a/xmake/modules/private/service/remote_build/client.lua +++ b/xmake/modules/private/service/remote_build/client.lua @@ -78,7 +78,7 @@ function remote_build_client:connect() if not token and self:user() then -- get user password - cprint("Please input user ${bright}%s${clear} password:", self:user()) + cprint("Please input user ${bright}%s${clear} password to connect <%s:%d>:", self:user(), self:addr(), self:port()) io.flush() local pass = (io.read() or ""):trim() assert(pass ~= "", "password is empty!") diff --git a/xmake/modules/private/service/server.lua b/xmake/modules/private/service/server.lua index a3971899a..204d6e70e 100644 --- a/xmake/modules/private/service/server.lua +++ b/xmake/modules/private/service/server.lua @@ -106,7 +106,7 @@ end -- verify user function server:verify_user(token, peeraddr) if not token then - return false, "client has no authorization, we need add username to connect address or token to `remote_build.token`!" + return false, "client has no authorization, we need add username to connect address or token!" end -- check authorization |
