Skip to content

Commit

Permalink
Merge pull request grpc#668 from nathanielmanistaatgoogle/assembly
Browse files Browse the repository at this point in the history
The framework.assembly package.
  • Loading branch information
soltanmm committed Feb 20, 2015
2 parents 98cb476 + 7efe54e commit 04608c4
Show file tree
Hide file tree
Showing 16 changed files with 1,298 additions and 24 deletions.
3 changes: 2 additions & 1 deletion src/python/src/grpc/_adapter/_face_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ def set_up_implementation(
fore_link = fore.ForeLink(
pool, serialization.request_deserializers,
serialization.response_serializers, None, ())
port = fore_link.start()
fore_link.start()
port = fore_link.port()
rear_link = rear.RearLink(
'localhost', port, pool,
serialization.request_serializers, serialization.response_deserializers)
Expand Down
9 changes: 6 additions & 3 deletions src/python/src/grpc/_adapter/_links_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def rear_action(front_to_back_ticket, fore_link):
self.fore_link_pool, {test_method: None}, {test_method: None}, None, ())
fore_link.join_rear_link(test_rear_link)
test_rear_link.join_fore_link(fore_link)
port = fore_link.start()
fore_link.start()
port = fore_link.port()

rear_link = rear.RearLink(
'localhost', port, self.rear_link_pool, {test_method: None},
Expand Down Expand Up @@ -123,7 +124,8 @@ def rear_action(front_to_back_ticket, fore_link):
{test_method: _IDENTITY}, None, ())
fore_link.join_rear_link(test_rear_link)
test_rear_link.join_fore_link(fore_link)
port = fore_link.start()
fore_link.start()
port = fore_link.port()

rear_link = rear.RearLink(
'localhost', port, self.rear_link_pool, {test_method: _IDENTITY},
Expand Down Expand Up @@ -185,7 +187,8 @@ def rear_action(front_to_back_ticket, fore_link):
{test_method: scenario.serialize_response}, None, ())
fore_link.join_rear_link(test_rear_link)
test_rear_link.join_fore_link(fore_link)
port = fore_link.start()
fore_link.start()
port = fore_link.port()

rear_link = rear.RearLink(
'localhost', port, self.rear_link_pool,
Expand Down
50 changes: 41 additions & 9 deletions src/python/src/grpc/_adapter/fore.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from grpc.framework.base.packets import interfaces as ticket_interfaces
from grpc.framework.base.packets import null
from grpc.framework.base.packets import packets as tickets
from grpc.framework.foundation import activated


@enum.unique
Expand All @@ -65,7 +66,7 @@ def _status(call, rpc_state):
rpc_state.write.low = _LowWrite.CLOSED


class ForeLink(ticket_interfaces.ForeLink):
class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
"""A service-side bridge between RPC Framework and the C-ish _low code."""

def __init__(
Expand All @@ -92,13 +93,14 @@ def __init__(
self._response_serializers = response_serializers
self._root_certificates = root_certificates
self._key_chain_pairs = key_chain_pairs
self._port = port
self._requested_port = port

self._rear_link = null.NULL_REAR_LINK
self._completion_queue = None
self._server = None
self._rpc_states = {}
self._spinning = False
self._port = None

def _on_stop_event(self):
self._spinning = False
Expand Down Expand Up @@ -264,35 +266,36 @@ def join_rear_link(self, rear_link):
"""See ticket_interfaces.ForeLink.join_rear_link for specification."""
self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link

def start(self):
def _start(self):
"""Starts this ForeLink.
This method must be called before attempting to exchange tickets with this
object.
"""
with self._condition:
address = '[::]:%d' % (0 if self._port is None else self._port)
address = '[::]:%d' % (
0 if self._requested_port is None else self._requested_port)
self._completion_queue = _low.CompletionQueue()
if self._root_certificates is None and not self._key_chain_pairs:
self._server = _low.Server(self._completion_queue, None)
port = self._server.add_http2_addr(address)
self._port = self._server.add_http2_addr(address)
else:
server_credentials = _low.ServerCredentials(
self._root_certificates, self._key_chain_pairs)
self._server = _low.Server(self._completion_queue, server_credentials)
port = self._server.add_secure_http2_addr(address)
self._port = self._server.add_secure_http2_addr(address)
self._server.start()

self._server.service(None)

self._pool.submit(self._spin, self._completion_queue, self._server)
self._spinning = True

return port
return self

# TODO(nathaniel): Expose graceful-shutdown semantics in which this object
# enters a state in which it finishes ongoing RPCs but refuses new ones.
def stop(self):
def _stop(self):
"""Stops this ForeLink.
This method must be called for proper termination of this object, and no
Expand All @@ -301,14 +304,43 @@ def stop(self):
"""
with self._condition:
self._server.stop()
# TODO(b/18904187): Yep, this is weird. Deleting a server shouldn't have a
# TODO(nathaniel): Yep, this is weird. Deleting a server shouldn't have a
# behaviorally significant side-effect.
self._server = None
self._completion_queue.stop()

while self._spinning:
self._condition.wait()

self._port = None

def __enter__(self):
"""See activated.Activated.__enter__ for specification."""
return self._start()

def __exit__(self, exc_type, exc_val, exc_tb):
"""See activated.Activated.__exit__ for specification."""
self._stop()
return False

def start(self):
"""See activated.Activated.start for specification."""
return self._start()

def stop(self):
"""See activated.Activated.stop for specification."""
self._stop()

def port(self):
"""Identifies the port on which this ForeLink is servicing RPCs.
Returns:
The number of the port on which this ForeLink is servicing RPCs, or None
if this ForeLink is not currently activated and servicing RPCs.
"""
with self._condition:
return self._port

def accept_back_to_front_ticket(self, ticket):
"""See ticket_interfaces.ForeLink.accept_back_to_front_ticket for spec."""
with self._condition:
Expand Down
25 changes: 22 additions & 3 deletions src/python/src/grpc/_adapter/rear.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from grpc.framework.base.packets import interfaces as ticket_interfaces
from grpc.framework.base.packets import null
from grpc.framework.base.packets import packets as tickets
from grpc.framework.foundation import activated

_INVOCATION_EVENT_KINDS = (
_low.Event.Kind.METADATA_ACCEPTED,
Expand Down Expand Up @@ -84,7 +85,7 @@ def _write(operation_id, call, outstanding, write_state, serialized_payload):
raise ValueError('Write attempted after writes completed!')


class RearLink(ticket_interfaces.RearLink):
class RearLink(ticket_interfaces.RearLink, activated.Activated):
"""An invocation-side bridge between RPC Framework and the C-ish _low code."""

def __init__(
Expand Down Expand Up @@ -297,7 +298,7 @@ def join_fore_link(self, fore_link):
with self._condition:
self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link

def start(self):
def _start(self):
"""Starts this RearLink.
This method must be called before attempting to exchange tickets with this
Expand All @@ -306,8 +307,9 @@ def start(self):
with self._condition:
self._completion_queue = _low.CompletionQueue()
self._channel = _low.Channel('%s:%d' % (self._host, self._port))
return self

def stop(self):
def _stop(self):
"""Stops this RearLink.
This method must be called for proper termination of this object, and no
Expand All @@ -321,6 +323,23 @@ def stop(self):
while self._spinning:
self._condition.wait()

def __enter__(self):
"""See activated.Activated.__enter__ for specification."""
return self._start()

def __exit__(self, exc_type, exc_val, exc_tb):
"""See activated.Activated.__exit__ for specification."""
self._stop()
return False

def start(self):
"""See activated.Activated.start for specification."""
return self._start()

def stop(self):
"""See activated.Activated.stop for specification."""
self._stop()

def accept_front_to_back_ticket(self, ticket):
"""See ticket_interfaces.RearLink.accept_front_to_back_ticket for spec."""
with self._condition:
Expand Down
3 changes: 2 additions & 1 deletion src/python/src/grpc/early_adopter/implementations.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def start(self):
self._pool, self._breakdown.request_deserializers,
self._breakdown.response_serializers, None,
((self._private_key, self._certificate_chain),), port=self._port)
port = self._fore_link.start()
self._fore_link.start()
port = self._fore_link.port()
self._back = _tickets_implementations.back(
servicer, self._pool, self._pool, self._pool, _MEGA_TIMEOUT,
_MEGA_TIMEOUT)
Expand Down
30 changes: 30 additions & 0 deletions src/python/src/grpc/framework/assembly/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Loading

0 comments on commit 04608c4

Please sign in to comment.