route_guide_callback_server.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2021 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <algorithm>
20 #include <chrono>
21 #include <cmath>
22 #include <iostream>
23 #include <memory>
24 #include <string>
25 #include <thread>
26 
27 #include "helper.h"
28 
29 #include <grpc/grpc.h>
31 #include <grpcpp/server.h>
32 #include <grpcpp/server_builder.h>
33 #include <grpcpp/server_context.h>
34 #ifdef BAZEL_BUILD
35 #include "examples/protos/route_guide.grpc.pb.h"
36 #else
37 #include "route_guide.grpc.pb.h"
38 #endif
39 
41 using grpc::Server;
43 using grpc::Status;
45 using routeguide::Point;
47 using routeguide::RouteGuide;
50 using std::chrono::system_clock;
51 
52 float ConvertToRadians(float num) { return num * 3.1415926 / 180; }
53 
54 // The formula is based on http://mathforum.org/library/drmath/view/51879.html
55 float GetDistance(const Point& start, const Point& end) {
56  const float kCoordFactor = 10000000.0;
57  float lat_1 = start.latitude() / kCoordFactor;
58  float lat_2 = end.latitude() / kCoordFactor;
59  float lon_1 = start.longitude() / kCoordFactor;
60  float lon_2 = end.longitude() / kCoordFactor;
61  float lat_rad_1 = ConvertToRadians(lat_1);
62  float lat_rad_2 = ConvertToRadians(lat_2);
63  float delta_lat_rad = ConvertToRadians(lat_2 - lat_1);
64  float delta_lon_rad = ConvertToRadians(lon_2 - lon_1);
65 
66  float a = pow(sin(delta_lat_rad / 2), 2) +
67  cos(lat_rad_1) * cos(lat_rad_2) * pow(sin(delta_lon_rad / 2), 2);
68  float c = 2 * atan2(sqrt(a), sqrt(1 - a));
69  int R = 6371000; // metres
70 
71  return R * c;
72 }
73 
75  const std::vector<Feature>& feature_list) {
76  for (const Feature& f : feature_list) {
77  if (f.location().latitude() == point.latitude() &&
78  f.location().longitude() == point.longitude()) {
79  return f.name();
80  }
81  }
82  return "";
83 }
84 
85 class RouteGuideImpl final : public RouteGuide::CallbackService {
86  public:
87  explicit RouteGuideImpl(const std::string& db) {
89  }
90 
92  const Point* point,
93  Feature* feature) override {
94  feature->set_name(GetFeatureName(*point, feature_list_));
95  feature->mutable_location()->CopyFrom(*point);
96  auto* reactor = context->DefaultReactor();
97  reactor->Finish(Status::OK);
98  return reactor;
99  }
100 
103  const routeguide::Rectangle* rectangle) override {
104  class Lister : public grpc::ServerWriteReactor<Feature> {
105  public:
106  Lister(const routeguide::Rectangle* rectangle,
107  const std::vector<Feature>* feature_list)
108  : left_((std::min)(rectangle->lo().longitude(),
109  rectangle->hi().longitude())),
110  right_((std::max)(rectangle->lo().longitude(),
111  rectangle->hi().longitude())),
112  top_((std::max)(rectangle->lo().latitude(),
113  rectangle->hi().latitude())),
114  bottom_((std::min)(rectangle->lo().latitude(),
115  rectangle->hi().latitude())),
116  feature_list_(feature_list),
117  next_feature_(feature_list_->begin()) {
118  NextWrite();
119  }
120  void OnDone() override { delete this; }
121  void OnWriteDone(bool /*ok*/) override { NextWrite(); }
122 
123  private:
124  void NextWrite() {
125  while (next_feature_ != feature_list_->end()) {
126  const Feature& f = *next_feature_;
127  next_feature_++;
128  if (f.location().longitude() >= left_ &&
129  f.location().longitude() <= right_ &&
130  f.location().latitude() >= bottom_ &&
131  f.location().latitude() <= top_) {
132  StartWrite(&f);
133  return;
134  }
135  }
136  // Didn't write anything, all is done.
138  }
139  const long left_;
140  const long right_;
141  const long top_;
142  const long bottom_;
143  const std::vector<Feature>* feature_list_;
144  std::vector<Feature>::const_iterator next_feature_;
145  };
146  return new Lister(rectangle, &feature_list_);
147  }
148 
150  RouteSummary* summary) override {
151  class Recorder : public grpc::ServerReadReactor<Point> {
152  public:
153  Recorder(RouteSummary* summary, const std::vector<Feature>* feature_list)
155  summary_(summary),
156  feature_list_(feature_list) {
157  StartRead(&point_);
158  }
159  void OnDone() { delete this; }
160  void OnReadDone(bool ok) {
161  if (ok) {
162  point_count_++;
163  if (!GetFeatureName(point_, *feature_list_).empty()) {
164  feature_count_++;
165  }
166  if (point_count_ != 1) {
167  distance_ += GetDistance(previous_, point_);
168  }
169  previous_ = point_;
170  StartRead(&point_);
171  } else {
172  summary_->set_point_count(point_count_);
173  summary_->set_feature_count(feature_count_);
174  summary_->set_distance(static_cast<long>(distance_));
175  auto secs = std::chrono::duration_cast<std::chrono::seconds>(
177  summary_->set_elapsed_time(secs.count());
179  }
180  }
181 
182  private:
184  RouteSummary* summary_;
185  const std::vector<Feature>* feature_list_;
186  Point point_;
187  int point_count_ = 0;
188  int feature_count_ = 0;
189  float distance_ = 0.0;
190  Point previous_;
191  };
192  return new Recorder(summary, &feature_list_);
193  }
194 
196  CallbackServerContext* context) override {
197  class Chatter : public grpc::ServerBidiReactor<RouteNote, RouteNote> {
198  public:
199  Chatter(absl::Mutex* mu, std::vector<RouteNote>* received_notes)
200  : mu_(mu), received_notes_(received_notes) {
201  StartRead(&note_);
202  }
203  void OnDone() override { delete this; }
204  void OnReadDone(bool ok) override {
205  if (ok) {
206  // Unlike the other example in this directory that's not using
207  // the reactor pattern, we can't grab a local lock to secure the
208  // access to the notes vector, because the reactor will most likely
209  // make us jump threads, so we'll have to use a different locking
210  // strategy. We'll grab the lock locally to build a copy of the
211  // list of nodes we're going to send, then we'll grab the lock
212  // again to append the received note to the existing vector.
213  mu_->Lock();
214  std::copy_if(received_notes_->begin(), received_notes_->end(),
215  std::back_inserter(to_send_notes_),
216  [this](const RouteNote& note) {
217  return note.location().latitude() ==
218  note_.location().latitude() &&
219  note.location().longitude() ==
220  note_.location().longitude();
221  });
222  mu_->Unlock();
223  notes_iterator_ = to_send_notes_.begin();
224  NextWrite();
225  } else {
227  }
228  }
229  void OnWriteDone(bool /*ok*/) override { NextWrite(); }
230 
231  private:
232  void NextWrite() {
233  if (notes_iterator_ != to_send_notes_.end()) {
234  StartWrite(&*notes_iterator_);
235  notes_iterator_++;
236  } else {
237  mu_->Lock();
238  received_notes_->push_back(note_);
239  mu_->Unlock();
240  StartRead(&note_);
241  }
242  }
243  RouteNote note_;
244  absl::Mutex* mu_;
245  std::vector<RouteNote>* received_notes_;
246  std::vector<RouteNote> to_send_notes_;
247  std::vector<RouteNote>::iterator notes_iterator_;
248  };
249  return new Chatter(&mu_, &received_notes_);
250  }
251 
252  private:
253  std::vector<Feature> feature_list_;
255  std::vector<RouteNote> received_notes_ ABSL_GUARDED_BY(mu_);
256 };
257 
258 void RunServer(const std::string& db_path) {
259  std::string server_address("0.0.0.0:50051");
260  RouteGuideImpl service(db_path);
261 
264  builder.RegisterService(&service);
265  std::unique_ptr<Server> server(builder.BuildAndStart());
266  std::cout << "Server listening on " << server_address << std::endl;
267  server->Wait();
268 }
269 
270 int main(int argc, char** argv) {
271  // Expect only arg: --db_path=path/to/route_guide_db.json.
272  std::string db = routeguide::GetDbFileContent(argc, argv);
273  RunServer(db);
274 
275  return 0;
276 }
now
static double now(void)
Definition: test/core/fling/client.cc:130
RouteGuideImpl::RouteGuideImpl
RouteGuideImpl(const std::string &db)
Definition: route_guide_callback_server.cc:87
grpc::ServerReadReactor
ServerReadReactor is the interface for a client-streaming RPC.
Definition: impl/codegen/server_callback.h:184
RouteGuideImpl::GetFeature
grpc::ServerUnaryReactor * GetFeature(CallbackServerContext *context, const Point *point, Feature *feature) override
Definition: route_guide_callback_server.cc:91
RouteGuideImpl::ABSL_GUARDED_BY
std::vector< RouteNote > received_notes_ ABSL_GUARDED_BY(mu_)
absl::time_internal::cctz::time_point
std::chrono::time_point< std::chrono::system_clock, D > time_point
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h:39
GetDistance
float GetDistance(const Point &start, const Point &end)
Definition: route_guide_callback_server.cc:55
absl::Mutex
Definition: abseil-cpp/absl/synchronization/mutex.h:131
RunServer
void RunServer(const std::string &db_path)
Definition: route_guide_callback_server.cc:258
absl::Mutex::Unlock
void Unlock() ABSL_UNLOCK_FUNCTION()
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
framework.rpc.grpc_channelz.Server
Server
Definition: grpc_channelz.py:42
OK
@ OK
Definition: cronet_status.h:43
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
ConvertToRadians
float ConvertToRadians(float num)
Definition: route_guide_callback_server.cc:52
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
grpc::ServerBidiReactor
ServerBidiReactor is the interface for a bidirectional streaming RPC.
Definition: impl/codegen/server_callback.h:188
RouteGuideImpl::received_notes_
std::vector< RouteNote > received_notes_
Definition: route_guide_server.cc:169
server_address
std::string server_address("0.0.0.0:10000")
routeguide::GetDbFileContent
std::string GetDbFileContent(int argc, char **argv)
Definition: helper.cc:34
RouteGuideImpl::mu_
absl::Mutex mu_
Definition: route_guide_callback_server.cc:254
routeguide::ParseDb
void ParseDb(const std::string &db, std::vector< Feature > *feature_list)
Definition: helper.cc:143
route_guide_pb2.RouteSummary
RouteSummary
Definition: multiplex/route_guide_pb2.py:270
route_guide_pb2.Point
Point
Definition: multiplex/route_guide_pb2.py:242
server
std::unique_ptr< Server > server
Definition: channelz_service_test.cc:330
start_time_
Timestamp start_time_
Definition: outlier_detection.cc:379
start
static uint64_t start
Definition: benchmark-pound.c:74
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
profile_analyzer.builder
builder
Definition: profile_analyzer.py:159
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
RouteGuideImpl::feature_list_
std::vector< Feature > feature_list_
Definition: route_guide_callback_server.cc:253
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
grpc::ServerBuilder
A builder class for the creation and startup of grpc::Server instances.
Definition: grpcpp/server_builder.h:86
mu
Mutex mu
Definition: server_config_selector_filter.cc:74
tests._result.summary
def summary(result)
Definition: _result.py:346
RouteGuideImpl
Definition: route_guide_callback_server.cc:85
absl::Mutex::Lock
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION()
GetFeatureName
std::string GetFeatureName(const Point &point, const std::vector< Feature > &feature_list)
Definition: route_guide_callback_server.cc:74
grpc.h
main
int main(int argc, char **argv)
Definition: route_guide_callback_server.cc:270
left_
bool left_
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:309
min
#define min(a, b)
Definition: qsort.h:83
grpc::CallbackServerContext
Definition: grpcpp/impl/codegen/server_context.h:606
server_credentials.h
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
point
Definition: bloaty/third_party/zlib/examples/zran.c:67
RouteGuideImpl::RecordRoute
grpc::ServerReadReactor< Point > * RecordRoute(CallbackServerContext *context, RouteSummary *summary) override
Definition: route_guide_callback_server.cc:149
RouteGuideImpl::RouteChat
grpc::ServerBidiReactor< RouteNote, RouteNote > * RouteChat(CallbackServerContext *context) override
Definition: route_guide_callback_server.cc:195
server
Definition: examples/python/async_streaming/server.py:1
benchmark::internal::Finish
double Finish(Counter const &c, IterationCount iterations, double cpu_time, double num_threads)
Definition: benchmark/src/counter.cc:20
bm_diff.note
note
Definition: bm_diff.py:274
route_guide_pb2.Rectangle
Rectangle
Definition: multiplex/route_guide_pb2.py:249
helper.h
server_context.h
grpc::protobuf::util::Status
GRPC_CUSTOM_UTIL_STATUS Status
Definition: include/grpcpp/impl/codegen/config_protobuf.h:93
xds_manager.num
num
Definition: xds_manager.py:56
RouteGuideImpl::ListFeatures
grpc::ServerWriteReactor< Feature > * ListFeatures(CallbackServerContext *context, const routeguide::Rectangle *rectangle) override
Definition: route_guide_callback_server.cc:101
ok
bool ok
Definition: async_end2end_test.cc:197
grpc::ServerUnaryReactor
Definition: impl/codegen/server_callback.h:699
grpc::InsecureServerCredentials
std::shared_ptr< ServerCredentials > InsecureServerCredentials()
Definition: insecure_server_credentials.cc:52
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
server.h
service
__attribute__((deprecated("Please use GRPCProtoMethod."))) @interface ProtoMethod NSString * service
Definition: ProtoMethod.h:25
grpc::ServerWriteReactor
ServerWriteReactor is the interface for a server-streaming RPC.
Definition: impl/codegen/server_callback.h:186
server_builder.h
route_guide_pb2.Feature
Feature
Definition: multiplex/route_guide_pb2.py:256
route_guide_pb2.RouteNote
RouteNote
Definition: multiplex/route_guide_pb2.py:263


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:12