You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2022/02/25 00:03:43 UTC

[arrow-cookbook] branch main updated: [C++] gRPC settings and custom endpoint examples (#153)

This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-cookbook.git


The following commit(s) were added to refs/heads/main by this push:
     new 5a90a74  [C++] gRPC settings and custom endpoint examples (#153)
5a90a74 is described below

commit 5a90a74633e2ac0477a22ac7e0d6384bbd60b60e
Author: Will Jones <wi...@gmail.com>
AuthorDate: Thu Feb 24 16:03:36 2022 -0800

    [C++] gRPC settings and custom endpoint examples (#153)
    
    * Draft options example
    
    * Get flight examples to compile
    
    * Start creating client for gRPC custom service
    
    * Fix test
    
    * Cleanup
    
    * PR feedback
    
    * Further cleanup
    
    * Remove references to other ports
---
 cpp/code/CMakeLists.txt          |  23 ++++++++
 cpp/code/flight.cc               | 113 +++++++++++++++++++++++++++++++++++++--
 cpp/code/protos/helloworld.proto |  30 +++++++++++
 cpp/conda-linux-64.lock          |  39 +++++++-------
 cpp/conda-linux-aarch64.lock     |  39 +++++++-------
 cpp/conda-osx-arm64.lock         |  48 +++++++++--------
 cpp/environment.yml              |   1 +
 cpp/source/flight.rst            |  68 +++++++++++++++++++++++
 8 files changed, 298 insertions(+), 63 deletions(-)

diff --git a/cpp/code/CMakeLists.txt b/cpp/code/CMakeLists.txt
index f215d91..5b8f4b5 100644
--- a/cpp/code/CMakeLists.txt
+++ b/cpp/code/CMakeLists.txt
@@ -46,3 +46,26 @@ recipe(basic_arrow)
 recipe(creating_arrow_objects)
 recipe(datasets)
 recipe(flight)
+
+
+# Add protobuf to flight
+find_package(Protobuf REQUIRED)
+find_package(gRPC CONFIG REQUIRED)
+find_package(Threads)
+
+set(PROTO_FILES
+    protos/helloworld.proto
+)
+
+target_link_libraries(flight
+    protobuf::libprotobuf
+    gRPC::grpc
+    gRPC::grpc++
+)
+target_include_directories(flight PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
+get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
+protobuf_generate(TARGET flight LANGUAGE cpp PROTOS ${PROTO_FILES})
+protobuf_generate(TARGET flight LANGUAGE grpc 
+                  GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc 
+                  PLUGIN "protoc-gen-grpc=${grpc_cpp_plugin_location}"
+                  PROTOS ${PROTO_FILES})
\ No newline at end of file
diff --git a/cpp/code/flight.cc b/cpp/code/flight.cc
index 52dfef9..8eaabd5 100644
--- a/cpp/code/flight.cc
+++ b/cpp/code/flight.cc
@@ -25,9 +25,13 @@
 #include <arrow/status.h>
 #include <arrow/table.h>
 #include <arrow/type.h>
+#include <gmock/gmock.h>
+#include <grpc++/grpc++.h>
 #include <gtest/gtest.h>
 #include <parquet/arrow/reader.h>
 #include <parquet/arrow/writer.h>
+#include <protos/helloworld.grpc.pb.h>
+#include <protos/helloworld.pb.h>
 
 #include <algorithm>
 #include <memory>
@@ -43,9 +47,9 @@ class ParquetStorageService : public arrow::flight::FlightServerBase {
   explicit ParquetStorageService(std::shared_ptr<arrow::fs::FileSystem> root)
       : root_(std::move(root)) {}
 
-  arrow::Status ListFlights(const arrow::flight::ServerCallContext&,
-                            const arrow::flight::Criteria*,
-                            std::unique_ptr<arrow::flight::FlightListing>* listings) override {
+  arrow::Status ListFlights(
+      const arrow::flight::ServerCallContext&, const arrow::flight::Criteria*,
+      std::unique_ptr<arrow::flight::FlightListing>* listings) override {
     arrow::fs::FileSelector selector;
     selector.base_dir = "/";
     ARROW_ASSIGN_OR_RAISE(auto listing, root_->GetFileInfo(selector));
@@ -173,6 +177,18 @@ class ParquetStorageService : public arrow::flight::FlightServerBase {
   std::shared_ptr<arrow::fs::FileSystem> root_;
 };  // end ParquetStorageService
 
+class HelloWorldServiceImpl : public HelloWorldService::Service {
+  grpc::Status SayHello(grpc::ServerContext*, 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;
+  }
+};  // end HelloWorldServiceImpl
+
 arrow::Status TestPutGetDelete() {
   StartRecipe("ParquetStorageService::StartServer");
   auto fs = std::make_shared<arrow::fs::LocalFileSystem>();
@@ -291,4 +307,95 @@ arrow::Status TestPutGetDelete() {
   return arrow::Status::OK();
 }
 
+arrow::Status TestClientOptions() {
+  // Set up server as usual
+  auto fs = std::make_shared<arrow::fs::LocalFileSystem>();
+  ARROW_RETURN_NOT_OK(fs->CreateDir("./flight_datasets/"));
+  ARROW_RETURN_NOT_OK(fs->DeleteDirContents("./flight_datasets/"));
+  auto root = std::make_shared<arrow::fs::SubTreeFileSystem>("./flight_datasets/", fs);
+
+  arrow::flight::Location server_location;
+  ARROW_RETURN_NOT_OK(
+      arrow::flight::Location::ForGrpcTcp("0.0.0.0", 0, &server_location));
+
+  arrow::flight::FlightServerOptions options(server_location);
+  auto server = std::unique_ptr<arrow::flight::FlightServerBase>(
+      new ParquetStorageService(std::move(root)));
+  ARROW_RETURN_NOT_OK(server->Init(options));
+
+  StartRecipe("TestClientOptions::Connect");
+  auto client_options = arrow::flight::FlightClientOptions::Defaults();
+  // Set a very low limit at the gRPC layer to fail all calls
+  client_options.generic_options.emplace_back(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, 2);
+
+  arrow::flight::Location location;
+  ARROW_RETURN_NOT_OK(
+      arrow::flight::Location::ForGrpcTcp("localhost", server->port(), &location));
+
+  std::unique_ptr<arrow::flight::FlightClient> client;
+  ARROW_RETURN_NOT_OK(  // pass client_options into Connect()
+      arrow::flight::FlightClient::Connect(location, client_options, &client));
+  rout << "Connected to " << location.ToString() << std::endl;
+  EndRecipe("TestClientOptions::Connect");
+
+  auto descriptor = arrow::flight::FlightDescriptor::Path({"airquality.parquet"});
+  std::unique_ptr<arrow::flight::FlightInfo> flight_info;
+  return client->GetFlightInfo(descriptor, &flight_info);
+}
+
+arrow::Status TestCustomGrpcImpl() {
+  // Build flight service as usual
+  auto fs = std::make_shared<arrow::fs::LocalFileSystem>();
+  ARROW_RETURN_NOT_OK(fs->CreateDir("./flight_datasets/"));
+  ARROW_RETURN_NOT_OK(fs->DeleteDirContents("./flight_datasets/"));
+  auto root = std::make_shared<arrow::fs::SubTreeFileSystem>("./flight_datasets/", fs);
+
+  StartRecipe("CustomGrpcImpl::StartServer");
+  arrow::flight::Location server_location;
+  ARROW_RETURN_NOT_OK(
+      arrow::flight::Location::ForGrpcTcp("0.0.0.0", 5000, &server_location));
+
+  arrow::flight::FlightServerOptions options(server_location);
+  auto server = std::unique_ptr<arrow::flight::FlightServerBase>(
+      new ParquetStorageService(std::move(root)));
+
+  // Create hello world service
+  HelloWorldServiceImpl grpc_service;
+
+  // Use builder_hook to register grpc service
+  options.builder_hook = [&](void* raw_builder) {
+    auto* builder = reinterpret_cast<grpc::ServerBuilder*>(raw_builder);
+    builder->RegisterService(&grpc_service);
+  };
+
+  ARROW_RETURN_NOT_OK(server->Init(options));
+  rout << "Listening on port " << server->port() << std::endl;
+  EndRecipe("CustomGrpcImpl::StartServer");
+
+  StartRecipe("CustomGrpcImpl::CreateClient");
+  auto client_channel =
+      grpc::CreateChannel("0.0.0.0:5000", grpc::InsecureChannelCredentials());
+
+  auto stub = HelloWorldService::NewStub(client_channel);
+
+  grpc::ClientContext context;
+  HelloRequest request;
+  request.set_name("Arrow User");
+  HelloResponse response;
+  grpc::Status status = stub->SayHello(&context, request, &response);
+  if (!status.ok()) {
+    return arrow::Status::IOError(status.error_message());
+  }
+  rout << response.reply();
+
+  EndRecipe("CustomGrpcImpl::CreateClient");
+  return arrow::Status::OK();
+}
+
 TEST(ParquetStorageServiceTest, PutGetDelete) { ASSERT_OK(TestPutGetDelete()); }
+TEST(ParquetStorageServiceTest, TestClientOptions) {
+  auto status = TestClientOptions();
+  ASSERT_EQ(status.code(), arrow::StatusCode::Invalid);
+  ASSERT_THAT(status.message(), testing::HasSubstr("resource exhausted"));
+}
+TEST(ParquetStorageServiceTest, TestCustomGrpcImpl) { ASSERT_OK(TestCustomGrpcImpl()); }
\ No newline at end of file
diff --git a/cpp/code/protos/helloworld.proto b/cpp/code/protos/helloworld.proto
new file mode 100644
index 0000000..599f88b
--- /dev/null
+++ b/cpp/code/protos/helloworld.proto
@@ -0,0 +1,30 @@
+// 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.
+
+syntax = "proto3";
+
+service HelloWorldService {
+  rpc SayHello(HelloRequest) returns (HelloResponse);
+}
+
+message HelloRequest {
+  string name = 1;
+}
+
+message HelloResponse {
+  string reply = 1;
+}
\ No newline at end of file
diff --git a/cpp/conda-linux-64.lock b/cpp/conda-linux-64.lock
index 002129e..acd8d7e 100644
--- a/cpp/conda-linux-64.lock
+++ b/cpp/conda-linux-64.lock
@@ -1,14 +1,14 @@
 # Generated by conda-lock.
 # platform: linux-64
-# input_hash: 55c56b4ebbc5dd9b4cba1e832f00a159d9839ca31c100704c4d58ef54bea2479
+# input_hash: 961d5bf5a1d8489cdc3d6b85eae93769c022e5ba6abebe1f3afbb9e9051a78f5
 @EXPLICIT
 https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
 https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2021.10.8-ha878542_0.tar.bz2#575611b8a84f45960e87722eeb51fa26
 https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_15.tar.bz2#5dd5127afd710f91f6a75821bac0a4f0
 https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.36.1-hea4e1c9_2.tar.bz2#bd4f2e711b39af170e7ff15163fe87ee
-https://conda.anaconda.org/conda-forge/linux-64/libgcc-devel_linux-64-9.4.0-hd854feb_12.tar.bz2#8b51f462cec80cc9e47e28fd97cc83af
+https://conda.anaconda.org/conda-forge/linux-64/libgcc-devel_linux-64-10.3.0-he6cfe16_12.tar.bz2#931483f6dd8ea66149dc7c72bbd10c85
 https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-11.2.0-h5c6108e_12.tar.bz2#f547bf125ab234cec9c89491b262fc2f
-https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-devel_linux-64-9.4.0-hd854feb_12.tar.bz2#a8a1259e65e005afc1bfd1a8f0b50ae0
+https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-devel_linux-64-10.3.0-he6cfe16_12.tar.bz2#0d615dbcbac0b4f169f28d3b940677f0
 https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-11.2.0-he4da1e4_12.tar.bz2#7ff3b832ba5e6918c0d026976359d065
 https://conda.anaconda.org/conda-forge/noarch/tzdata-2021e-he74cb21_0.tar.bz2#a751ec502589ebdc2eceb183ff602569
 https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-11.2.0-h69a702a_12.tar.bz2#33c165be455015cc74e8d857182f3f58
@@ -31,7 +31,7 @@ https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h516909a_1.tar.bz2#6f
 https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2#d645c6d2ac96843a2bfaccd2d62b3ac3
 https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.0-h7f98852_0.tar.bz2#39b1328babf85c7c3a61636d9cd50206
 https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.18-pthreads_h8fe5266_0.tar.bz2#41532e4448c0cce086d6570f95e4e12e
-https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-9.4.0-h79bfe98_12.tar.bz2#13eb8f99569047baff01edfb8120c35e
+https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-10.3.0-h26c7422_12.tar.bz2#387f3b7d600827f48325b5340c023884
 https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.7.0-h7f98852_0.tar.bz2#913570ed14b42cf48ccbba364af20302
 https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.32.1-h7f98852_1000.tar.bz2#772d69f030955d9646d3d0eaf21d859d
 https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.11-h36c2ea0_1013.tar.bz2#dcddf696ff5dfcab567100d691678e18
@@ -43,41 +43,42 @@ https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.8-he1b5a44_3.tar.bz2#
 https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.5-h516909a_1.tar.bz2#33f601066901f3e1a85af3522a8113f9
 https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.5.11-h95a6274_0.tar.bz2#d4e7b241fb22dd3d7be1171f813d5da3
 https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.11-ha31a3da_7.tar.bz2#2fdb96aaab883abc0766ff76c0a34483
-https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-9.4.0-h03d3576_12.tar.bz2#dd24912b641140dc74c0bfb2033f9b1b
+https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-10.3.0-hf2f2afa_12.tar.bz2#8385babc4fbc1f40df0eaa23cbbb7c2b
 https://conda.anaconda.org/conda-forge/linux-64/glog-0.5.0-h48cff8f_0.tar.bz2#a574d6262c2f18ed60a686e1014a6700
+https://conda.anaconda.org/conda-forge/linux-64/gmock-1.10.0-h4bd325d_7.tar.bz2#b304c28df09bea056c584e441ff6204d
 https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-13_linux64_openblas.tar.bz2#8a4038563ed92dfa622bd72c0d8f31d3
 https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.0.9-h7f98852_6.tar.bz2#c7c03a2592cac92246a13a0732bd1573
 https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.0.9-h7f98852_6.tar.bz2#28bfe0a70154e6881da7bae97517c948
 https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2#4d331e44109e3f0e19b4cb8f9b82f3e1
 https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.10-h9b69904_4.tar.bz2#390026683aef81db27ff1b8570ca1336
-https://conda.anaconda.org/conda-forge/linux-64/libllvm13-13.0.1-hf817b99_0.tar.bz2#8fd6f0628d54935a4620b8dcbf300ee3
+https://conda.anaconda.org/conda-forge/linux-64/libllvm13-13.0.1-hf817b99_2.tar.bz2#47da3ce0d8b2e65ccb226c186dd91eba
 https://conda.anaconda.org/conda-forge/linux-64/readline-8.1-h46c0cb4_0.tar.bz2#5788de3c8d7a7d64ac56c784c4ef48e6
 https://conda.anaconda.org/conda-forge/linux-64/s2n-1.0.10-h9b69904_0.tar.bz2#9708c3ac26c20b4c4549cbe8fef937eb
 https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.12-h27826a3_0.tar.bz2#5b8c42eb62e9fc961af70bdd6a26e168
 https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.11-h36c2ea0_1013.tar.bz2#cf7190238072a41e9579e4476a6a60b8
 https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.2-ha95c52a_0.tar.bz2#5222b231b1ef49a7f60d40b363469b70
 https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.10.5-hfb6a706_0.tar.bz2#47d6b88b0c42a8c9877f3993b49f052d
-https://conda.anaconda.org/conda-forge/linux-64/gcc-9.4.0-h192d537_5.tar.bz2#2dca31fb79229558405ad02f3328ce18
-https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-9.4.0-h391b98a_5.tar.bz2#00cc202c08737df3143486b5e5cb5f46
-https://conda.anaconda.org/conda-forge/linux-64/gfortran_impl_linux-64-9.4.0-h0003116_12.tar.bz2#a90ea60020bf8976f156330af5030131
-https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-9.4.0-h03d3576_12.tar.bz2#b8402eb94d27526e767033c75d4f5858
+https://conda.anaconda.org/conda-forge/linux-64/gcc-10.3.0-he2824d0_5.tar.bz2#ee3efe0f6c88121e41d736c88b62f3b0
+https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-10.3.0-hc39de41_5.tar.bz2#1648574f1cdb73682ca896bc61ac1da5
+https://conda.anaconda.org/conda-forge/linux-64/gfortran_impl_linux-64-10.3.0-h73f4979_12.tar.bz2#75c09511f51777bc97c50396e2f39ccb
+https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-10.3.0-hf2f2afa_12.tar.bz2#9d18064a9989218984d628f2295afa63
 https://conda.anaconda.org/conda-forge/linux-64/krb5-1.19.2-hcc1bbae_3.tar.bz2#e29650992ae593bc05fc93722483e5c3
 https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-13_linux64_openblas.tar.bz2#b17676dbd6688396c3a3076259fb7907
 https://conda.anaconda.org/conda-forge/linux-64/libclang-13.0.1-default_hc23dcda_0.tar.bz2#8cebb0736cba83485b13dc10d242d96d
 https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp13-13.0.1-default_hc23dcda_0.tar.bz2#f492332e48fb4f5e44bd20c133517d1a
 https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-13_linux64_openblas.tar.bz2#018b80e8f21d8560ae4961567e3e00c9
-https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.46.0-h812cca2_0.tar.bz2#507fa47e9075f889af8e8b72925379be
+https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.47.0-h727a467_0.tar.bz2#a22567abfea169ff8048506b1ca9b230
 https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-3.19.4-h780b84a_0.tar.bz2#9ff9ab8cc887d4bdebc7c7dba641626f
 https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.10.0-ha56f1ee_2.tar.bz2#6ab4eaa11ff01801cffca0a27489dc04
 https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.15.0-he6d91bd_1.tar.bz2#97155bdbbd9a42d278981c1f958e06c0
 https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.37.0-h9cd32fc_0.tar.bz2#eb66fc098824d25518a79e83d12a81d6
 https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.2.7-h3541f99_13.tar.bz2#39768ba0fe69c241d54703a7f5e3119f
-https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.3.0-h7f98852_0.tar.bz2#543ebd7ec7822fc5fb0284adfa3ba284
+https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.4.0-h166bdaf_0.tar.bz2#05b7989baf353f269e62495bc2785de3
 https://conda.anaconda.org/conda-forge/linux-64/clang-format-13-13.0.1-default_hc23dcda_0.tar.bz2#32f4adc0ffa64442ab7c1b863ef8f8ed
-https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-9.4.0-hf0ab688_5.tar.bz2#4ffed95ab167d1303bcd446f711fc6e5
+https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-10.3.0-hb09a455_5.tar.bz2#20e5b5e332b55df21e48646d65e44c85
 https://conda.anaconda.org/conda-forge/linux-64/grpc-cpp-1.43.2-h9e046d8_1.tar.bz2#d9687ebeaec84b63d1bcbfd079ebe61e
-https://conda.anaconda.org/conda-forge/linux-64/gxx-9.4.0-h192d537_5.tar.bz2#024aec65604a948cfca58d2350b43b25
-https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-9.4.0-h0316aca_5.tar.bz2#e488f85749d675e5c6e4c3dbf56aa812
+https://conda.anaconda.org/conda-forge/linux-64/gxx-10.3.0-he2824d0_5.tar.bz2#f45fbbb3465c526549531ba185a3c33a
+https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-10.3.0-h2593f52_5.tar.bz2#4fedd073f7a192cb31d8534156064c39
 https://conda.anaconda.org/conda-forge/linux-64/libcurl-7.81.0-h2574ce0_0.tar.bz2#1f8655741d0269ca6756f131522da1e8
 https://conda.anaconda.org/conda-forge/linux-64/orc-1.7.3-h1be678f_0.tar.bz2#390f40a6ceaa94b3b221599456168856
 https://conda.anaconda.org/conda-forge/linux-64/python-3.9.10-h85951f9_2_cpython.tar.bz2#eb70cef531c241272a35010ea8a4f705
@@ -86,8 +87,8 @@ https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.8.186-hb4091e7_3.t
 https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.0.12-pyhd8ed1ab_0.tar.bz2#1f5b32dabae0f1893ae3283dac7f799e
 https://conda.anaconda.org/conda-forge/linux-64/clang-format-13.0.1-default_hc23dcda_0.tar.bz2#e64b91f6f4c0436a808419ded3f1fcaf
 https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.4-pyh9f0ad1d_0.tar.bz2#c08b4c1326b880ed44f3ffb04803332f
-https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.3.0-h4bd325d_0.tar.bz2#0fbd916fafd28bc73ba5b9855fdfc94d
-https://conda.anaconda.org/conda-forge/linux-64/gfortran-9.4.0-h2018a41_5.tar.bz2#8ae6954630b91454904112139680c51c
+https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.4.0-h924138e_0.tar.bz2#30e1329ef15b9ee293bbd4f082da0d94
+https://conda.anaconda.org/conda-forge/linux-64/gfortran-10.3.0-h18518b4_5.tar.bz2#1bc4924b8e86387d107ec06d4349f8e9
 https://conda.anaconda.org/conda-forge/noarch/idna-3.3-pyhd8ed1ab_0.tar.bz2#40b50b8b030f5f2f22085c062ed013dd
 https://conda.anaconda.org/conda-forge/noarch/imagesize-1.3.0-pyhd8ed1ab_0.tar.bz2#be807e7606fff9436e5e700f6bffb7c6
 https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-1.35.0-h6945097_2.tar.bz2#cd98869ef2ab424c943dcd3e1d8cd354
@@ -107,7 +108,7 @@ https://conda.anaconda.org/conda-forge/linux-64/certifi-2021.10.8-py39hf3d152e_1
 https://conda.anaconda.org/conda-forge/linux-64/cffi-1.15.0-py39h4bc2ebd_0.tar.bz2#f6191bf565dee581e77549d63737751c
 https://conda.anaconda.org/conda-forge/linux-64/clang-tools-13.0.1-default_hc23dcda_0.tar.bz2#d3478b6f39d7413ace3f727fd88167d8
 https://conda.anaconda.org/conda-forge/linux-64/docutils-0.17.1-py39hf3d152e_1.tar.bz2#8c11754f3614fddbb3ab585164829dfc
-https://conda.anaconda.org/conda-forge/linux-64/fortran-compiler-1.3.0-h1990efc_0.tar.bz2#fc19435a9a259c341f8478068036099c
+https://conda.anaconda.org/conda-forge/linux-64/fortran-compiler-1.4.0-h2a4ca65_0.tar.bz2#fc82b1a3534a0c52ae2a9f0eb166dcee
 https://conda.anaconda.org/conda-forge/linux-64/importlib-metadata-4.11.1-py39hf3d152e_0.tar.bz2#2f682cc4885383e56249e2c39137bf35
 https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.0-py39hb9d737c_0.tar.bz2#394ae1759ca48ad0d55282cdd468bfcd
 https://conda.anaconda.org/conda-forge/linux-64/numpy-1.22.2-py39h91f2184_0.tar.bz2#83a015042ad4dd725d59f5d223ec3db9
@@ -116,7 +117,7 @@ https://conda.anaconda.org/conda-forge/linux-64/pysocks-1.7.1-py39hf3d152e_4.tar
 https://conda.anaconda.org/conda-forge/linux-64/setuptools-60.9.3-py39hf3d152e_0.tar.bz2#f7f1f230795c8b18c5439b134a7ac27f
 https://conda.anaconda.org/conda-forge/linux-64/arrow-cpp-7.0.0-py39h6409b3a_2_cpu.tar.bz2#7a13f383222d41abad2922cbbba95db9
 https://conda.anaconda.org/conda-forge/linux-64/brotlipy-0.7.0-py39h3811e60_1003.tar.bz2#9b1975f772d5d8a398c34e539a7ea1a1
-https://conda.anaconda.org/conda-forge/linux-64/compilers-1.3.0-ha770c72_0.tar.bz2#9e0cda2ff85c8fba2ba4fb0046c61764
+https://conda.anaconda.org/conda-forge/linux-64/compilers-1.4.0-ha770c72_0.tar.bz2#4a6f7d4ad81b9e604147891c563742ec
 https://conda.anaconda.org/conda-forge/linux-64/cryptography-36.0.1-py39h95dcef6_0.tar.bz2#986821383dd9622121c1a0b8a745b1e2
 https://conda.anaconda.org/conda-forge/noarch/jinja2-3.0.3-pyhd8ed1ab_0.tar.bz2#036d872c653780cb26e797e2e2f61b4c
 https://conda.anaconda.org/conda-forge/noarch/pygments-2.11.2-pyhd8ed1ab_0.tar.bz2#caef60540e2239e27bf62569a5015e3b
diff --git a/cpp/conda-linux-aarch64.lock b/cpp/conda-linux-aarch64.lock
index 4714b9f..cd1cc35 100644
--- a/cpp/conda-linux-aarch64.lock
+++ b/cpp/conda-linux-aarch64.lock
@@ -1,14 +1,14 @@
 # Generated by conda-lock.
 # platform: linux-aarch64
-# input_hash: 6ecaafc50c6915cab927b2bd9123db76577f77c6fe7eb3a782f202a45f6c5e91
+# input_hash: 53c6212a61e67956fdca12e0e0b7f5fc9473fd004d40fead1ee974a962b1e145
 @EXPLICIT
 https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2021.10.8-h4fd8a4c_0.tar.bz2#ad855209fcca3b45da677d409b16e021
 https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h5b4a56d_13.tar.bz2#a9385e5b11a076c40d75915986f498d7
 https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.36.1-h02ad14f_2.tar.bz2#3ca1a8e406eab04ffc3bfa6e8ac0a724
-https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-devel_linux-aarch64-9.4.0-h85f5abf_12.tar.bz2#ed0c76c111a37ca34b4efad58df3566a
+https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-devel_linux-aarch64-10.3.0-h8e480ec_12.tar.bz2#e6e20265e35405fe831843bc88bd9d64
 https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-11.2.0-h440fb59_12.tar.bz2#74f1d951027bcb7cd09d398fd83c12a2
 https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-11.2.0-hf1cc4e7_12.tar.bz2#a3abd5f12d1924da46051081e51c081b
-https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-devel_linux-aarch64-9.4.0-h85f5abf_12.tar.bz2#88432568e7f59450a4ba285e62f07dd5
+https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-devel_linux-aarch64-10.3.0-h8e480ec_12.tar.bz2#f586d4a36af9efc8b924cddb952bd045
 https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-11.2.0-h0d0a5bb_12.tar.bz2#d70ff7375c4c8932b97779c06cfc4773
 https://conda.anaconda.org/conda-forge/noarch/tzdata-2021e-he74cb21_0.tar.bz2#a751ec502589ebdc2eceb183ff602569
 https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-1_gnu.tar.bz2#d029b13a6c638f91c9db96a991ac56f0
@@ -30,7 +30,7 @@ https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h516909a_1.tar.b
 https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2#dddd85f4d52121fab0a8b099c5e06501
 https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.0-hf897c2e_0.tar.bz2#36fdbc05c9d9145ece86f5a63c3f352e
 https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.18-pthreads_h775ce2d_0.tar.bz2#1ca386fb2a69cad512670e0cf082f2a3
-https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-9.4.0-h4d00405_12.tar.bz2#aa6687d465bcc31442dc1dc6fc31aa0a
+https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-10.3.0-h971684a_12.tar.bz2#37bd5ac683bf248663c6f8d6cc19e7c2
 https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.7.0-hf897c2e_0.tar.bz2#09a036693b8e077ccbb0e4c25af2a16c
 https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.32.1-hf897c2e_1000.tar.bz2#e038da5ef9095b0d79aac14a311394e7
 https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.11-hb9de7d4_1013.tar.bz2#8da01d8d112058433902f24c753f5190
@@ -42,41 +42,42 @@ https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.8-h54f1f3f_3.tar
 https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.5-h6dd45c4_1.tar.bz2#9da6f161d0f47f8a29fa708cda8deda2
 https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.5.11-h76602a3_0.tar.bz2#b4bc77d1e9aafae1961fa14be5999fe5
 https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.11-hafdcbdd_7.tar.bz2#8dd89d70f18be569bbfbf1de40cd6658
-https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-9.4.0-h603953f_12.tar.bz2#835ee5332c38d47402369c5f436c634c
+https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-10.3.0-ha07e0e6_12.tar.bz2#55377ee1f8568144edbb7d2f6ccaa42e
 https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.5.0-hbffda88_0.tar.bz2#939375fff4b51fcf1e3921e6fab165c1
+https://conda.anaconda.org/conda-forge/linux-aarch64/gmock-1.10.0-hd62202e_7.tar.bz2#ec43cd9a5382121f818e36f7d89459f0
 https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-13_linuxaarch64_openblas.tar.bz2#a845b50b554fc280dc012b44889d7f64
 https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.0.9-hf897c2e_6.tar.bz2#f2b0ffe32e64782bcd3db1baacb37625
 https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.0.9-hf897c2e_6.tar.bz2#8c98f807ddd1009083b3a4efd6f827ca
 https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2#29371161d77933a54fccf1bb66b96529
 https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.10-h6aed413_4.tar.bz2#688418283c67fd1d725b07ba9c0d328c
-https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm13-13.0.1-h6293a0b_0.tar.bz2#04a9693b5caf9a3562e5c3aab7b13d68
+https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm13-13.0.1-hb2805f8_2.tar.bz2#a4c151e9903824232085e8b6e70ec83e
 https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.1-h1a49cc3_0.tar.bz2#ccd3c3e1bde615ec934282f3481a1ede
 https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.0.10-h6aed413_0.tar.bz2#a2811501920071cbd542e7d1aac7dcf9
 https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.12-hd8af866_0.tar.bz2#7894e82ff743bd96c76585ddebe28e2a
 https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.11-hb9de7d4_1013.tar.bz2#7528dd959ebfdf9b73e3ffa79356e114
 https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.2-h41fb7a4_0.tar.bz2#03434131cc82915a59513e1ab989fdd5
 https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.10.5-h5a3db43_0.tar.bz2#1d77281aabc9b2202b225cee0bb7300a
-https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-9.4.0-hff40af5_5.tar.bz2#728436f75b8252a3b6c3e9e236d86e75
-https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-9.4.0-h9fa865e_5.tar.bz2#eb1ee40b092af1d672622a413f8913ed
-https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_impl_linux-aarch64-9.4.0-h54cdb55_12.tar.bz2#04cc569424bc1b8643ae193413850149
-https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-9.4.0-h603953f_12.tar.bz2#3c6966c48d0eecdd65830482667c88f3
+https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-10.3.0-hc0724ed_5.tar.bz2#b8f96ccab5c49efb15a46d09b20487c8
+https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-10.3.0-h4e3e293_5.tar.bz2#1110d236706f2acebabc83e721c3b899
+https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_impl_linux-aarch64-10.3.0-h209a052_12.tar.bz2#a76b4f9764a256cd1be98ef5c2fe13c4
+https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-10.3.0-ha07e0e6_12.tar.bz2#2835e19118b3d8e43cfb041fc9a6d99c
 https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.19.2-h4f20351_2.tar.bz2#4b553ede9fe44be7ee4b80c3aad67f51
 https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-13_linuxaarch64_openblas.tar.bz2#0b8e63f48a4f4c2f382a1ce2d71788a5
 https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-13.0.1-default_hf9dac01_0.tar.bz2#93986a5fa1c39f725ab05380ff2471e6
 https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp13-13.0.1-default_hf9dac01_0.tar.bz2#ac3ba8320af529949dc3356ec2905759
 https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-13_linuxaarch64_openblas.tar.bz2#5937a66b4386d731df627f0eac99928e
-https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.46.0-h097699d_0.tar.bz2#dda93e153833071204e17ee4911edccc
+https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.47.0-h75cb1c7_0.tar.bz2#dab86433a432b91d6e56dcee6a9dc227
 https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-3.19.4-h469bdbd_0.tar.bz2#8601868f83e474baf64c05f29be9eefa
 https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.10.0-h1ab2c7b_2.tar.bz2#91b9f2d8cfd9a3d9341bca8800a8f463
 https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.15.0-hb5cdc64_1.tar.bz2#0389cb676b9ac5b6745e188bee8318da
 https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.37.0-hc164836_0.tar.bz2#81077a2ca51dfd8183f842e5b337e62a
 https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.2.7-hf314db3_13.tar.bz2#262217173231b3a68bcda58c62d57f7e
-https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.3.0-hf897c2e_0.tar.bz2#1fa1a855fad5fbee391ad4cd2b493853
+https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.4.0-h4e544f5_0.tar.bz2#7fca501c7422de2ab639ea6ff3cb37b2
 https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-13-13.0.1-default_hf9dac01_0.tar.bz2#4077900679c43a2f90ec6dee3101829e
-https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-9.4.0-h02353c8_5.tar.bz2#68e145d4581bcbf2773ad426f136a356
+https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-10.3.0-he65f139_5.tar.bz2#9ac5205e79ffa728a807b0a7c6461291
 https://conda.anaconda.org/conda-forge/linux-aarch64/grpc-cpp-1.43.2-h4e595cf_1.tar.bz2#bfa07f38fb1ee7e4cd7aba16dd4335ba
-https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-9.4.0-hff40af5_5.tar.bz2#ba2a66d620e0cde0d7db0fe2e99d6903
-https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-9.4.0-h1e24722_5.tar.bz2#45aee6d63a18a8ce467c30ea43a0aed5
+https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-10.3.0-hc0724ed_5.tar.bz2#86d95ba04abd46d5223ef24ee04b393f
+https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-10.3.0-h72ff769_5.tar.bz2#d41514e0c355842ab6112e363463feef
 https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-7.81.0-hcafe9da_0.tar.bz2#82c3a2999a2a7fc9b8cb8477d98fe7f5
 https://conda.anaconda.org/conda-forge/linux-aarch64/orc-1.7.3-h5c30ecb_0.tar.bz2#cb4f95b76c2515c5a272a36c6af13af8
 https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.9.10-he7f7bba_2_cpython.tar.bz2#902240b183b55c8f1034d0b97b3ce4eb
@@ -85,8 +86,8 @@ https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.8.186-h3fd84e
 https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.0.12-pyhd8ed1ab_0.tar.bz2#1f5b32dabae0f1893ae3283dac7f799e
 https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-13.0.1-default_hf9dac01_0.tar.bz2#9e8852eac03d36a020433f31855c87cb
 https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.4-pyh9f0ad1d_0.tar.bz2#c08b4c1326b880ed44f3ffb04803332f
-https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.3.0-hd62202e_0.tar.bz2#d213dc5d10b2132574af0a583ca6aaae
-https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran-9.4.0-h958508c_5.tar.bz2#d01165871eb7b0645fb5d2e197920c68
+https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.4.0-hdd96247_0.tar.bz2#d2358caa1de8e2d9102825167b814119
+https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran-10.3.0-h80b223c_5.tar.bz2#9f418a066b850e26e79f5c3c9c2e77f6
 https://conda.anaconda.org/conda-forge/noarch/idna-3.3-pyhd8ed1ab_0.tar.bz2#40b50b8b030f5f2f22085c062ed013dd
 https://conda.anaconda.org/conda-forge/noarch/imagesize-1.3.0-pyhd8ed1ab_0.tar.bz2#be807e7606fff9436e5e700f6bffb7c6
 https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-1.35.0-h82cccae_2.tar.bz2#42adaa9929b4b0c743e055d679dd6971
@@ -106,7 +107,7 @@ https://conda.anaconda.org/conda-forge/linux-aarch64/certifi-2021.10.8-py39ha656
 https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-1.15.0-py39hab139ec_0.tar.bz2#e19fa26ceac3f4b0e0f11e4d65b41416
 https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-13.0.1-default_hf9dac01_0.tar.bz2#5cdef3b22ea03f21e81168767d83fe76
 https://conda.anaconda.org/conda-forge/linux-aarch64/docutils-0.17.1-py39ha65689a_1.tar.bz2#cca23e9a0abb7389983153fc060ef403
-https://conda.anaconda.org/conda-forge/linux-aarch64/fortran-compiler-1.3.0-h88a8a60_0.tar.bz2#71f9db6e70556e7215de466d9a57fb86
+https://conda.anaconda.org/conda-forge/linux-aarch64/fortran-compiler-1.4.0-h3fbb618_0.tar.bz2#86c70d1799f508685a013dc31ef3b206
 https://conda.anaconda.org/conda-forge/linux-aarch64/importlib-metadata-4.11.1-py39ha65689a_0.tar.bz2#b09bc4636ea67b5b1ec0747e95a84d69
 https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.0-py39hb9a1dbb_0.tar.bz2#7d84ffc4d0b96c12a2e951d9a0e9ec54
 https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.22.2-py39h8a86e7d_0.tar.bz2#55d9b0e132cca58112f4adcc3665d821
@@ -115,7 +116,7 @@ https://conda.anaconda.org/conda-forge/linux-aarch64/pysocks-1.7.1-py39ha65689a_
 https://conda.anaconda.org/conda-forge/linux-aarch64/setuptools-60.9.3-py39ha65689a_0.tar.bz2#0389bdea7301af99bdc480d40b10d415
 https://conda.anaconda.org/conda-forge/linux-aarch64/arrow-cpp-7.0.0-py39hf9328f6_2_cpu.tar.bz2#a3b3eb29101db54842d4424d9661369a
 https://conda.anaconda.org/conda-forge/linux-aarch64/brotlipy-0.7.0-py39h14843e3_1003.tar.bz2#3a33e442189583f64b9c7c9cf0795236
-https://conda.anaconda.org/conda-forge/linux-aarch64/compilers-1.3.0-h8af1aa0_0.tar.bz2#64c1b1a6c5b1339093c1b7ee4cc6036d
+https://conda.anaconda.org/conda-forge/linux-aarch64/compilers-1.4.0-h8af1aa0_0.tar.bz2#dbcd7032fcc234c1437a773eb6616a91
 https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-36.0.1-py39h659f20f_0.tar.bz2#daf5807253bed814672337a6a9f628b5
 https://conda.anaconda.org/conda-forge/noarch/jinja2-3.0.3-pyhd8ed1ab_0.tar.bz2#036d872c653780cb26e797e2e2f61b4c
 https://conda.anaconda.org/conda-forge/noarch/pygments-2.11.2-pyhd8ed1ab_0.tar.bz2#caef60540e2239e27bf62569a5015e3b
diff --git a/cpp/conda-osx-arm64.lock b/cpp/conda-osx-arm64.lock
index 7679b58..5b94b6c 100644
--- a/cpp/conda-osx-arm64.lock
+++ b/cpp/conda-osx-arm64.lock
@@ -1,6 +1,6 @@
 # Generated by conda-lock.
 # platform: osx-arm64
-# input_hash: 213de6cee69e8b1eece6cd1a009f9d5336d80db7461fa506cdb07b3152629943
+# input_hash: e33f6b7dda21f5540c0300fe1641d2d63038c1ca9c9df8ef538126a822d1291e
 @EXPLICIT
 https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.6.2-h3422bc3_0.tar.bz2#e6c0dfc1c6e34241720983abb66ec35e
 https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2#fc76ace7b94fb1f694988ab1b14dd248
@@ -29,7 +29,6 @@ https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.0.9-h3422bc3_6.t
 https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2#32bd82a6a625ea6ce090a81c3d34edeb
 https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2#30e4362988a2623e9eb34337b83e01f9
 https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-11.0.1.dev0-hf114ba7_23.tar.bz2#402c05211a9c339c71a1e82ac8b7ad81
-https://conda.anaconda.org/conda-forge/osx-arm64/libllvm11-11.1.0-h93073aa_3.tar.bz2#3092589066a18ffa092b842ece9fc426
 https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.3-hbdafb3b_1.tar.bz2#074b9beb2e563515c0dd46229b18d521
 https://conda.anaconda.org/conda-forge/osx-arm64/openssl-1.1.1l-h3422bc3_0.tar.bz2#0b3c59333ff2693e8de50b6f679bd3cd
 https://conda.anaconda.org/conda-forge/osx-arm64/re2-2022.02.01-hbdafb3b_0.tar.bz2#54e29e68123d2ace54d11a0412305967
@@ -40,38 +39,41 @@ https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.12-he1e0b03_0.tar.bz2#2c
 https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.11-hee7b306_1013.tar.bz2#0b65c3db409dd06257dd879605eddb45
 https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.5.11-h4530763_0.tar.bz2#ce11646fafb17267c81d929ca42cdb5c
 https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.5.0-h5c6a83d_0.tar.bz2#1d553ce42ca7852d459e851a5ae3d4d4
+https://conda.anaconda.org/conda-forge/osx-arm64/gmock-1.10.0-h260d524_7.tar.bz2#9cc502d00d51801270531e3021f4bdab
 https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.19.2-hd92b7a7_3.tar.bz2#833b40d09291292d3d6649535aa56b9c
-https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp11.1-11.1.0-default_h0fdd720_1.tar.bz2#d09ee5f38a54d87ba571065695414a28
 https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.10-hbae9a57_4.tar.bz2#a1f2aca3c5999a24527d6f8a3a8e9320
 https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0.dev0-11_0_1_hf114ba7_23.tar.bz2#75f6bd23c894fbb8d353c75edb7041d6
-https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.46.0-he4cd7f6_0.tar.bz2#394abe091b8d8c78b1c59104b8438a90
+https://conda.anaconda.org/conda-forge/osx-arm64/libllvm12-12.0.1-h93073aa_2.tar.bz2#a07550ba127f427126b336199adbaf06
+https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.47.0-he723fca_0.tar.bz2#961b2f1f6307a6bd85aa32cbfa3a6218
 https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-3.19.4-hccf11d3_0.tar.bz2#a89d03f004d294a1d8644189009b7e77
 https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.10.0-hb80f160_2.tar.bz2#0c349d0f6965a927b5b57dedbb0a650b
-https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-11.1.0-h93073aa_3.tar.bz2#edbfd72269b09e40e8f78894608c5c6a
 https://conda.anaconda.org/conda-forge/osx-arm64/mpfr-4.1.0-h6d7a090_1.tar.bz2#c37f296f76cfb61d4f91613da93789e6
 https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h7747421_0.tar.bz2#565b291dcdefa3e59830b1222800f46a
 https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.37.0-h72a2b83_0.tar.bz2#f74a80bbaeb1ba21140af97042e9192c
 https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.2-h861e0a7_0.tar.bz2#1ecb5634b253f1849feefe7227824e3f
 https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.10.5-hea86ef8_0.tar.bz2#03d1eeb5706292ae6570456b98f38dcb
-https://conda.anaconda.org/conda-forge/osx-arm64/clang-11-11.1.0-default_h0fdd720_1.tar.bz2#8ca76d7efe8172e1a55b10e0fa618a5e
 https://conda.anaconda.org/conda-forge/osx-arm64/grpc-cpp-1.43.2-ha9bca3c_1.tar.bz2#ab1d05b7e8c8faa12d941e4452156627
-https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-609-h354fe41_6.tar.bz2#059d1aa055a88f4dd78d79d70974ec2f
+https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-609-h7c97014_7.tar.bz2#30cba0918535606b7d98fa69db02699a
+https://conda.anaconda.org/conda-forge/osx-arm64/libclang-12.0.1-default_h2cfa9b4_4.tar.bz2#16b35318caa525ddfc88cd555874eab0
+https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp12-12.0.1-default_h2cfa9b4_4.tar.bz2#52a2b7dfd3dff3793b6918a9541baa14
 https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-7.81.0-h8fe1914_0.tar.bz2#69a0d49c499feec90cba515d7860f6bd
 https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.18-openmp_h5dd58f0_0.tar.bz2#8860a24cd05b691ea33f8c85f9981d4b
 https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.15.0-h28a9c34_1.tar.bz2#5aa405675684f579041d9d296f89cfc4
+https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-12.0.1-h93073aa_2.tar.bz2#ce91c92b08ab4de225bb69ff6ff157a5
 https://conda.anaconda.org/conda-forge/osx-arm64/mpc-1.2.1-h309154c_0.tar.bz2#5673ae769869dc7df76458cca52557e2
 https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.7.3-hcb6706d_0.tar.bz2#1be35f7f0672449437af796f8bfccf12
 https://conda.anaconda.org/conda-forge/osx-arm64/python-3.9.10-hd16f9c5_2_cpython.tar.bz2#bc3b42bea9ad6a7d230bfe9fe915786e
 https://conda.anaconda.org/conda-forge/noarch/alabaster-0.7.12-py_0.tar.bz2#2489a97287f90176ecdc3ca982b4b0a0
 https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.2.7-h9972306_13.tar.bz2#1aa327d20aec700b23809ce8c1da34cd
-https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-973.0.1-ha8964d5_6.tar.bz2#dabcf3f28dac9615f4afceadbcacda8b
+https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-973.0.1-h83ffe51_7.tar.bz2#7fdf170bad9fea1dfc3d411167e1a74b
 https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.0.12-pyhd8ed1ab_0.tar.bz2#1f5b32dabae0f1893ae3283dac7f799e
-https://conda.anaconda.org/conda-forge/osx-arm64/clang-11.1.0-hce30654_1.tar.bz2#d2671870f9522b53e733561bdafce0aa
+https://conda.anaconda.org/conda-forge/osx-arm64/clang-12-12.0.1-default_h2cfa9b4_4.tar.bz2#9480c5fb29b7f88802268562a3d6cb88
+https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-12-12.0.1-default_h2cfa9b4_4.tar.bz2#90e948b77bd8b664a4aa7261fac272dd
 https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.4-pyh9f0ad1d_0.tar.bz2#c08b4c1326b880ed44f3ffb04803332f
 https://conda.anaconda.org/conda-forge/osx-arm64/gfortran_impl_osx-arm64-11.0.1.dev0-hbce66ab_23.tar.bz2#885d39e5dac9071a6b286968debd6cdf
 https://conda.anaconda.org/conda-forge/noarch/idna-3.3-pyhd8ed1ab_0.tar.bz2#40b50b8b030f5f2f22085c062ed013dd
 https://conda.anaconda.org/conda-forge/noarch/imagesize-1.3.0-pyhd8ed1ab_0.tar.bz2#be807e7606fff9436e5e700f6bffb7c6
-https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h08716b2_6.tar.bz2#02f1884c9e0e8e98ca46bb2f45930856
+https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h08716b2_7.tar.bz2#db54fd6424e004687fcb01c92bec3289
 https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-13_osxarm64_openblas.tar.bz2#cfe4c943d79f32e927f859de87fb03f1
 https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-1.35.0-h2b0db34_2.tar.bz2#5bfd9fa64778bebb079fd0abc2cc588c
 https://conda.anaconda.org/conda-forge/noarch/pycparser-2.21-pyhd8ed1ab_0.tar.bz2#076becd9e05608f8dc72757d5f3a91ff
@@ -87,10 +89,11 @@ https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-1.0.3-py_0.ta
 https://conda.anaconda.org/conda-forge/noarch/zipp-3.7.0-pyhd8ed1ab_1.tar.bz2#b689b2cbc8481b224777415e1a193170
 https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.8.186-hb86bbe7_3.tar.bz2#5443878eb1d419ea51036c3d0e42bbed
 https://conda.anaconda.org/conda-forge/noarch/babel-2.9.1-pyh44b312d_0.tar.bz2#74136ed39bfea0832d338df1e58d013e
-https://conda.anaconda.org/conda-forge/osx-arm64/cctools-973.0.1-ha9384d2_6.tar.bz2#c8b9cc1b376fe0a6214da3be80370773
+https://conda.anaconda.org/conda-forge/osx-arm64/cctools-973.0.1-ha9384d2_7.tar.bz2#06671bfcd54daef34a1f0488eacc43f2
 https://conda.anaconda.org/conda-forge/osx-arm64/certifi-2021.10.8-py39h2804cbe_1.tar.bz2#fb53ec8c7ae669a5388856ffe7c12a00
 https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.15.0-py39h52b1de0_0.tar.bz2#3333a407ad0bb89fb85954579c76b88f
-https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-11.1.0-default_h8b1a7b7_1.tar.bz2#60b4aecc623568847a93a261403c4c40
+https://conda.anaconda.org/conda-forge/osx-arm64/clang-12.0.1-hce30654_4.tar.bz2#6a387333b994cb96ffe4604afd658d43
+https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-12.0.1-default_h2cfa9b4_4.tar.bz2#1d018683f1bd018af47dbc7a8b02e970
 https://conda.anaconda.org/conda-forge/osx-arm64/docutils-0.17.1-py39h2804cbe_1.tar.bz2#11d85bd8f6e9c634a71276ceb70490a2
 https://conda.anaconda.org/conda-forge/osx-arm64/importlib-metadata-4.11.1-py39h2804cbe_0.tar.bz2#09ab5c9ed2087ae8baf13176a07e7a22
 https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-13_osxarm64_openblas.tar.bz2#edf690edcb07d6a02fc12c9f31c2dd94
@@ -100,26 +103,27 @@ https://conda.anaconda.org/conda-forge/noarch/packaging-21.3-pyhd8ed1ab_0.tar.bz
 https://conda.anaconda.org/conda-forge/osx-arm64/pysocks-1.7.1-py39h2804cbe_4.tar.bz2#770a25ef670b5154e54c854f561d667d
 https://conda.anaconda.org/conda-forge/osx-arm64/setuptools-60.9.3-py39h2804cbe_0.tar.bz2#84373bb6755d513fcb98531dbb8cce82
 https://conda.anaconda.org/conda-forge/osx-arm64/brotlipy-0.7.0-py39h5161555_1003.tar.bz2#851dacb18129066f316a417ffc236748
-https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-11.1.0-default_h0fdd720_1.tar.bz2#b483422253628dc78a2e14da93f48bcc
-https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-11.1.0-h103ad0d_0.tar.bz2#7a7d6c99b671eccd17ea66627eb6a938
+https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-12.0.1-default_h2cfa9b4_4.tar.bz2#aafc2c5adf026a97529ff8a8af9b026a
+https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-12.0.1-default_hf584372_4.tar.bz2#179e1cf5987abc9b70b27055371f30dd
 https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-36.0.1-py39hfb8cd70_0.tar.bz2#95d6a9b811c3876e6e5a78c4dbe5cc4e
 https://conda.anaconda.org/conda-forge/noarch/jinja2-3.0.3-pyhd8ed1ab_0.tar.bz2#036d872c653780cb26e797e2e2f61b4c
 https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.22.2-py39h61a45d2_0.tar.bz2#4aa1a915c27a80a9252f9646f39c5b1a
 https://conda.anaconda.org/conda-forge/noarch/pygments-2.11.2-pyhd8ed1ab_0.tar.bz2#caef60540e2239e27bf62569a5015e3b
 https://conda.anaconda.org/conda-forge/osx-arm64/arrow-cpp-7.0.0-py39h763d086_2_cpu.tar.bz2#eacce293f5663c1c23766ac5bcd96abb
-https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-11.1.0-h7d99272_0.tar.bz2#3786907db1287b697dea35257f6e7d07
+https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-12.0.1-h44bac85_0.tar.bz2#e10298d4d84d9bc894b91987752670cd
 https://conda.anaconda.org/conda-forge/noarch/pyopenssl-22.0.0-pyhd8ed1ab_0.tar.bz2#1d7e241dfaf5475e893d4b824bb71b44
-https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-11.1.0-hf92b6e0_6.tar.bz2#e8a4a631081998c6f3e07333004c1259
+https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-12.0.1-h94c6b0c_0.tar.bz2#ffc6c0a11f638971e5fe814f6cbfedbb
 https://conda.anaconda.org/conda-forge/noarch/parquet-cpp-1.5.1-2.tar.bz2#79a5f78c42817594ae016a7896521a97
 https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.8-pyhd8ed1ab_1.tar.bz2#53f1387c68c21cecb386e2cde51b3f7c
-https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.3.0-h3422bc3_0.tar.bz2#9192951695fdc50165683daae24b5943
-https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-11.1.0-h0742238_6.tar.bz2#69647e9cd1ad766fa7b9308564f6224a
-https://conda.anaconda.org/conda-forge/osx-arm64/gfortran_osx-arm64-11.0.1.dev0-h57527a5_15.tar.bz2#90e072be00b31296db1f42bf24da2e3e
+https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-12.0.1-hc0c6576_6.tar.bz2#9a9477bdffd5459156bca3c1b446c945
 https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-7.0.0-py39hd3b58d7_2_cpu.tar.bz2#02f686435b43d0dcecf8de41b4b4af76
 https://conda.anaconda.org/conda-forge/noarch/requests-2.27.1-pyhd8ed1ab_0.tar.bz2#7c1c427246b057b8fa97200ecdb2ed62
-https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.3.0-hc021e02_0.tar.bz2#9374b0a398c592f845498db9f7c63fb9
+https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.4.0-hccd94f0_0.tar.bz2#156fbc93ed14783e586dbf6c5ae1b7e2
+https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-12.0.1-hc2331a0_6.tar.bz2#4d04ee83880d970b984285e894319d0e
+https://conda.anaconda.org/conda-forge/osx-arm64/gfortran_osx-arm64-11.0.1.dev0-h57527a5_15.tar.bz2#90e072be00b31296db1f42bf24da2e3e
+https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.4.0-h3e96240_0.tar.bz2#0566b5c9bad07a5a53e6f018304dc6cb
 https://conda.anaconda.org/conda-forge/osx-arm64/gfortran-11.0.1.dev0-h40eb566_15.tar.bz2#ce046dbc7de8c17e0c19ef48f81d9a81
-https://conda.anaconda.org/conda-forge/osx-arm64/fortran-compiler-1.3.0-h630c574_0.tar.bz2#8a759000650a674186ae399f22df9362
-https://conda.anaconda.org/conda-forge/osx-arm64/compilers-1.3.0-hce30654_0.tar.bz2#58bf1f7b87c147ce7f69bc8344fa8f9c
+https://conda.anaconda.org/conda-forge/osx-arm64/fortran-compiler-1.4.0-haab47bd_0.tar.bz2#3adead5d2e6add926607b1683ef827bb
+https://conda.anaconda.org/conda-forge/osx-arm64/compilers-1.4.0-hce30654_0.tar.bz2#aa120175683d97126e9ba009366b6f91
 https://conda.anaconda.org/conda-forge/noarch/sphinx-4.4.0-pyh6c4a22f_1.tar.bz2#a9025d14c2a609e0d895ad3e75b5369c
 https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.5-pyhd8ed1ab_1.tar.bz2#63d2f874f990fdcab47c822b608d6ade
diff --git a/cpp/environment.yml b/cpp/environment.yml
index 87c9852..de2058e 100644
--- a/cpp/environment.yml
+++ b/cpp/environment.yml
@@ -7,5 +7,6 @@ dependencies:
   - arrow-cpp >=7,<8
   - sphinx
   - gtest
+  - gmock
   - pyarrow >=7,<8
   - clang-tools
\ No newline at end of file
diff --git a/cpp/source/flight.rst b/cpp/source/flight.rst
index 74447ac..77c36e3 100644
--- a/cpp/source/flight.rst
+++ b/cpp/source/flight.rst
@@ -83,3 +83,71 @@ Finally, we'll stop our server:
 
 .. recipe:: ../code/flight.cc ParquetStorageService::StopServer
    :dedent: 2
+
+
+Setting gRPC client options
+===========================
+
+Options for gRPC clients can be passed in using the ``generic_options`` field of
+:cpp:class:`arrow::flight::FlightClientOptions`. There is a list of available
+client options in the `gRPC API documentation <https://grpc.github.io/grpc/cpp/group__grpc__arg__keys.html>`_. 
+
+For example, you can change the maximum message length sent with:
+
+.. recipe:: ../code/flight.cc TestClientOptions::Connect
+   :dedent: 2
+
+
+Flight Service with other gRPC endpoints
+========================================
+
+If you are using the gRPC backend, you can add other gRPC endpoints to the 
+Flight server. While Flight clients won't recognize these endpoints, general
+gRPC clients will be able to.
+
+.. note::
+   If statically linking Arrow Flight, Protobuf and gRPC must also be statically
+   linked, and the same goes for dynamic linking. Read more at
+   https://arrow.apache.org/docs/cpp/build_system.html#a-note-on-linking
+
+Creating the server
+-------------------
+
+To create a gRPC service, first define a service using protobuf.
+
+.. literalinclude:: ../code/protos/helloworld.proto
+   :language: protobuf
+   :linenos:
+   :start-at: syntax = "proto3";
+   :caption: Hello world protobuf specification
+
+Next, you'll need to compile that to provide the protobuf and gRPC generated
+files. See gRPC's `generating client and server code 
+<https://grpc.io/docs/languages/cpp/basics/#generating-client-and-server-code>`_
+docs for details.
+
+Then write an implementation for the gRPC service:
+
+.. literalinclude:: ../code/flight.cc
+   :language: cpp
+   :linenos:
+   :start-at: class HelloWorldServiceImpl
+   :end-at: };  // end HelloWorldServiceImpl
+   :caption: Hello world gRPC service implementation
+
+Finally, use the ``builder_hook`` hook on :cpp:class:`arrow::flight::FlightServerOptions`
+to register the additional gRPC service.
+
+.. recipe:: ../code/flight.cc CustomGrpcImpl::StartServer
+   :dedent: 2
+
+Creating the client
+-------------------
+
+The Flight client implementation doesn't know about any custom gRPC services,
+so to call them you'll need to create a normal gRPC client. For the Hello World
+service, we use the HelloWorldService stub, which is provided by the compiled 
+gRPC definition.
+
+.. recipe:: ../code/flight.cc CustomGrpcImpl::CreateClient
+   :dedent: 2