コード例 #1
0
    def _next_ticket(self):
        """Creates the next ticket to be transmitted.

    Returns:
      A links.Ticket to be sent to the other side of the operation or None if
        there is nothing to be sent at this time.
    """
        if self._abort.kind is _Abort.Kind.ABORTED_NO_NOTIFY:
            return None
        elif self._abort.kind is _Abort.Kind.ABORTED_NOTIFY_NEEDED:
            termination = self._abort.termination
            code, details = self._abort.code, self._abort.details
            self._abort = _ABORTED_NO_NOTIFY
            return links.Ticket(self._operation_id,
                                self._lowest_unused_sequence_number, None,
                                None, None, None, None, None, None, None, code,
                                details, termination, None)

        action = False
        # TODO(nathaniel): Support other subscriptions.
        local_subscription = links.Ticket.Subscription.FULL
        timeout = self._timeout
        if timeout is not None:
            self._timeout = None
            action = True
        if self._local_allowance <= 0:
            allowance = None
        else:
            allowance = self._local_allowance
            self._local_allowance = 0
            action = True
        initial_metadata = self._initial_metadata
        if initial_metadata is not None:
            self._initial_metadata = None
            action = True
        if not self._payloads or self._remote_allowance <= 0:
            payload = None
        else:
            payload = self._payloads.pop(0)
            self._remote_allowance -= 1
            action = True
        if self._completion is None or self._payloads:
            terminal_metadata, code, message, termination = None, None, None, None
        else:
            terminal_metadata, code, message, termination = _explode_completion(
                self._completion)
            self._completion = None
            action = True

        if action:
            ticket = links.Ticket(self._operation_id,
                                  self._lowest_unused_sequence_number, None,
                                  None, local_subscription, timeout, allowance,
                                  initial_metadata, payload, terminal_metadata,
                                  code, message, termination, None)
            self._lowest_unused_sequence_number += 1
            return ticket
        else:
            return None
コード例 #2
0
    def testSimplestRoundTrip(self):
        """Tests transmission of one ticket in each direction."""
        invocation_operation_id = object()
        invocation_payload = b'\x07' * 1023
        timeout = test_constants.LONG_TIMEOUT
        invocation_initial_metadata = self.create_invocation_initial_metadata()
        invocation_terminal_metadata = self.create_invocation_terminal_metadata(
        )
        invocation_code, invocation_message = self.create_invocation_completion(
        )
        service_payload = b'\x08' * 1025
        service_initial_metadata = self.create_service_initial_metadata()
        service_terminal_metadata = self.create_service_terminal_metadata()
        service_code, service_message = self.create_service_completion()

        original_invocation_ticket = links.Ticket(
            invocation_operation_id, 0, _TRANSMISSION_GROUP,
            _TRANSMISSION_METHOD, links.Ticket.Subscription.FULL, timeout, 0,
            invocation_initial_metadata, invocation_payload,
            invocation_terminal_metadata, invocation_code, invocation_message,
            links.Ticket.Termination.COMPLETION)
        self._invocation_link.accept_ticket(original_invocation_ticket)

        # TODO(nathaniel): This shouldn't be necessary. Detecting the end of the
        # invocation-side ticket sequence shouldn't require granting allowance for
        # another payload.
        self._service_mate.block_until_tickets_satisfy(
            at_least_n_payloads_received_predicate(1))
        service_operation_id = self._service_mate.tickets()[0].operation_id
        self._service_link.accept_ticket(
            links.Ticket(service_operation_id, 0, None, None,
                         links.Ticket.Subscription.FULL, None, 1, None, None,
                         None, None, None, None))

        self._service_mate.block_until_tickets_satisfy(terminated)
        self._assert_is_valid_invocation_sequence(
            self._service_mate.tickets(), _TRANSMISSION_GROUP,
            _TRANSMISSION_METHOD, (invocation_payload, ),
            invocation_initial_metadata, invocation_terminal_metadata,
            links.Ticket.Termination.COMPLETION)

        original_service_ticket = links.Ticket(
            service_operation_id, 1, None, None,
            links.Ticket.Subscription.FULL, timeout, 0,
            service_initial_metadata, service_payload,
            service_terminal_metadata, service_code, service_message,
            links.Ticket.Termination.COMPLETION)
        self._service_link.accept_ticket(original_service_ticket)
        self._invocation_mate.block_until_tickets_satisfy(terminated)
        self._assert_is_valid_service_sequence(
            self._invocation_mate.tickets(), (service_payload, ),
            service_initial_metadata, service_terminal_metadata, service_code,
            service_message, links.Ticket.Termination.COMPLETION)
コード例 #3
0
    def testZeroMessageRoundTrip(self):
        test_operation_id = object()
        test_group = 'test package.Test Group'
        test_method = 'test method'
        identity_transformation = {(test_group, test_method): _IDENTITY}
        test_code = beta_interfaces.StatusCode.OK
        test_message = 'a test message'

        service_link = service.service_link(identity_transformation,
                                            identity_transformation)
        service_mate = test_utilities.RecordingLink()
        service_link.join_link(service_mate)
        port = service_link.add_port('[::]:0', None)
        service_link.start()
        channel = _intermediary_low.Channel('localhost:%d' % port, None)
        invocation_link = invocation.invocation_link(channel, None, None,
                                                     identity_transformation,
                                                     identity_transformation)
        invocation_mate = test_utilities.RecordingLink()
        invocation_link.join_link(invocation_mate)
        invocation_link.start()

        invocation_ticket = links.Ticket(
            test_operation_id, 0, test_group, test_method,
            links.Ticket.Subscription.FULL, test_constants.LONG_TIMEOUT, None,
            None, None, None, None, None, links.Ticket.Termination.COMPLETION,
            None)
        invocation_link.accept_ticket(invocation_ticket)
        service_mate.block_until_tickets_satisfy(test_cases.terminated)

        service_ticket = links.Ticket(service_mate.tickets()[-1].operation_id,
                                      0, None, None, None, None, None, None,
                                      None, None, test_code, test_message,
                                      links.Ticket.Termination.COMPLETION,
                                      None)
        service_link.accept_ticket(service_ticket)
        invocation_mate.block_until_tickets_satisfy(test_cases.terminated)

        invocation_link.stop()
        service_link.begin_stop()
        service_link.end_stop()

        self.assertIs(service_mate.tickets()[-1].termination,
                      links.Ticket.Termination.COMPLETION)
        self.assertIs(invocation_mate.tickets()[-1].termination,
                      links.Ticket.Termination.COMPLETION)
        self.assertIs(invocation_mate.tickets()[-1].code, test_code)
        self.assertEqual(invocation_mate.tickets()[-1].message, test_message)
コード例 #4
0
    def _test_lonely_invocation_with_termination(self, termination):
        test_operation_id = object()
        test_group = 'test package.Test Service'
        test_method = 'test method'
        invocation_link_mate = test_utilities.RecordingLink()

        channel = _intermediary_low.Channel('nonexistent:54321', None)
        invocation_link = invocation.invocation_link(
            channel, 'nonexistent',
            {(test_group, test_method): _NULL_BEHAVIOR},
            {(test_group, test_method): _NULL_BEHAVIOR})
        invocation_link.join_link(invocation_link_mate)
        invocation_link.start()

        ticket = links.Ticket(test_operation_id, 0, test_group, test_method,
                              links.Ticket.Subscription.FULL,
                              test_constants.SHORT_TIMEOUT, 1, None, None,
                              None, None, None, termination)
        invocation_link.accept_ticket(ticket)
        invocation_link_mate.block_until_tickets_satisfy(test_cases.terminated)

        invocation_link.stop()

        self.assertIsNot(invocation_link_mate.tickets()[-1].termination,
                         links.Ticket.Termination.COMPLETION)
コード例 #5
0
    def _on_service_acceptance_event(self, event, server):
        server.service(None)

        service_acceptance = event.service_acceptance
        call = service_acceptance.call
        call.accept(self._completion_queue, call)
        try:
            group, method = service_acceptance.method.split('/')[1:3]
        except ValueError:
            logging.info('Illegal path "%s"!', service_acceptance.method)
            return
        request_deserializer = self._request_deserializers.get((group, method),
                                                               _IDENTITY)
        response_serializer = self._response_serializers.get((group, method),
                                                             _IDENTITY)

        call.read(call)
        context = _Context(call)
        self._rpc_states[call] = _RPCState(request_deserializer,
                                           response_serializer, 1,
                                           _Read.READING, None, 1,
                                           _HighWrite.OPEN, _LowWrite.OPEN,
                                           False, None, None, None,
                                           set((
                                               _READ,
                                               _FINISH,
                                           )), context)
        protocol = links.Protocol(links.Protocol.Kind.SERVICER_CONTEXT,
                                  context)
        ticket = links.Ticket(call, 0, group, method,
                              links.Ticket.Subscription.FULL,
                              service_acceptance.deadline - time.time(), None,
                              event.metadata, None, None, None, None, None,
                              protocol)
        self._relay.add_value(ticket)
コード例 #6
0
    def _on_service_acceptance_event(self, event, server):
        server.service(None)

        service_acceptance = event.service_acceptance
        call = service_acceptance.call
        call.accept(self._completion_queue, call)
        try:
            group, method = service_acceptance.method.split('/')[1:3]
        except ValueError:
            logging.info('Illegal path "%s"!', service_acceptance.method)
            return
        request_deserializer = self._request_deserializers.get((group, method))
        response_serializer = self._response_serializers.get((group, method))
        if request_deserializer is None or response_serializer is None:
            # TODO(nathaniel): Terminate the RPC with code NOT_FOUND.
            call.cancel()
            return

        call.read(call)
        self._rpc_states[call] = _RPCState(request_deserializer,
                                           response_serializer, 1,
                                           _Read.READING, None, 1,
                                           _HighWrite.OPEN, _LowWrite.OPEN,
                                           False, None, None, None)
        ticket = links.Ticket(call, 0, group, method,
                              links.Ticket.Subscription.FULL,
                              service_acceptance.deadline - time.time(), None,
                              event.metadata, None, None, None, None, None,
                              'TODO: Service Context Object!')
        self._relay.add_value(ticket)
コード例 #7
0
    def _on_read_event(self, event):
        call = event.tag
        rpc_state = self._rpc_states.get(call, None)
        if rpc_state is None:
            return

        if event.bytes is None:
            rpc_state.read = _Read.CLOSED
            payload = None
            termination = links.Ticket.Termination.COMPLETION
        else:
            if 0 < rpc_state.allowance:
                payload = rpc_state.request_deserializer(event.bytes)
                termination = None
                rpc_state.allowance -= 1
                call.read(call)
            else:
                rpc_state.early_read = event.bytes
                return
                # TODO(issue 2916): Instead of returning:
                # rpc_state.read = _Read.AWAITING_ALLOWANCE
        ticket = links.Ticket(call, rpc_state.sequence_number, None, None,
                              None, None, None, None, payload, None, None,
                              None, termination, None)
        rpc_state.sequence_number += 1
        self._relay.add_value(ticket)
コード例 #8
0
def _safe_for_log_ticket(ticket):
    """Creates a safe-for-printing-to-the-log ticket for a given ticket.

  Args:
    ticket: Any links.Ticket.

  Returns:
    A links.Ticket that is as much as can be equal to the given ticket but
      possibly features values like the string "<payload of length 972321>" in
      place of the actual values of the given ticket.
  """
    if isinstance(ticket.payload, (basestring, )):
        payload_length = len(ticket.payload)
    else:
        payload_length = -1
    if payload_length < _UNCOMFORTABLY_LONG:
        return ticket
    else:
        return links.Ticket(ticket.operation_id, ticket.sequence_number,
                            ticket.group, ticket.method, ticket.subscription,
                            ticket.timeout, ticket.allowance,
                            ticket.initial_metadata,
                            '<payload of length {}>'.format(payload_length),
                            ticket.terminal_metadata, ticket.code,
                            ticket.message, ticket.termination, None)
コード例 #9
0
 def _on_metadata_event(self, operation_id, event, rpc_state):
     rpc_state.allowance -= 1
     rpc_state.call.read(operation_id)
     rpc_state.read = _Read.READING
     ticket = links.Ticket(operation_id, rpc_state.sequence_number, None,
                           None, links.Ticket.Subscription.FULL, None, None,
                           event.metadata, None, None, None, None, None)
     rpc_state.sequence_number += 1
     self._relay.add_value(ticket)
コード例 #10
0
 def timeout(self, timeout):
     """See _interfaces.TransmissionManager.timeout for specification."""
     if self._transmitting:
         self._timeout = timeout
     else:
         ticket = links.Ticket(self._operation_id,
                               self._lowest_unused_sequence_number, None,
                               None, None, timeout, None, None, None, None,
                               None, None, None, None)
         self._lowest_unused_sequence_number += 1
         self._transmit(ticket)
コード例 #11
0
    def _invoke(self, operation_id, group, method, initial_metadata, payload,
                termination, timeout, allowance):
        """Invoke an RPC.

    Args:
      operation_id: Any object to be used as an operation ID for the RPC.
      group: The group to which the RPC method belongs.
      method: The RPC method name.
      initial_metadata: The initial metadata object for the RPC.
      payload: A payload object for the RPC or None if no payload was given at
        invocation-time.
      termination: A links.Ticket.Termination value or None indicated whether or
        not more writes will follow from this side of the RPC.
      timeout: A duration of time in seconds to allow for the RPC.
      allowance: The number of payloads (beyond the free first one) that the
        local ticket exchange mate has granted permission to be read.
    """
        if termination is links.Ticket.Termination.COMPLETION:
            high_write = _HighWrite.CLOSED
        elif termination is None:
            high_write = _HighWrite.OPEN
        else:
            return

        request_serializer = self._request_serializers.get((group, method))
        response_deserializer = self._response_deserializers.get(
            (group, method))
        if request_serializer is None or response_deserializer is None:
            cancellation_ticket = links.Ticket(
                operation_id, 0, None, None, None, None, None, None, None,
                None, None, None, links.Ticket.Termination.CANCELLATION)
            self._relay.add_value(cancellation_ticket)
            return

        call = _intermediary_low.Call(self._channel, self._completion_queue,
                                      '/%s/%s' % (group, method), self._host,
                                      time.time() + timeout)
        if initial_metadata is not None:
            for metadata_key, metadata_value in initial_metadata:
                call.add_metadata(metadata_key, metadata_value)
        call.invoke(self._completion_queue, operation_id, operation_id)
        if payload is None:
            if high_write is _HighWrite.CLOSED:
                call.complete(operation_id)
                low_write = _LowWrite.CLOSED
            else:
                low_write = _LowWrite.OPEN
        else:
            call.write(request_serializer(payload), operation_id)
            low_write = _LowWrite.ACTIVE
        self._rpc_states[operation_id] = _RPCState(
            call, request_serializer, response_deserializer, 0,
            _Read.AWAITING_METADATA, 1 if allowance is None else
            (1 + allowance), high_write, low_write)
コード例 #12
0
 def _on_write_event(self, operation_id, unused_event, rpc_state):
     if rpc_state.high_write is _HighWrite.CLOSED:
         rpc_state.call.complete(operation_id)
         rpc_state.low_write = _LowWrite.CLOSED
     else:
         ticket = links.Ticket(operation_id, rpc_state.sequence_number,
                               None, None, None, None, 1, None, None, None,
                               None, None, None)
         rpc_state.sequence_number += 1
         self._relay.add_value(ticket)
         rpc_state.low_write = _LowWrite.OPEN
コード例 #13
0
ファイル: invocation.py プロジェクト: zhouruiapple/grpc
 def _on_write_event(self, operation_id, unused_event, rpc_state):
     if rpc_state.high_write is _HighWrite.CLOSED:
         rpc_state.call.complete(operation_id)
         rpc_state.due.add(_COMPLETE)
         rpc_state.due.remove(_WRITE)
         rpc_state.low_write = _LowWrite.CLOSED
     else:
         ticket = links.Ticket(operation_id, rpc_state.sequence_number,
                               None, None, None, None, 1, None, None, None,
                               None, None, None, None)
         rpc_state.sequence_number += 1
         self._relay.add_value(ticket)
         rpc_state.low_write = _LowWrite.OPEN
         _no_longer_due(_WRITE, rpc_state, operation_id, self._rpc_states)
コード例 #14
0
 def kick_off(self, group, method, timeout, initial_metadata, payload,
              completion, allowance):
     """See _interfaces.TransmissionManager.kickoff for specification."""
     # TODO(nathaniel): Support other subscriptions.
     subscription = links.Ticket.Subscription.FULL
     terminal_metadata, code, message, termination = _explode_completion(
         completion)
     self._remote_allowance = 1 if payload is None else 0
     ticket = links.Ticket(self._operation_id, 0, group, method,
                           subscription, timeout, allowance,
                           initial_metadata, payload, terminal_metadata,
                           code, message, termination, None)
     self._lowest_unused_sequence_number = 1
     self._transmit(ticket)
コード例 #15
0
 def _on_read_event(self, operation_id, event, rpc_state):
     if event.bytes is None:
         rpc_state.read = _Read.CLOSED
     else:
         if 0 < rpc_state.allowance:
             rpc_state.allowance -= 1
             rpc_state.call.read(operation_id)
         else:
             rpc_state.read = _Read.AWAITING_ALLOWANCE
         ticket = links.Ticket(operation_id, rpc_state.sequence_number,
                               None, None, None, None, None, None,
                               rpc_state.response_deserializer(event.bytes),
                               None, None, None, None)
         rpc_state.sequence_number += 1
         self._relay.add_value(ticket)
コード例 #16
0
    def advance(self, initial_metadata, payload, completion, allowance):
        """See _interfaces.TransmissionManager.advance for specification."""
        if self._abort.kind is not _Abort.Kind.NOT_ABORTED:
            return

        effective_initial_metadata = initial_metadata
        effective_payload = payload
        effective_completion = completion
        if allowance is not None and not self._remote_complete:
            effective_allowance = allowance
        else:
            effective_allowance = None
        if self._transmitting:
            if effective_initial_metadata is not None:
                self._initial_metadata = effective_initial_metadata
            if effective_payload is not None:
                self._payloads.append(effective_payload)
            if effective_completion is not None:
                self._completion = effective_completion
            if effective_allowance is not None:
                self._local_allowance += effective_allowance
        else:
            if effective_payload is not None:
                if 0 < self._remote_allowance:
                    ticket_payload = effective_payload
                    self._remote_allowance -= 1
                else:
                    self._payloads.append(effective_payload)
                    ticket_payload = None
            else:
                ticket_payload = None
            if effective_completion is not None and not self._payloads:
                ticket_completion = effective_completion
            else:
                self._completion = effective_completion
                ticket_completion = None
            if any((effective_initial_metadata, ticket_payload,
                    ticket_completion, effective_allowance)):
                terminal_metadata, code, message, termination = _explode_completion(
                    completion)
                ticket = links.Ticket(self._operation_id,
                                      self._lowest_unused_sequence_number,
                                      None, None, None, None, allowance,
                                      effective_initial_metadata,
                                      ticket_payload, terminal_metadata, code,
                                      message, termination, None)
                self._lowest_unused_sequence_number += 1
                self._transmit(ticket)
コード例 #17
0
 def abort(self, outcome):
     """See _interfaces.TransmissionManager.abort for specification."""
     if self._transmitting:
         self._aborted, self._abortion_outcome = True, outcome
     else:
         self._aborted = True
         if outcome is not None:
             termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION[
                 outcome]
             if termination is not None:
                 ticket = links.Ticket(self._operation_id,
                                       self._lowest_unused_sequence_number,
                                       None, None, None, None, None, None,
                                       None, None, None, None, termination,
                                       None)
                 self._transmit(ticket)
コード例 #18
0
ファイル: invocation.py プロジェクト: zhouruiapple/grpc
 def _on_metadata_event(self, operation_id, event, rpc_state):
     if _FINISH in rpc_state.due:
         rpc_state.allowance -= 1
         rpc_state.call.read(operation_id)
         rpc_state.read = _Read.READING
         rpc_state.due.add(_READ)
         rpc_state.due.remove(_METADATA)
         ticket = links.Ticket(operation_id, rpc_state.sequence_number,
                               None, None, links.Ticket.Subscription.FULL,
                               None, None, event.metadata, None, None, None,
                               None, None, None)
         rpc_state.sequence_number += 1
         self._relay.add_value(ticket)
     else:
         _no_longer_due(_METADATA, rpc_state, operation_id,
                        self._rpc_states)
コード例 #19
0
 def _on_finish_event(self, operation_id, event, rpc_state):
     self._rpc_states.pop(operation_id, None)
     if event.status.code is _intermediary_low.Code.OK:
         termination = links.Ticket.Termination.COMPLETION
     elif event.status.code is _intermediary_low.Code.CANCELLED:
         termination = links.Ticket.Termination.CANCELLATION
     elif event.status.code is _intermediary_low.Code.DEADLINE_EXCEEDED:
         termination = links.Ticket.Termination.EXPIRATION
     else:
         termination = links.Ticket.Termination.TRANSMISSION_FAILURE
     ticket = links.Ticket(operation_id, rpc_state.sequence_number, None,
                           None, None, None, None, None, None,
                           event.metadata, event.status.code,
                           event.status.details, termination)
     rpc_state.sequence_number += 1
     self._relay.add_value(ticket)
コード例 #20
0
 def abort(self, outcome, code, message):
     """See _interfaces.TransmissionManager.abort for specification."""
     if self._abort.kind is _Abort.Kind.NOT_ABORTED:
         termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION.get(
             outcome)
         if termination is None:
             self._abort = _ABORTED_NO_NOTIFY
         elif self._transmitting:
             self._abort = _Abort(_Abort.Kind.ABORTED_NOTIFY_NEEDED,
                                  termination, code, message)
         else:
             ticket = links.Ticket(self._operation_id,
                                   self._lowest_unused_sequence_number,
                                   None, None, None, None, None, None, None,
                                   None, code, message, termination, None)
             self._transmit(ticket)
コード例 #21
0
    def _on_finish_event(self, event):
        call = event.tag
        rpc_state = self._rpc_states[call]
        _no_longer_due(_FINISH, rpc_state, call, self._rpc_states)
        code = event.status.code
        if code is _intermediary_low.Code.OK:
            return

        if code is _intermediary_low.Code.CANCELLED:
            termination = links.Ticket.Termination.CANCELLATION
        elif code is _intermediary_low.Code.DEADLINE_EXCEEDED:
            termination = links.Ticket.Termination.EXPIRATION
        else:
            termination = links.Ticket.Termination.TRANSMISSION_FAILURE
        ticket = links.Ticket(call, rpc_state.sequence_number, None, None,
                              None, None, None, None, None, None, None, None,
                              termination, None)
        rpc_state.sequence_number += 1
        self._relay.add_value(ticket)
コード例 #22
0
    def _on_write_event(self, event):
        call = event.tag
        rpc_state = self._rpc_states.get(call, None)
        if rpc_state is None:
            return

        if rpc_state.high_write is _HighWrite.CLOSED:
            if rpc_state.terminal_metadata is not None:
                _metadatafy(call, rpc_state.terminal_metadata)
            call.status(
                _intermediary_low.Status(rpc_state.code, rpc_state.message),
                call)
            rpc_state.low_write = _LowWrite.CLOSED
        else:
            ticket = links.Ticket(call, rpc_state.sequence_number, None, None,
                                  None, None, 1, None, None, None, None, None,
                                  None, None)
            rpc_state.sequence_number += 1
            self._relay.add_value(ticket)
            rpc_state.low_write = _LowWrite.OPEN
コード例 #23
0
 def allowance(self, allowance):
     """See _interfaces.TransmissionManager.allowance for specification."""
     if self._transmitting or not self._payloads:
         self._remote_allowance += allowance
     else:
         self._remote_allowance += allowance - 1
         payload = self._payloads.pop(0)
         if self._payloads:
             completion = None
         else:
             completion = self._completion
             self._completion = None
         terminal_metadata, code, message, termination = _explode_completion(
             completion)
         ticket = links.Ticket(self._operation_id,
                               self._lowest_unused_sequence_number, None,
                               None, None, None, None, None, payload,
                               terminal_metadata, code, message,
                               termination, None)
         self._lowest_unused_sequence_number += 1
         self._transmit(ticket)
コード例 #24
0
    def _on_write_event(self, event):
        call = event.tag
        rpc_state = self._rpc_states[call]

        if rpc_state.high_write is _HighWrite.CLOSED:
            if rpc_state.terminal_metadata is not None:
                _metadatafy(call, rpc_state.terminal_metadata)
            status = _status(links.Ticket.Termination.COMPLETION,
                             rpc_state.code, rpc_state.message)
            call.status(status, call)
            rpc_state.low_write = _LowWrite.CLOSED
            rpc_state.due.add(_COMPLETE)
            rpc_state.due.remove(_WRITE)
        else:
            ticket = links.Ticket(call, rpc_state.sequence_number, None, None,
                                  None, None, 1, None, None, None, None, None,
                                  None, None)
            rpc_state.sequence_number += 1
            self._relay.add_value(ticket)
            rpc_state.low_write = _LowWrite.OPEN
            _no_longer_due(_WRITE, rpc_state, call, self._rpc_states)
コード例 #25
0
ファイル: invocation.py プロジェクト: zhouruiapple/grpc
 def _on_finish_event(self, operation_id, event, rpc_state):
     _no_longer_due(_FINISH, rpc_state, operation_id, self._rpc_states)
     if event.status.code == _intermediary_low.Code.OK:
         termination = links.Ticket.Termination.COMPLETION
     elif event.status.code == _intermediary_low.Code.CANCELLED:
         termination = links.Ticket.Termination.CANCELLATION
     elif event.status.code == _intermediary_low.Code.DEADLINE_EXCEEDED:
         termination = links.Ticket.Termination.EXPIRATION
     elif event.status.code == _intermediary_low.Code.UNIMPLEMENTED:
         termination = links.Ticket.Termination.REMOTE_FAILURE
     elif event.status.code == _intermediary_low.Code.UNKNOWN:
         termination = links.Ticket.Termination.LOCAL_FAILURE
     else:
         termination = links.Ticket.Termination.TRANSMISSION_FAILURE
     code = _constants.LOW_STATUS_CODE_TO_HIGH_STATUS_CODE[
         event.status.code]
     ticket = links.Ticket(operation_id, rpc_state.sequence_number, None,
                           None, None, None, None, None, None,
                           event.metadata, code, event.status.details,
                           termination, None)
     rpc_state.sequence_number += 1
     self._relay.add_value(ticket)
コード例 #26
0
ファイル: _transmission_test.py プロジェクト: mindware/grpc
    def _perform_scenario_test(self, scenario):
        test_operation_id = object()
        test_group, test_method = scenario.group_and_method()
        test_code = _intermediary_low.Code.OK
        test_message = 'a scenario test message'

        service_link = service.service_link(
            {(test_group, test_method): scenario.deserialize_request},
            {(test_group, test_method): scenario.serialize_response})
        service_mate = test_utilities.RecordingLink()
        service_link.join_link(service_mate)
        port = service_link.add_port('[::]:0', None)
        service_link.start()
        channel = _intermediary_low.Channel('localhost:%d' % port, None)
        invocation_link = invocation.invocation_link(
            channel, 'localhost', None,
            {(test_group, test_method): scenario.serialize_request},
            {(test_group, test_method): scenario.deserialize_response})
        invocation_mate = test_utilities.RecordingLink()
        invocation_link.join_link(invocation_mate)
        invocation_link.start()

        invocation_ticket = links.Ticket(test_operation_id, 0, test_group,
                                         test_method,
                                         links.Ticket.Subscription.FULL,
                                         test_constants.LONG_TIMEOUT, None,
                                         None, None, None, None, None, None,
                                         None)
        invocation_link.accept_ticket(invocation_ticket)
        requests = scenario.requests()
        for request_index, request in enumerate(requests):
            request_ticket = links.Ticket(test_operation_id, 1 + request_index,
                                          None, None, None, None, 1, None,
                                          request, None, None, None, None,
                                          None)
            invocation_link.accept_ticket(request_ticket)
            service_mate.block_until_tickets_satisfy(
                test_cases.at_least_n_payloads_received_predicate(
                    1 + request_index))
            response_ticket = links.Ticket(
                service_mate.tickets()[0].operation_id, request_index, None,
                None, None, None, 1, None,
                scenario.response_for_request(request), None, None, None, None,
                None)
            service_link.accept_ticket(response_ticket)
            invocation_mate.block_until_tickets_satisfy(
                test_cases.at_least_n_payloads_received_predicate(
                    1 + request_index))
        request_count = len(requests)
        invocation_completion_ticket = links.Ticket(
            test_operation_id, request_count + 1, None, None, None, None, None,
            None, None, None, None, None, links.Ticket.Termination.COMPLETION,
            None)
        invocation_link.accept_ticket(invocation_completion_ticket)
        service_mate.block_until_tickets_satisfy(test_cases.terminated)
        service_completion_ticket = links.Ticket(
            service_mate.tickets()[0].operation_id, request_count, None, None,
            None, None, None, None, None, None, test_code, test_message,
            links.Ticket.Termination.COMPLETION, None)
        service_link.accept_ticket(service_completion_ticket)
        invocation_mate.block_until_tickets_satisfy(test_cases.terminated)

        invocation_link.stop()
        service_link.begin_stop()
        service_link.end_stop()

        observed_requests = tuple(ticket.payload
                                  for ticket in service_mate.tickets()
                                  if ticket.payload is not None)
        observed_responses = tuple(ticket.payload
                                   for ticket in invocation_mate.tickets()
                                   if ticket.payload is not None)
        self.assertTrue(scenario.verify_requests(observed_requests))
        self.assertTrue(scenario.verify_responses(observed_responses))
コード例 #27
0
    def _next_ticket(self):
        """Creates the next ticket to be transmitted.

    Returns:
      A links.Ticket to be sent to the other side of the operation or None if
        there is nothing to be sent at this time.
    """
        if self._aborted:
            if self._abortion_outcome is None:
                return None
            else:
                termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION[
                    self._abortion_outcome]
                if termination is None:
                    return None
                else:
                    self._abortion_outcome = None
                    return links.Ticket(self._operation_id,
                                        self._lowest_unused_sequence_number,
                                        None, None, None, None, None, None,
                                        None, None, None, None, termination,
                                        None)

        action = False
        # TODO(nathaniel): Support other subscriptions.
        local_subscription = links.Ticket.Subscription.FULL
        timeout = self._timeout
        if timeout is not None:
            self._timeout = None
            action = True
        if self._local_allowance <= 0:
            allowance = None
        else:
            allowance = self._local_allowance
            self._local_allowance = 0
            action = True
        initial_metadata = self._initial_metadata
        if initial_metadata is not None:
            self._initial_metadata = None
            action = True
        if not self._payloads or self._remote_allowance <= 0:
            payload = None
        else:
            payload = self._payloads.pop(0)
            self._remote_allowance -= 1
            action = True
        if self._completion is None or self._payloads:
            terminal_metadata, code, message, termination = None, None, None, None
        else:
            terminal_metadata, code, message, termination = _explode_completion(
                self._completion)
            self._completion = None
            action = True

        if action:
            ticket = links.Ticket(self._operation_id,
                                  self._lowest_unused_sequence_number, None,
                                  None, local_subscription, timeout, allowance,
                                  initial_metadata, payload, terminal_metadata,
                                  code, message, termination, None)
            self._lowest_unused_sequence_number += 1
            return ticket
        else:
            return None
コード例 #28
0
    def add_ticket(self, ticket):
        with self._lock:
            call = ticket.operation_id
            rpc_state = self._rpc_states.get(call)
            if rpc_state is None:
                return

            if ticket.initial_metadata is not None:
                _metadatafy(call, ticket.initial_metadata)
                call.premetadata()
                rpc_state.premetadataed = True
            elif not rpc_state.premetadataed:
                if (ticket.terminal_metadata is not None
                        or ticket.payload is not None
                        or ticket.termination is not None
                        or ticket.code is not None
                        or ticket.message is not None):
                    call.premetadata()
                    rpc_state.premetadataed = True

            if ticket.allowance is not None:
                if rpc_state.early_read is None:
                    rpc_state.allowance += ticket.allowance
                else:
                    payload = rpc_state.request_deserializer(
                        rpc_state.early_read)
                    rpc_state.allowance += ticket.allowance - 1
                    rpc_state.early_read = None
                    if rpc_state.read is _Read.READING:
                        call.read(call)
                        rpc_state.due.add(_READ)
                        termination = None
                    else:
                        termination = links.Ticket.Termination.COMPLETION
                    early_read_ticket = links.Ticket(call,
                                                     rpc_state.sequence_number,
                                                     None, None, None, None,
                                                     None, None, payload, None,
                                                     None, None, termination,
                                                     None)
                    rpc_state.sequence_number += 1
                    self._relay.add_value(early_read_ticket)

            if ticket.payload is not None:
                disable_compression = rpc_state.context.next_compression_disabled(
                )
                if disable_compression:
                    flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS
                else:
                    flags = 0
                call.write(rpc_state.response_serializer(ticket.payload), call,
                           flags)
                rpc_state.due.add(_WRITE)
                rpc_state.low_write = _LowWrite.ACTIVE

            if ticket.terminal_metadata is not None:
                rpc_state.terminal_metadata = ticket.terminal_metadata
            if ticket.code is not None:
                rpc_state.code = ticket.code
            if ticket.message is not None:
                rpc_state.message = ticket.message

            if ticket.termination is links.Ticket.Termination.COMPLETION:
                rpc_state.high_write = _HighWrite.CLOSED
                if rpc_state.low_write is _LowWrite.OPEN:
                    if rpc_state.terminal_metadata is not None:
                        _metadatafy(call, rpc_state.terminal_metadata)
                    status = _status(links.Ticket.Termination.COMPLETION,
                                     rpc_state.code, rpc_state.message)
                    call.status(status, call)
                    rpc_state.due.add(_COMPLETE)
                    rpc_state.low_write = _LowWrite.CLOSED
            elif ticket.termination is not None:
                if rpc_state.terminal_metadata is not None:
                    _metadatafy(call, rpc_state.terminal_metadata)
                status = _status(ticket.termination, rpc_state.code,
                                 rpc_state.message)
                call.status(status, call)
                rpc_state.due.add(_COMPLETE)
コード例 #29
0
    def add_ticket(self, ticket):
        with self._lock:
            if self._server is None:
                return
            call = ticket.operation_id
            rpc_state = self._rpc_states.get(call)
            if rpc_state is None:
                return

            if ticket.initial_metadata is not None:
                _metadatafy(call, ticket.initial_metadata)
                call.premetadata()
                rpc_state.premetadataed = True
            elif not rpc_state.premetadataed:
                if (ticket.terminal_metadata is not None
                        or ticket.payload is not None
                        or ticket.termination is not None
                        or ticket.code is not None
                        or ticket.message is not None):
                    call.premetadata()
                    rpc_state.premetadataed = True

            if ticket.allowance is not None:
                if rpc_state.early_read is None:
                    rpc_state.allowance += ticket.allowance
                else:
                    payload = rpc_state.request_deserializer(
                        rpc_state.early_read)
                    rpc_state.allowance += ticket.allowance - 1
                    rpc_state.early_read = None
                    if rpc_state.read is _Read.READING:
                        call.read(call)
                        termination = None
                    else:
                        termination = links.Ticket.Termination.COMPLETION
                    early_read_ticket = links.Ticket(call,
                                                     rpc_state.sequence_number,
                                                     None, None, None, None,
                                                     None, None, payload, None,
                                                     None, None, termination,
                                                     None)
                    rpc_state.sequence_number += 1
                    self._relay.add_value(early_read_ticket)

            if ticket.payload is not None:
                call.write(rpc_state.response_serializer(ticket.payload), call)
                rpc_state.low_write = _LowWrite.ACTIVE

            if ticket.terminal_metadata is not None:
                rpc_state.terminal_metadata = ticket.terminal_metadata
            if ticket.code is not None:
                rpc_state.code = ticket.code
            if ticket.message is not None:
                rpc_state.message = ticket.message

            if ticket.termination is links.Ticket.Termination.COMPLETION:
                rpc_state.high_write = _HighWrite.CLOSED
                if rpc_state.low_write is _LowWrite.OPEN:
                    if rpc_state.terminal_metadata is not None:
                        _metadatafy(call, rpc_state.terminal_metadata)
                    status = _intermediary_low.Status(
                        _intermediary_low.Code.OK
                        if rpc_state.code is None else rpc_state.code,
                        '' if rpc_state.message is None else rpc_state.message)
                    call.status(status, call)
                    rpc_state.low_write = _LowWrite.CLOSED
            elif ticket.termination is not None:
                call.cancel()
                self._rpc_states.pop(call, None)
コード例 #30
0
ファイル: invocation.py プロジェクト: zhouruiapple/grpc
    def _invoke(self, operation_id, group, method, initial_metadata, payload,
                termination, timeout, allowance, options):
        """Invoke an RPC.

    Args:
      operation_id: Any object to be used as an operation ID for the RPC.
      group: The group to which the RPC method belongs.
      method: The RPC method name.
      initial_metadata: The initial metadata object for the RPC.
      payload: A payload object for the RPC or None if no payload was given at
        invocation-time.
      termination: A links.Ticket.Termination value or None indicated whether or
        not more writes will follow from this side of the RPC.
      timeout: A duration of time in seconds to allow for the RPC.
      allowance: The number of payloads (beyond the free first one) that the
        local ticket exchange mate has granted permission to be read.
      options: A beta_interfaces.GRPCCallOptions value or None.
    """
        if termination is links.Ticket.Termination.COMPLETION:
            high_write = _HighWrite.CLOSED
        elif termination is None:
            high_write = _HighWrite.OPEN
        else:
            return

        transformed_initial_metadata = self._metadata_transformer(
            initial_metadata)
        request_serializer = self._request_serializers.get((group, method),
                                                           _IDENTITY)
        response_deserializer = self._response_deserializers.get(
            (group, method), _IDENTITY)

        call = _intermediary_low.Call(self._channel, self._completion_queue,
                                      '/%s/%s' % (group, method), self._host,
                                      time.time() + timeout)
        if options is not None and options.credentials is not None:
            call.set_credentials(options.credentials._low_credentials)
        if transformed_initial_metadata is not None:
            for metadata_key, metadata_value in transformed_initial_metadata:
                call.add_metadata(metadata_key, metadata_value)
        call.invoke(self._completion_queue, operation_id, operation_id)
        if payload is None:
            if high_write is _HighWrite.CLOSED:
                call.complete(operation_id)
                low_write = _LowWrite.CLOSED
                due = set((
                    _METADATA,
                    _COMPLETE,
                    _FINISH,
                ))
            else:
                low_write = _LowWrite.OPEN
                due = set((
                    _METADATA,
                    _FINISH,
                ))
        else:
            if options is not None and options.disable_compression:
                flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS
            else:
                flags = 0
            call.write(request_serializer(payload), operation_id, flags)
            low_write = _LowWrite.ACTIVE
            due = set((
                _WRITE,
                _METADATA,
                _FINISH,
            ))
        context = _Context()
        self._rpc_states[operation_id] = _RPCState(
            call, request_serializer, response_deserializer, 1,
            _Read.AWAITING_METADATA, 1 if allowance is None else
            (1 + allowance), high_write, low_write, due, context)
        protocol = links.Protocol(links.Protocol.Kind.INVOCATION_CONTEXT,
                                  context)
        ticket = links.Ticket(operation_id, 0, None, None, None, None, None,
                              None, None, None, None, None, None, protocol)
        self._relay.add_value(ticket)