blob: 1e7065608181082028a26204c4585fc6c6fbaf08 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <signal.h>
#include <cstdlib>
#include <iostream>
#include <arrow/api.h>
#include <arrow/flight/api.h>
#include <gflags/gflags.h>
#include <grpc++/grpc++.h>
#include "examples/arrow/helloworld.grpc.pb.h"
#include "examples/arrow/helloworld.pb.h"
// Demonstrate registering a gRPC service alongside a Flight service
//
// The gRPC service can be accessed with a gRPC client, on the same
// port as the Flight service. Additionally, the CMake config for this
// example links against the gRPC reflection library, enabling tools
// like grpc_cli and grpcurl to list and call RPCs on the server
// without needing local copies of the Protobuf definitions.
// For example, with grpcurl (https://github.com/fullstorydev/grpcurl):
//
// grpcurl -d '{"name": "Rakka"}' -plaintext localhost:31337 HelloWorldService/SayHello
//
// Note that for applications that wish to follow the example here,
// care must be taken to ensure that Protobuf and gRPC are not
// multiply linked, else the resulting program may crash or silently
// corrupt data. In particular:
//
// * If dynamically linking Arrow Flight, then your application and
// Arrow Flight must also dynamically link Protobuf and gRPC. (The
// same goes for static linking.)
// * The Flight packages on some platforms may make this difficult,
// because the Flight dynamic library will itself have statically
// linked Protobuf and gRPC since the platform does not ship a
// recent enough version of those dependencies.
// * The versions of Protobuf and gRPC must be the same between Flight
// and your application.
//
// See "Using Arrow C++ in your own project" in the documentation.
DEFINE_int32(port, -1, "Server port to listen on");
namespace flight = ::arrow::flight;
// Flight service
class SimpleFlightServer : public flight::FlightServerBase {};
// gRPC service
class HelloWorldServiceImpl : public HelloWorldService::Service {
grpc::Status SayHello(grpc::ServerContext* ctx, const HelloRequest* request,
HelloResponse* reply) override {
const std::string& name = request->name();
if (name.empty()) {
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Must provide a name!");
}
reply->set_reply("Hello, " + name);
return grpc::Status::OK;
}
};
arrow::Status RunFlightGrpc() {
std::unique_ptr<flight::FlightServerBase> server;
server.reset(new SimpleFlightServer());
flight::Location bind_location;
ARROW_RETURN_NOT_OK(
flight::Location::ForGrpcTcp("0.0.0.0", FLAGS_port).Value(&bind_location));
flight::FlightServerOptions options(bind_location);
HelloWorldServiceImpl grpc_service;
int extra_port = 0;
options.builder_hook = [&](void* raw_builder) {
auto* builder = reinterpret_cast<grpc::ServerBuilder*>(raw_builder);
builder->AddListeningPort("0.0.0.0:0", grpc::InsecureServerCredentials(),
&extra_port);
builder->RegisterService(&grpc_service);
};
ARROW_RETURN_NOT_OK(server->Init(options));
std::cout << "Listening on ports " << FLAGS_port << " and " << extra_port << std::endl;
ARROW_RETURN_NOT_OK(server->SetShutdownOnSignals({SIGTERM}));
ARROW_RETURN_NOT_OK(server->Serve());
return arrow::Status::OK();
}
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_port < 0) {
// For CI
std::cout << "Must specify a port with -port" << std::endl;
return EXIT_SUCCESS;
}
auto status = RunFlightGrpc();
if (!status.ok()) {
std::cerr << status.ToString() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}