• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 
15 using System;
16 using System.Collections.Concurrent;
17 using System.Collections.Generic;
18 using System.Diagnostics;
19 using System.Linq;
20 using System.Text;
21 using System.Threading.Tasks;
22 
23 using Grpc.Core;
24 using Grpc.Core.Utils;
25 
26 namespace Routeguide
27 {
28     /// <summary>
29     /// Example implementation of RouteGuide server.
30     /// </summary>
31     public class RouteGuideImpl : RouteGuide.RouteGuideBase
32     {
33         readonly List<Feature> features;
34         readonly object myLock = new object();
35         readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();
36 
RouteGuideImpl(List<Feature> features)37         public RouteGuideImpl(List<Feature> features)
38         {
39             this.features = features;
40         }
41 
42         /// <summary>
43         /// Gets the feature at the requested point. If no feature at that location
44         /// exists, an unnammed feature is returned at the provided location.
45         /// </summary>
GetFeature(Point request, ServerCallContext context)46         public override Task<Feature> GetFeature(Point request, ServerCallContext context)
47         {
48             return Task.FromResult(CheckFeature(request));
49         }
50 
51         /// <summary>
52         /// Gets all features contained within the given bounding rectangle.
53         /// </summary>
ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)54         public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
55         {
56             var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
57             foreach (var response in responses)
58             {
59                 await responseStream.WriteAsync(response);
60             }
61         }
62 
63         /// <summary>
64         /// Gets a stream of points, and responds with statistics about the "trip": number of points,
65         /// number of known features visited, total distance traveled, and total time spent.
66         /// </summary>
RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)67         public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
68         {
69             int pointCount = 0;
70             int featureCount = 0;
71             int distance = 0;
72             Point previous = null;
73             var stopwatch = new Stopwatch();
74             stopwatch.Start();
75 
76             while (await requestStream.MoveNext())
77             {
78                 var point = requestStream.Current;
79                 pointCount++;
80                 if (CheckFeature(point).Exists())
81                 {
82                     featureCount++;
83                 }
84                 if (previous != null)
85                 {
86                     distance += (int) previous.GetDistance(point);
87                 }
88                 previous = point;
89             }
90 
91             stopwatch.Stop();
92 
93             return new RouteSummary
94             {
95                 PointCount = pointCount,
96                 FeatureCount = featureCount,
97                 Distance = distance,
98                 ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000)
99             };
100         }
101 
102         /// <summary>
103         /// Receives a stream of message/location pairs, and responds with a stream of all previous
104         /// messages at each of those locations.
105         /// </summary>
RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)106         public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
107         {
108             while (await requestStream.MoveNext())
109             {
110                 var note = requestStream.Current;
111                 List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
112                 foreach (var prevNote in prevNotes)
113                 {
114                     await responseStream.WriteAsync(prevNote);
115                 }
116             }
117         }
118 
119         /// <summary>
120         /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note).
121         /// </summary>
AddNoteForLocation(Point location, RouteNote note)122         private List<RouteNote> AddNoteForLocation(Point location, RouteNote note)
123         {
124             lock (myLock)
125             {
126                 List<RouteNote> notes;
127                 if (!routeNotes.TryGetValue(location, out notes)) {
128                     notes = new List<RouteNote>();
129                     routeNotes.Add(location, notes);
130                 }
131                 var preexistingNotes = new List<RouteNote>(notes);
132                 notes.Add(note);
133                 return preexistingNotes;
134             }
135         }
136 
137         /// <summary>
138         /// Gets the feature at the given point.
139         /// </summary>
140         /// <param name="location">the location to check</param>
141         /// <returns>The feature object at the point Note that an empty name indicates no feature.</returns>
CheckFeature(Point location)142         private Feature CheckFeature(Point location)
143         {
144             var result = features.FirstOrDefault((feature) => feature.Location.Equals(location));
145             if (result == null)
146             {
147                 // No feature was found, return an unnamed feature.
148                 return new Feature { Name = "", Location = location };
149             }
150             return result;
151         }
152     }
153 }
154