예제 #1
0
 def _recv_msg(self, mid_stream=False):
     """
     :param mid_stream: are we receiving in a streaming operation?
     :type mid_stream: boolean
     """
     try:
         msgbuf = self._recv_pkt()
     except BadResource as e:
         e.mid_stream = mid_stream
         raise
     except socket.timeout as e:
         # A timeout can leave the socket in an inconsistent state because
         # it might still receive the data later and mix up with a
         # subsequent request.
         # https://github.com/basho/riak-python-client/issues/425
         raise BadResource(e, mid_stream)
     mv = memoryview(msgbuf)
     mcb = mv[0:1]
     if self.bytes_required:
         mcb = mcb.tobytes()
     try:
         msg_code, = struct.unpack("B", mcb)
     except struct.error:
         # NB: Python 2.7.3 requires this
         # http://bugs.python.org/issue10212
         msg_code, = struct.unpack("B", mv[0:1].tobytes())
         self.bytes_required = True
     data = mv[1:].tobytes()
     return (msg_code, data)
예제 #2
0
 def test_bad_resource_inner_exception(self):
     ex_msg = 'exception-message!'
     ex = RiakError(ex_msg)
     with self.assertRaises(BadResource) as cm:
         raise BadResource(ex)
     br_ex = cm.exception
     self.assertEqual(br_ex.args[0], ex)
예제 #3
0
    def _with_retries(self, pool, fn):
        """
        Performs the passed function with retries against the given pool.

        :param pool: the connection pool to use
        :type pool: Pool
        :param fn: the function to pass a transport
        :type fn: function
        """
        skip_nodes = []

        def _skip_bad_nodes(transport):
            return transport._node not in skip_nodes

        retry_count = self.RETRY_COUNT

        for retry in range(retry_count):
            try:
                with pool.take(_filter=_skip_bad_nodes) as transport:
                    try:
                        return fn(transport)
                    except (IOError, httplib.HTTPException) as e:
                        if _is_retryable(e):
                            transport._node.error_rate.incr(1)
                            skip_nodes.append(transport._node)
                            raise BadResource(e)
                        else:
                            raise
            except BadResource as e:
                if retry < (retry_count - 1):
                    continue
                else:
                    # Re-raise the inner exception
                    raise e.args[0]
예제 #4
0
    def _with_retries(self, pool, fn):
        """
        Performs the passed function with retries against the given pool.

        :param pool: the connection pool to use
        :type pool: Pool
        :param fn: the function to pass a transport
        :type fn: function
        """
        skip_nodes = []

        def _skip_bad_nodes(transport):
            return transport._node not in skip_nodes

        retry_count = self.retries - 1
        first_try = True
        current_try = 0
        while True:
            try:
                with pool.transaction(
                        _filter=_skip_bad_nodes,
                        yield_resource=True) as resource:
                    transport = resource.object
                    try:
                        return fn(transport)
                    except (IOError, HTTPException, ConnectionClosed) as e:
                        resource.errored = True
                        if _is_retryable(e):
                            transport._node.error_rate.incr(1)
                            skip_nodes.append(transport._node)
                            if first_try:
                                continue
                            else:
                                raise BadResource(e)
                        else:
                            raise
            except BadResource as e:
                if current_try < retry_count:
                    resource.errored = True
                    current_try += 1
                    continue
                else:
                    # Re-raise the inner exception
                    raise e.args[0]
            finally:
                first_try = False
예제 #5
0
 def _recv(self, msglen):
     # TODO FUTURE re-use buffer
     # http://stackoverflow.com/a/15964489
     msgbuf = bytearray(msglen)
     view = memoryview(msgbuf)
     nread = 0
     toread = msglen
     while toread:
         nbytes = self._socket.recv_into(view, toread)
         # https://docs.python.org/2/howto/sockets.html#using-a-socket
         # https://github.com/basho/riak-python-client/issues/399
         if nbytes == 0:
             ex = RiakError('recv_into returned zero bytes unexpectedly')
             raise BadResource(ex)
         view = view[nbytes:]  # slicing views is cheap
         toread -= nbytes
         nread += nbytes
     if nread != msglen:
         raise RiakError("Socket returned short packet %d - expected %d" %
                         (nread, msglen))
     return msgbuf
예제 #6
0
    def _request(self, msg, codec=None):
        if isinstance(msg, Msg):
            msg_code = msg.msg_code
            data = msg.data
            expect = msg.resp_code
        else:
            raise ValueError('expected a Msg argument')

        if not isinstance(codec, Codec):
            raise ValueError('expected a Codec argument')

        resp_code, data = self._send_recv(msg_code, data)
        # NB: decodes errors with msg code 0
        codec.maybe_riak_error(resp_code, data)
        codec.maybe_incorrect_code(resp_code, expect)
        if resp_code == MSG_CODE_TS_TTB_MSG or \
           resp_code in riak.pb.messages.MESSAGE_CLASSES:
            msg = codec.parse_msg(resp_code, data)
        else:
            # NB: raise a BadResource to ensure this connection is
            # closed and not re-used
            raise BadResource('unknown msg code {}'.format(resp_code))
        return resp_code, msg
예제 #7
0
 def test_can_raise_bad_resource(self):
     ex_msg = 'exception-message!'
     with self.assertRaises(BadResource) as cm:
         raise BadResource(ex_msg)
     ex = cm.exception
     self.assertEqual(ex.args[0], ex_msg)