From d5ac3eb190af07446913593f3f7510f452ee896c Mon Sep 17 00:00:00 2001 From: Pawel Wodkowski Date: Thu, 29 Nov 2018 15:12:32 +0100 Subject: [PATCH] scripts/rpc: add support for receiving multiple responses Switch to raw_decode in recv() function. This allow to decode JSON objects one by one. Decoded part is removed from from receive bufer. Change-Id: Id0d78a2ace85bcbb9cc8e30d72da6c1c2cad753c Signed-off-by: Pawel Wodkowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/435507 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker Reviewed-by: Karol Latecki Reviewed-by: Pawel Kaminski --- scripts/rpc/client.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/scripts/rpc/client.py b/scripts/rpc/client.py index 92abd48bf..cfdba7d6b 100644 --- a/scripts/rpc/client.py +++ b/scripts/rpc/client.py @@ -18,7 +18,9 @@ class JSONRPCClient(object): self.sock = None self.verbose = verbose self.timeout = timeout - self.request_id = 0 + self._request_id = 0 + self._recv_buf = "" + self._reqs = [] try: if os.path.exists(addr): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) @@ -40,11 +42,11 @@ class JSONRPCClient(object): self.sock.close() def send(self, method, params=None): - self.request_id += 1 + self._request_id += 1 req = { 'jsonrpc': '2.0', 'method': method, - 'id': self.request_id + 'id': self._request_id } if params: @@ -58,10 +60,18 @@ class JSONRPCClient(object): self.sock.sendall(reqstr.encode("utf-8")) return req + def decode_one_response(self): + try: + buf = self._recv_buf.lstrip() + obj, idx = json.JSONDecoder().raw_decode(buf) + self._recv_buf = buf[idx:] + return obj + except ValueError: + return None + def recv(self): start_time = time.clock() - response = None - buf = '' + response = self.decode_one_response() while not response: try: timeout = self.timeout - (time.clock() - start_time) @@ -70,16 +80,16 @@ class JSONRPCClient(object): if not newdata: self.sock.close() self.sock = None - raise JSONRPCException("Connection closed with partial response:\n%s\n" % buf) - buf += newdata.decode("utf-8") - response = json.loads(buf) + raise JSONRPCException("Connection closed with partial response:\n%s\n" % self._recv_buf) + self._recv_buf += newdata.decode("utf-8") + response = self.decode_one_response() except socket.timeout: break # throw exception after loop to avoid Python freaking out about nested exceptions except ValueError: continue # incomplete response; keep buffering if not response: - raise JSONRPCException("Timeout while waiting for response:\n%s\n" % buf) + raise JSONRPCException("Timeout while waiting for response:\n%s\n" % self._recv_buf) if self.verbose: print("response:")