Commit d5ac3eb1 authored by Pawel Wodkowski's avatar Pawel Wodkowski Committed by Jim Harris
Browse files

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: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/435507


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarKarol Latecki <karol.latecki@intel.com>
Reviewed-by: default avatarPawel Kaminski <pawelx.kaminski@intel.com>
parent 336faf10
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -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:")