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 <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/435507
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Pawel Kaminski <pawelx.kaminski@intel.com>
This commit is contained in:
Pawel Wodkowski 2018-11-29 15:12:32 +01:00 committed by Jim Harris
parent 336faf1074
commit d5ac3eb190

View File

@ -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:")