aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs')
-rw-r--r--examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs128
1 files changed, 41 insertions, 87 deletions
diff --git a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
index 0bdf386fc3..fbe0f4471c 100644
--- a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
+++ b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
@@ -6,7 +6,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace examples
+using Grpc.Core.Utils;
+
+namespace Examples
{
/// <summary>
/// Example implementation of RouteGuide server.
@@ -14,8 +16,8 @@ namespace examples
public class RouteGuideImpl : RouteGuide.IRouteGuide
{
readonly List<Feature> features;
- private readonly ConcurrentDictionary<Point, List<RouteNote>> routeNotes =
- new ConcurrentDictionary<Point, List<RouteNote>>();
+ readonly object myLock = new object();
+ readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();
public RouteGuideImpl(List<Feature> features)
{
@@ -26,7 +28,7 @@ namespace examples
/// Gets the feature at the requested point. If no feature at that location
/// exists, an unnammed feature is returned at the provided location.
/// </summary>
- public Task<Feature> GetFeature(Grpc.Core.ServerCallContext context, Point request)
+ public Task<Feature> GetFeature(Point request, Grpc.Core.ServerCallContext context)
{
return Task.FromResult(CheckFeature(request));
}
@@ -34,26 +36,12 @@ namespace examples
/// <summary>
/// Gets all features contained within the given bounding rectangle.
/// </summary>
- public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream)
+ public async Task ListFeatures(Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream, Grpc.Core.ServerCallContext context)
{
- int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude);
- int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude);
- int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude);
- int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude);
-
- foreach (var feature in features)
+ var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
+ foreach (var response in responses)
{
- if (!RouteGuideUtil.Exists(feature))
- {
- continue;
- }
-
- int lat = feature.Location.Latitude;
- int lon = feature.Location.Longitude;
- if (lon >= left && lon <= right && lat >= bottom && lat <= top)
- {
- await responseStream.WriteAsync(feature);
- }
+ await responseStream.WriteAsync(response);
}
}
@@ -61,7 +49,7 @@ namespace examples
/// Gets a stream of points, and responds with statistics about the "trip": number of points,
/// number of known features visited, total distance traveled, and total time spent.
/// </summary>
- public async Task<RouteSummary> RecordRoute(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader<Point> requestStream)
+ public async Task<RouteSummary> RecordRoute(Grpc.Core.IAsyncStreamReader<Point> requestStream, Grpc.Core.ServerCallContext context)
{
int pointCount = 0;
int featureCount = 0;
@@ -74,61 +62,61 @@ namespace examples
{
var point = requestStream.Current;
pointCount++;
- if (RouteGuideUtil.Exists(CheckFeature(point)))
+ if (CheckFeature(point).Exists())
{
featureCount++;
}
if (previous != null)
{
- distance += (int) CalcDistance(previous, point);
+ distance += (int) previous.GetDistance(point);
}
previous = point;
}
stopwatch.Stop();
- return RouteSummary.CreateBuilder().SetPointCount(pointCount)
- .SetFeatureCount(featureCount).SetDistance(distance)
- .SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build();
+
+ return new RouteSummary
+ {
+ PointCount = pointCount,
+ FeatureCount = featureCount,
+ Distance = distance,
+ ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000)
+ };
}
/// <summary>
/// Receives a stream of message/location pairs, and responds with a stream of all previous
/// messages at each of those locations.
/// </summary>
- public async Task RouteChat(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream)
+ public async Task RouteChat(Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream, Grpc.Core.ServerCallContext context)
{
while (await requestStream.MoveNext())
{
var note = requestStream.Current;
- List<RouteNote> notes = GetOrCreateNotes(note.Location);
-
- List<RouteNote> prevNotes;
- lock (notes)
- {
- prevNotes = new List<RouteNote>(notes);
- }
-
+ List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
foreach (var prevNote in prevNotes)
{
await responseStream.WriteAsync(prevNote);
- }
-
- lock (notes)
- {
- notes.Add(note);
}
}
}
-
/// <summary>
- /// Get the notes list for the given location. If missing, create it.
+ /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note).
/// </summary>
- private List<RouteNote> GetOrCreateNotes(Point location)
+ private List<RouteNote> AddNoteForLocation(Point location, RouteNote note)
{
- List<RouteNote> notes = new List<RouteNote>();
- routeNotes.TryAdd(location, notes);
- return routeNotes[location];
+ lock (myLock)
+ {
+ List<RouteNote> notes;
+ if (!routeNotes.TryGetValue(location, out notes)) {
+ notes = new List<RouteNote>();
+ routeNotes.Add(location, notes);
+ }
+ var preexistingNotes = new List<RouteNote>(notes);
+ notes.Add(note);
+ return preexistingNotes;
+ }
}
/// <summary>
@@ -138,47 +126,13 @@ namespace examples
/// <returns>The feature object at the point Note that an empty name indicates no feature.</returns>
private Feature CheckFeature(Point location)
{
- foreach (var feature in features)
+ var result = features.FirstOrDefault((feature) => feature.Location.Equals(location));
+ if (result == null)
{
- if (feature.Location.Latitude == location.Latitude
- && feature.Location.Longitude == location.Longitude)
- {
- return feature;
- }
+ // No feature was found, return an unnamed feature.
+ return new Feature { Name = "", Location = location };
}
-
- // No feature was found, return an unnamed feature.
- return Feature.CreateBuilder().SetName("").SetLocation(location).Build();
- }
-
- /// <summary>
- /// Calculate the distance between two points using the "haversine" formula.
- /// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
- /// </summary>
- /// <param name="start">the starting point</param>
- /// <param name="end">the end point</param>
- /// <returns>the distance between the points in meters</returns>
- private static double CalcDistance(Point start, Point end)
- {
- double lat1 = RouteGuideUtil.GetLatitude(start);
- double lat2 = RouteGuideUtil.GetLatitude(end);
- double lon1 = RouteGuideUtil.GetLongitude(start);
- double lon2 = RouteGuideUtil.GetLongitude(end);
- int r = 6371000; // metres
- double φ1 = ToRadians(lat1);
- double φ2 = ToRadians(lat2);
- double Δφ = ToRadians(lat2 - lat1);
- double Δλ = ToRadians(lon2 - lon1);
-
- double a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) + Math.Cos(φ1) * Math.Cos(φ2) * Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2);
- double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
-
- return r * c;
- }
-
- private static double ToRadians(double val)
- {
- return (Math.PI / 180) * val;
+ return result;
}
}
}