Home | History | Annotate | Download | only in multiplex
      1 # Copyright 2016 gRPC authors.
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 """A gRPC server servicing both Greeter and RouteGuide RPCs."""
     15 
     16 from concurrent import futures
     17 import time
     18 import math
     19 
     20 import grpc
     21 
     22 import helloworld_pb2
     23 import helloworld_pb2_grpc
     24 import route_guide_pb2
     25 import route_guide_pb2_grpc
     26 import route_guide_resources
     27 
     28 _ONE_DAY_IN_SECONDS = 60 * 60 * 24
     29 
     30 
     31 def _get_feature(feature_db, point):
     32     """Returns Feature at given location or None."""
     33     for feature in feature_db:
     34         if feature.location == point:
     35             return feature
     36     return None
     37 
     38 
     39 def _get_distance(start, end):
     40     """Distance between two points."""
     41     coord_factor = 10000000.0
     42     lat_1 = start.latitude / coord_factor
     43     lat_2 = end.latitude / coord_factor
     44     lon_1 = start.longitude / coord_factor
     45     lon_2 = end.longitude / coord_factor
     46     lat_rad_1 = math.radians(lat_1)
     47     lat_rad_2 = math.radians(lat_2)
     48     delta_lat_rad = math.radians(lat_2 - lat_1)
     49     delta_lon_rad = math.radians(lon_2 - lon_1)
     50 
     51     a = (pow(math.sin(delta_lat_rad / 2), 2) +
     52          (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(
     53              math.sin(delta_lon_rad / 2), 2)))
     54     c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
     55     R = 6371000
     56     # metres
     57     return R * c
     58 
     59 
     60 class _GreeterServicer(helloworld_pb2_grpc.GreeterServicer):
     61 
     62     def SayHello(self, request, context):
     63         return helloworld_pb2.HelloReply(
     64             message='Hello, {}!'.format(request.name))
     65 
     66 
     67 class _RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
     68     """Provides methods that implement functionality of route guide server."""
     69 
     70     def __init__(self):
     71         self.db = route_guide_resources.read_route_guide_database()
     72 
     73     def GetFeature(self, request, context):
     74         feature = _get_feature(self.db, request)
     75         if feature is None:
     76             return route_guide_pb2.Feature(name="", location=request)
     77         else:
     78             return feature
     79 
     80     def ListFeatures(self, request, context):
     81         left = min(request.lo.longitude, request.hi.longitude)
     82         right = max(request.lo.longitude, request.hi.longitude)
     83         top = max(request.lo.latitude, request.hi.latitude)
     84         bottom = min(request.lo.latitude, request.hi.latitude)
     85         for feature in self.db:
     86             if (feature.location.longitude >= left and
     87                     feature.location.longitude <= right and
     88                     feature.location.latitude >= bottom and
     89                     feature.location.latitude <= top):
     90                 yield feature
     91 
     92     def RecordRoute(self, request_iterator, context):
     93         point_count = 0
     94         feature_count = 0
     95         distance = 0.0
     96         prev_point = None
     97 
     98         start_time = time.time()
     99         for point in request_iterator:
    100             point_count += 1
    101             if _get_feature(self.db, point):
    102                 feature_count += 1
    103             if prev_point:
    104                 distance += _get_distance(prev_point, point)
    105             prev_point = point
    106 
    107         elapsed_time = time.time() - start_time
    108         return route_guide_pb2.RouteSummary(
    109             point_count=point_count,
    110             feature_count=feature_count,
    111             distance=int(distance),
    112             elapsed_time=int(elapsed_time))
    113 
    114     def RouteChat(self, request_iterator, context):
    115         prev_notes = []
    116         for new_note in request_iterator:
    117             for prev_note in prev_notes:
    118                 if prev_note.location == new_note.location:
    119                     yield prev_note
    120             prev_notes.append(new_note)
    121 
    122 
    123 def serve():
    124     server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    125     helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer(),
    126                                                       server)
    127     route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
    128         _RouteGuideServicer(), server)
    129     server.add_insecure_port('[::]:50051')
    130     server.start()
    131     try:
    132         while True:
    133             time.sleep(_ONE_DAY_IN_SECONDS)
    134     except KeyboardInterrupt:
    135         server.stop(0)
    136 
    137 
    138 if __name__ == '__main__':
    139     serve()
    140