mirror of https://github.com/grpc/grpc.git
New iomgr implementation backed by the EventEngine API (#26026)
This code adds an iomgr implementation that's backed by an EventEngine. This uses the EventEngine API alone, and separate work will introduce an EventEngine prototype to plug into it. See also drfloob#1: @nicolasnoble has a pull request against this branch, implementing the libuv-based EventEngine. One goal here is to implement the iomgr code such that it can be merged independently without affecting normal builds. This implementation can be built using bazel build --cxxopt='-DGRPC_USE_EVENT_ENGINE' :all Some shortcuts are being taken to get a working, testable version of the engine. EventEngines are not pluggable, for example.pull/26509/head
parent
29eafd4604
commit
25d91e3091
64 changed files with 2079 additions and 90 deletions
@ -0,0 +1,48 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H |
||||
#define GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <string> |
||||
|
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/types/variant.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
/// A set of parameters used to configure an endpoint, either when initiating a
|
||||
/// new connection on the client side or when listening for incoming connections
|
||||
/// on the server side. An EndpointConfig contains a set of zero or more
|
||||
/// Settings. Each setting has a unique name, which can be used to fetch that
|
||||
/// Setting via the Get() method. Each Setting has a value, which can be an
|
||||
/// integer, string, or void pointer. Each EE impl should define the set of
|
||||
/// Settings that it supports being passed into it, along with the corresponding
|
||||
/// type.
|
||||
class EndpointConfig { |
||||
public: |
||||
virtual ~EndpointConfig() = default; |
||||
using Setting = absl::variant<absl::monostate, int, absl::string_view, void*>; |
||||
/// Returns an EndpointConfig Setting. If there is no Setting associated with
|
||||
/// \a key in the EndpointConfig, an \a absl::monostate type will be
|
||||
/// returned. Caller does not take ownership of resulting value.
|
||||
virtual Setting Get(absl::string_view key) const = 0; |
||||
}; |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H
|
@ -0,0 +1,31 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
#if GRPC_ARES == 1 && defined(GRPC_USE_EVENT_ENGINE) |
||||
|
||||
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" |
||||
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory( |
||||
std::shared_ptr<WorkSerializer> /* work_serializer */) { |
||||
return nullptr; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_ARES == 1 && defined(GRPC_USE_EVENT_ENGINE) */ |
@ -0,0 +1,28 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
#if GRPC_ARES == 1 && defined(GRPC_USE_EVENT_ENGINE) |
||||
|
||||
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" |
||||
|
||||
bool grpc_ares_query_ipv6() { |
||||
/* The libuv grpc code currently does not have the code to probe for this,
|
||||
* so we assume for now that IPv6 is always available in contexts where this |
||||
* code will be used. */ |
||||
return true; |
||||
} |
||||
|
||||
#endif /* GRPC_ARES == 1 && defined(GRPC_USE_EVENT_ENGINE) */ |
@ -0,0 +1,46 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/endpoint_config.h> |
||||
|
||||
#include <grpc/impl/codegen/grpc_types.h> |
||||
#include <grpc/impl/codegen/log.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/event_engine/endpoint_config_internal.h" |
||||
#include "src/core/lib/gpr/useful.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EndpointConfig::Setting ChannelArgsEndpointConfig::Get( |
||||
absl::string_view key) const { |
||||
const grpc_arg* arg = grpc_channel_args_find(args_, std::string(key).c_str()); |
||||
if (arg == nullptr) { |
||||
return absl::monostate(); |
||||
} |
||||
switch (arg->type) { |
||||
case GRPC_ARG_STRING: |
||||
return absl::string_view(arg->value.string); |
||||
case GRPC_ARG_INTEGER: |
||||
return arg->value.integer; |
||||
case GRPC_ARG_POINTER: |
||||
return arg->value.pointer.p; |
||||
} |
||||
GPR_UNREACHABLE_CODE(return absl::monostate()); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,42 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_EVENT_ENGINE_ENDPOINT_CONFIG_INTERNAL_H |
||||
#define GRPC_CORE_LIB_EVENT_ENGINE_ENDPOINT_CONFIG_INTERNAL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/endpoint_config.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
/// A readonly \a EndpointConfig based on grpc_channel_args. This class does not
|
||||
/// take ownership of the grpc_endpoint_args*, and instances of this class
|
||||
/// should not be used after the underlying args are destroyed.
|
||||
class ChannelArgsEndpointConfig : public EndpointConfig { |
||||
public: |
||||
explicit ChannelArgsEndpointConfig(const grpc_channel_args* args) |
||||
: args_(args) {} |
||||
Setting Get(absl::string_view key) const override; |
||||
|
||||
private: |
||||
const grpc_channel_args* args_; |
||||
}; |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_CORE_LIB_EVENT_ENGINE_ENDPOINT_CONFIG_INTERNAL_H
|
@ -0,0 +1,50 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/endpoint_config.h> |
||||
#include <grpc/event_engine/event_engine.h> |
||||
#include <grpc/event_engine/port.h> |
||||
#include <grpc/impl/codegen/grpc_types.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "absl/strings/str_format.h" |
||||
#include "absl/strings/str_join.h" |
||||
|
||||
#include "src/core/lib/event_engine/sockaddr.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EventEngine::ResolvedAddress::ResolvedAddress(const sockaddr* address, |
||||
socklen_t size) |
||||
: size_(size) { |
||||
GPR_ASSERT(size <= sizeof(address_)); |
||||
memcpy(&address_, address, size); |
||||
} |
||||
|
||||
const struct sockaddr* EventEngine::ResolvedAddress::address() const { |
||||
return reinterpret_cast<const struct sockaddr*>(address_); |
||||
} |
||||
|
||||
socklen_t EventEngine::ResolvedAddress::size() const { return size_; } |
||||
|
||||
std::shared_ptr<grpc_event_engine::experimental::EventEngine> |
||||
DefaultEventEngineFactory() { |
||||
// TODO(nnoble): delete when uv-ee is merged
|
||||
abort(); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,44 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_EVENT_ENGINE_SOCKADDR_H |
||||
#define GRPC_CORE_LIB_EVENT_ENGINE_SOCKADDR_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/port.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
typedef struct sockaddr grpc_sockaddr; |
||||
typedef struct sockaddr_in grpc_sockaddr_in; |
||||
typedef struct sockaddr_in6 grpc_sockaddr_in6; |
||||
typedef struct in_addr grpc_in_addr; |
||||
typedef struct in6_addr grpc_in6_addr; |
||||
|
||||
#define GRPC_INET_ADDRSTRLEN INET_ADDRSTRLEN |
||||
#define GRPC_INET6_ADDRSTRLEN INET6_ADDRSTRLEN |
||||
|
||||
#define GRPC_SOCK_STREAM SOCK_STREAM |
||||
#define GRPC_SOCK_DGRAM SOCK_DGRAM |
||||
|
||||
#define GRPC_AF_UNSPEC AF_UNSPEC |
||||
#define GRPC_AF_UNIX AF_UNIX |
||||
#define GRPC_AF_INET AF_INET |
||||
#define GRPC_AF_INET6 AF_INET6 |
||||
|
||||
#define GRPC_AI_PASSIVE AI_PASSIVE |
||||
|
||||
#endif |
||||
#endif // GRPC_CORE_LIB_EVENT_ENGINE_SOCKADDR_H
|
@ -0,0 +1,33 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#include <stdlib.h> |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/iomgr/endpoint_pair.h" |
||||
|
||||
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair( |
||||
const char* /* name */, grpc_channel_args* /* args */) { |
||||
// TODO(hork): determine what's needed here in the long run
|
||||
GPR_ASSERT( |
||||
false && |
||||
"grpc_iomgr_create_endpoint_pair is not suppoted with event_engine"); |
||||
} |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,54 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/event_engine/pollset.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EventEngine::Callback GrpcClosureToCallback(grpc_closure* closure, |
||||
grpc_error_handle error) { |
||||
return [closure, error](absl::Status status) { |
||||
grpc_error_handle new_error = |
||||
grpc_error_add_child(error, absl_status_to_grpc_error(status)); |
||||
#ifndef NDEBUG |
||||
closure->scheduled = false; |
||||
if (grpc_trace_closure.enabled()) { |
||||
gpr_log(GPR_DEBUG, |
||||
"EventEngine: running closure %p: created [%s:%d]: %s [%s:%d]", |
||||
closure, closure->file_created, closure->line_created, |
||||
closure->run ? "run" : "scheduled", closure->file_initiated, |
||||
closure->line_initiated); |
||||
} |
||||
#endif |
||||
closure->cb(closure->cb_arg, new_error); |
||||
#ifndef NDEBUG |
||||
if (grpc_trace_closure.enabled()) { |
||||
gpr_log(GPR_DEBUG, "EventEngine: closure %p finished", closure); |
||||
} |
||||
#endif |
||||
GRPC_ERROR_UNREF(error); |
||||
grpc_pollset_ee_broadcast_event(); |
||||
}; |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,33 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_CLOSURE_H |
||||
#define GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_CLOSURE_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EventEngine::Callback GrpcClosureToCallback(grpc_closure* closure, |
||||
grpc_error_handle error); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_CLOSURE_H
|
@ -0,0 +1,194 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include "src/core/lib/iomgr/event_engine/endpoint.h" |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
#include <grpc/slice.h> |
||||
#include <grpc/slice_buffer.h> |
||||
#include <grpc/support/time.h> |
||||
#include "absl/strings/string_view.h" |
||||
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h" |
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/event_engine/closure.h" |
||||
#include "src/core/lib/iomgr/event_engine/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset_set.h" |
||||
#include "src/core/lib/iomgr/resource_quota.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
namespace { |
||||
|
||||
using ::grpc_event_engine::experimental::EventEngine; |
||||
using ::grpc_event_engine::experimental::ResolvedAddressToURI; |
||||
using ::grpc_event_engine::experimental::SliceBuffer; |
||||
|
||||
void endpoint_read(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb, bool /* urgent */) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
if (eeep->endpoint == nullptr) { |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, GRPC_ERROR_CANCELLED); |
||||
return; |
||||
} |
||||
SliceBuffer* read_buffer = new (&eeep->read_buffer) SliceBuffer(slices); |
||||
eeep->endpoint->Read( |
||||
[eeep, cb](absl::Status status) { |
||||
auto* read_buffer = reinterpret_cast<SliceBuffer*>(&eeep->read_buffer); |
||||
read_buffer->~SliceBuffer(); |
||||
grpc_core::ExecCtx exec_ctx; |
||||
grpc_core::Closure::Run(DEBUG_LOCATION, cb, |
||||
absl_status_to_grpc_error(status)); |
||||
exec_ctx.Flush(); |
||||
grpc_pollset_ee_broadcast_event(); |
||||
}, |
||||
read_buffer, absl::InfiniteFuture()); |
||||
} |
||||
|
||||
void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb, void* arg) { |
||||
// TODO(hork): adapt arg to some metrics collection mechanism.
|
||||
(void)arg; |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
if (eeep->endpoint == nullptr) { |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, GRPC_ERROR_CANCELLED); |
||||
return; |
||||
} |
||||
SliceBuffer* write_buffer = new (&eeep->write_buffer) SliceBuffer(slices); |
||||
eeep->endpoint->Write( |
||||
[eeep, cb](absl::Status status) { |
||||
auto* write_buffer = |
||||
reinterpret_cast<SliceBuffer*>(&eeep->write_buffer); |
||||
write_buffer->~SliceBuffer(); |
||||
grpc_core::ExecCtx exec_ctx; |
||||
grpc_core::Closure::Run(DEBUG_LOCATION, cb, |
||||
absl_status_to_grpc_error(status)); |
||||
exec_ctx.Flush(); |
||||
grpc_pollset_ee_broadcast_event(); |
||||
}, |
||||
write_buffer, absl::InfiniteFuture()); |
||||
} |
||||
void endpoint_add_to_pollset(grpc_endpoint* /* ep */, |
||||
grpc_pollset* /* pollset */) {} |
||||
void endpoint_add_to_pollset_set(grpc_endpoint* /* ep */, |
||||
grpc_pollset_set* /* pollset */) {} |
||||
void endpoint_delete_from_pollset_set(grpc_endpoint* /* ep */, |
||||
grpc_pollset_set* /* pollset */) {} |
||||
/// After shutdown, all endpoint operations except destroy are no-op,
|
||||
/// and will return some kind of sane default (empty strings, nullptrs, etc). It
|
||||
/// is the caller's responsibility to ensure that calls to endpoint_shutdown are
|
||||
/// synchronized.
|
||||
void endpoint_shutdown(grpc_endpoint* ep, grpc_error* why) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { |
||||
const char* str = grpc_error_string(why); |
||||
gpr_log(GPR_INFO, "TCP Endpoint %p shutdown why=%s", eeep->endpoint.get(), |
||||
str); |
||||
} |
||||
grpc_resource_user_shutdown(eeep->ru); |
||||
eeep->endpoint.reset(); |
||||
} |
||||
|
||||
void endpoint_destroy(grpc_endpoint* ep) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
grpc_resource_user_unref(eeep->ru); |
||||
delete eeep; |
||||
} |
||||
|
||||
grpc_resource_user* endpoint_get_resource_user(grpc_endpoint* ep) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
return eeep->ru; |
||||
} |
||||
|
||||
absl::string_view endpoint_get_peer(grpc_endpoint* ep) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
if (eeep->endpoint == nullptr) { |
||||
return ""; |
||||
} |
||||
if (eeep->peer_address.empty()) { |
||||
const EventEngine::ResolvedAddress* addr = eeep->endpoint->GetPeerAddress(); |
||||
GPR_ASSERT(addr != nullptr); |
||||
eeep->peer_address = ResolvedAddressToURI(*addr); |
||||
} |
||||
return eeep->peer_address; |
||||
} |
||||
|
||||
absl::string_view endpoint_get_local_address(grpc_endpoint* ep) { |
||||
auto* eeep = reinterpret_cast<grpc_event_engine_endpoint*>(ep); |
||||
if (eeep->endpoint == nullptr) { |
||||
return ""; |
||||
} |
||||
if (eeep->local_address.empty()) { |
||||
const EventEngine::ResolvedAddress* addr = |
||||
eeep->endpoint->GetLocalAddress(); |
||||
GPR_ASSERT(addr != nullptr); |
||||
eeep->local_address = ResolvedAddressToURI(*addr); |
||||
} |
||||
return eeep->local_address; |
||||
} |
||||
|
||||
int endpoint_get_fd(grpc_endpoint* /* ep */) { return -1; } |
||||
|
||||
bool endpoint_can_track_err(grpc_endpoint* /* ep */) { return false; } |
||||
|
||||
grpc_endpoint_vtable grpc_event_engine_endpoint_vtable = { |
||||
endpoint_read, |
||||
endpoint_write, |
||||
endpoint_add_to_pollset, |
||||
endpoint_add_to_pollset_set, |
||||
endpoint_delete_from_pollset_set, |
||||
endpoint_shutdown, |
||||
endpoint_destroy, |
||||
endpoint_get_resource_user, |
||||
endpoint_get_peer, |
||||
endpoint_get_local_address, |
||||
endpoint_get_fd, |
||||
endpoint_can_track_err}; |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_event_engine_endpoint* grpc_tcp_server_endpoint_create( |
||||
std::unique_ptr<EventEngine::Endpoint> ee_endpoint) { |
||||
auto endpoint = new grpc_event_engine_endpoint; |
||||
endpoint->base.vtable = &grpc_event_engine_endpoint_vtable; |
||||
// TODO(hork): populate endpoint->ru from the uvEngine's subclass
|
||||
endpoint->endpoint = std::move(ee_endpoint); |
||||
return endpoint; |
||||
} |
||||
|
||||
grpc_endpoint* grpc_tcp_create(const grpc_channel_args* channel_args, |
||||
absl::string_view peer_address) { |
||||
auto endpoint = new grpc_event_engine_endpoint; |
||||
endpoint->base.vtable = &grpc_event_engine_endpoint_vtable; |
||||
grpc_resource_quota* resource_quota = |
||||
grpc_channel_args_find_pointer<grpc_resource_quota>( |
||||
channel_args, GRPC_ARG_RESOURCE_QUOTA); |
||||
if (resource_quota != nullptr) { |
||||
grpc_resource_quota_ref_internal(resource_quota); |
||||
} else { |
||||
resource_quota = grpc_resource_quota_create(nullptr); |
||||
} |
||||
endpoint->ru = grpc_resource_user_create(resource_quota, |
||||
std::string(peer_address).c_str()); |
||||
grpc_resource_quota_unref_internal(resource_quota); |
||||
return &endpoint->base; |
||||
} |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,53 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_ENDPOINT_H |
||||
#define GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_ENDPOINT_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/resource_quota.h" |
||||
|
||||
struct grpc_event_engine_endpoint { |
||||
grpc_endpoint base; |
||||
std::unique_ptr<grpc_event_engine::experimental::EventEngine::Endpoint> |
||||
endpoint; |
||||
std::string peer_address; |
||||
std::string local_address; |
||||
grpc_resource_user* ru = nullptr; |
||||
std::aligned_storage< |
||||
sizeof(grpc_event_engine::experimental::SliceBuffer), |
||||
alignof(grpc_event_engine::experimental::SliceBuffer)>::type read_buffer; |
||||
std::aligned_storage< |
||||
sizeof(grpc_event_engine::experimental::SliceBuffer), |
||||
alignof(grpc_event_engine::experimental::SliceBuffer)>::type write_buffer; |
||||
}; |
||||
|
||||
/// Creates an internal grpc_endpoint struct from an EventEngine Endpoint.
|
||||
/// Server code needs to create grpc_endpoints after the EventEngine has made
|
||||
/// connections.
|
||||
grpc_event_engine_endpoint* grpc_tcp_server_endpoint_create( |
||||
std::unique_ptr<grpc_event_engine::experimental::EventEngine::Endpoint> ee); |
||||
|
||||
/// Creates a new internal grpc_endpoint struct, when no EventEngine Endpoint
|
||||
/// has yet been created. This is used in client code before connections are
|
||||
/// established.
|
||||
grpc_endpoint* grpc_tcp_create(const grpc_channel_args* channel_args, |
||||
absl::string_view peer_address); |
||||
|
||||
#endif |
||||
#endif // GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_ENDPOINT_H
|
@ -0,0 +1,105 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include "src/core/lib/iomgr/event_engine/iomgr.h" |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/debug/trace.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/event_engine/promise.h" |
||||
#include "src/core/lib/iomgr/iomgr_internal.h" |
||||
#include "src/core/lib/iomgr/tcp_client.h" |
||||
#include "src/core/lib/iomgr/tcp_server.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
#include "src/core/lib/surface/init.h" |
||||
|
||||
extern grpc_tcp_client_vtable grpc_event_engine_tcp_client_vtable; |
||||
extern grpc_tcp_server_vtable grpc_event_engine_tcp_server_vtable; |
||||
extern grpc_timer_vtable grpc_event_engine_timer_vtable; |
||||
extern grpc_pollset_vtable grpc_event_engine_pollset_vtable; |
||||
extern grpc_pollset_set_vtable grpc_event_engine_pollset_set_vtable; |
||||
extern grpc_address_resolver_vtable grpc_event_engine_resolver_vtable; |
||||
|
||||
// Disabled by default. grpc_polling_trace must be defined in all iomgr
|
||||
// implementations due to its usage in lockfree_event.
|
||||
grpc_core::DebugOnlyTraceFlag grpc_polling_trace(false, "polling"); |
||||
|
||||
namespace { |
||||
|
||||
using ::grpc_event_engine::experimental::DefaultEventEngineFactory; |
||||
using ::grpc_event_engine::experimental::EventEngine; |
||||
using ::grpc_event_engine::experimental::Promise; |
||||
|
||||
// Note: This is a pointer to a shared_ptr, so it's trivially destructible.
|
||||
std::shared_ptr<EventEngine>* g_event_engine; |
||||
|
||||
void iomgr_platform_init(void) { |
||||
g_event_engine = |
||||
new std::shared_ptr<EventEngine>(DefaultEventEngineFactory()); |
||||
} |
||||
|
||||
void iomgr_platform_flush(void) {} |
||||
|
||||
void iomgr_platform_shutdown(void) { |
||||
Promise<absl::Status> shutdown_status_promise; |
||||
(*g_event_engine)->Shutdown([&shutdown_status_promise](absl::Status status) { |
||||
shutdown_status_promise.Set(std::move(status)); |
||||
}); |
||||
auto shutdown_status = shutdown_status_promise.Get(); |
||||
GPR_ASSERT(shutdown_status.ok()); |
||||
delete g_event_engine; |
||||
g_event_engine = nullptr; |
||||
} |
||||
|
||||
void iomgr_platform_shutdown_background_closure(void) {} |
||||
|
||||
bool iomgr_platform_is_any_background_poller_thread(void) { |
||||
return (*g_event_engine)->IsWorkerThread(); |
||||
} |
||||
|
||||
bool iomgr_platform_add_closure_to_background_poller( |
||||
grpc_closure* /* closure */, grpc_error* /* error */) { |
||||
return false; |
||||
} |
||||
|
||||
grpc_iomgr_platform_vtable vtable = { |
||||
iomgr_platform_init, |
||||
iomgr_platform_flush, |
||||
iomgr_platform_shutdown, |
||||
iomgr_platform_shutdown_background_closure, |
||||
iomgr_platform_is_any_background_poller_thread, |
||||
iomgr_platform_add_closure_to_background_poller}; |
||||
|
||||
} // namespace
|
||||
|
||||
void grpc_set_default_iomgr_platform() { |
||||
grpc_set_tcp_client_impl(&grpc_event_engine_tcp_client_vtable); |
||||
grpc_set_tcp_server_impl(&grpc_event_engine_tcp_server_vtable); |
||||
grpc_set_timer_impl(&grpc_event_engine_timer_vtable); |
||||
grpc_set_pollset_vtable(&grpc_event_engine_pollset_vtable); |
||||
grpc_set_pollset_set_vtable(&grpc_event_engine_pollset_set_vtable); |
||||
grpc_set_resolver_impl(&grpc_event_engine_resolver_vtable); |
||||
grpc_set_iomgr_platform_vtable(&vtable); |
||||
} |
||||
|
||||
bool grpc_iomgr_run_in_background() { return false; } |
||||
|
||||
grpc_event_engine::experimental::EventEngine* grpc_iomgr_event_engine() { |
||||
return g_event_engine->get(); |
||||
} |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,24 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_IOMGR_H |
||||
#define GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_IOMGR_H |
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
// This can be called anywhere in the EE-based iomgr impl where we need to
|
||||
// access the global EE instance.
|
||||
grpc_event_engine::experimental::EventEngine* grpc_iomgr_event_engine(); |
||||
|
||||
#endif // GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_IOMGR_H
|
@ -0,0 +1,87 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/event_engine/pollset.h" |
||||
#include "src/core/lib/iomgr/iomgr_internal.h" |
||||
#include "src/core/lib/iomgr/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset_set.h" |
||||
|
||||
namespace { |
||||
|
||||
static gpr_mu g_mu; |
||||
static gpr_cv g_cv; |
||||
|
||||
// --- pollset vtable API ---
|
||||
void pollset_global_init(void) { |
||||
gpr_mu_init(&g_mu); |
||||
gpr_cv_init(&g_cv); |
||||
} |
||||
void pollset_global_shutdown(void) { |
||||
gpr_cv_destroy(&g_cv); |
||||
gpr_mu_destroy(&g_mu); |
||||
} |
||||
void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { *mu = &g_mu; } |
||||
void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) { |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, GRPC_ERROR_NONE); |
||||
} |
||||
void pollset_destroy(grpc_pollset* pollset) {} |
||||
grpc_error* pollset_work(grpc_pollset* pollset, grpc_pollset_worker** worker, |
||||
grpc_millis deadline) { |
||||
(void)worker; |
||||
gpr_cv_wait(&g_cv, &g_mu, |
||||
grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME)); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
grpc_error* pollset_kick(grpc_pollset* pollset, |
||||
grpc_pollset_worker* specific_worker) { |
||||
(void)pollset; |
||||
(void)specific_worker; |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
size_t pollset_size(void) { return 1; } |
||||
|
||||
// --- pollset_set vtable API ---
|
||||
grpc_pollset_set* pollset_set_create(void) { return nullptr; } |
||||
void pollset_set_destroy(grpc_pollset_set* pollset_set) {} |
||||
void pollset_set_add_pollset(grpc_pollset_set* pollset_set, |
||||
grpc_pollset* pollset) {} |
||||
|
||||
void pollset_set_del_pollset(grpc_pollset_set* pollset_set, |
||||
grpc_pollset* pollset) {} |
||||
void pollset_set_add_pollset_set(grpc_pollset_set* bag, |
||||
grpc_pollset_set* item) {} |
||||
void pollset_set_del_pollset_set(grpc_pollset_set* bag, |
||||
grpc_pollset_set* item) {} |
||||
|
||||
} // namespace
|
||||
|
||||
void grpc_pollset_ee_broadcast_event() { gpr_cv_signal(&g_cv); } |
||||
|
||||
// --- vtables ---
|
||||
grpc_pollset_vtable grpc_event_engine_pollset_vtable = { |
||||
pollset_global_init, pollset_global_shutdown, |
||||
pollset_init, pollset_shutdown, |
||||
pollset_destroy, pollset_work, |
||||
pollset_kick, pollset_size}; |
||||
|
||||
grpc_pollset_set_vtable grpc_event_engine_pollset_set_vtable = { |
||||
pollset_set_create, pollset_set_destroy, |
||||
pollset_set_add_pollset, pollset_set_del_pollset, |
||||
pollset_set_add_pollset_set, pollset_set_del_pollset_set}; |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,51 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_PROMISE_H |
||||
#define GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_PROMISE_H |
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/gprpp/sync.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
/// A minimal promise implementation.
|
||||
///
|
||||
/// This is light-duty, syntactical sugar around cv wait & signal, which is
|
||||
/// useful in some cases. A more robust implementation is being worked on
|
||||
/// separately.
|
||||
template <typename T> |
||||
class Promise { |
||||
public: |
||||
T& Get() { |
||||
absl::MutexLock lock(&mu_); |
||||
cv_.Wait(&mu_); |
||||
return val_; |
||||
} |
||||
void Set(T&& val) { |
||||
absl::MutexLock lock(&mu_); |
||||
val_ = std::move(val); |
||||
cv_.Signal(); |
||||
} |
||||
|
||||
private: |
||||
absl::Mutex mu_; |
||||
absl::CondVar cv_; |
||||
T val_; |
||||
}; |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_PROMISE_H
|
@ -0,0 +1,41 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/event_engine/resolved_address_internal.h" |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h" |
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EventEngine::ResolvedAddress CreateResolvedAddress( |
||||
const grpc_resolved_address& addr) { |
||||
return EventEngine::ResolvedAddress( |
||||
reinterpret_cast<const sockaddr*>(addr.addr), addr.len); |
||||
} |
||||
|
||||
grpc_resolved_address CreateGRPCResolvedAddress( |
||||
const EventEngine::ResolvedAddress& ra) { |
||||
grpc_resolved_address grpc_addr; |
||||
memcpy(grpc_addr.addr, ra.address(), ra.size()); |
||||
grpc_addr.len = ra.size(); |
||||
return grpc_addr; |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,35 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H |
||||
#define GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
EventEngine::ResolvedAddress CreateResolvedAddress( |
||||
const grpc_resolved_address& addr); |
||||
|
||||
grpc_resolved_address CreateGRPCResolvedAddress( |
||||
const EventEngine::ResolvedAddress& ra); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_CORE_LIB_IOMGR_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H
|
@ -0,0 +1,110 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
#include "absl/functional/bind_front.h" |
||||
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h" |
||||
#include "src/core/lib/gprpp/sync.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/event_engine/iomgr.h" |
||||
#include "src/core/lib/iomgr/event_engine/promise.h" |
||||
#include "src/core/lib/iomgr/event_engine/resolved_address_internal.h" |
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
#include "src/core/lib/iomgr/work_serializer.h" |
||||
#include "src/core/lib/surface/init.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
namespace { |
||||
using ::grpc_event_engine::experimental::CreateGRPCResolvedAddress; |
||||
using ::grpc_event_engine::experimental::EventEngine; |
||||
using ::grpc_event_engine::experimental::Promise; |
||||
|
||||
/// A fire-and-forget class representing an individual DNS request.
|
||||
///
|
||||
/// This provides a place to store the ownership of the DNSResolver object until
|
||||
/// the request is complete.
|
||||
class DnsRequest { |
||||
public: |
||||
DnsRequest(std::unique_ptr<EventEngine::DNSResolver> dns_resolver, |
||||
absl::string_view address, absl::string_view default_port, |
||||
grpc_closure* on_done, grpc_resolved_addresses** addresses) |
||||
: dns_resolver_(std::move(dns_resolver)), |
||||
cb_(on_done), |
||||
addresses_(addresses) { |
||||
dns_resolver_->LookupHostname( |
||||
absl::bind_front(&DnsRequest::OnLookupComplete, this), address, |
||||
default_port, absl::InfiniteFuture()); |
||||
} |
||||
|
||||
private: |
||||
void OnLookupComplete( |
||||
absl::StatusOr<std::vector<EventEngine::ResolvedAddress>> addresses) { |
||||
grpc_core::ExecCtx exec_ctx; |
||||
// Convert addresses to iomgr form.
|
||||
*addresses_ = static_cast<grpc_resolved_addresses*>( |
||||
gpr_malloc(sizeof(grpc_resolved_addresses))); |
||||
(*addresses_)->naddrs = addresses->size(); |
||||
(*addresses_)->addrs = static_cast<grpc_resolved_address*>( |
||||
gpr_malloc(sizeof(grpc_resolved_address) * addresses->size())); |
||||
for (size_t i = 0; i < addresses->size(); ++i) { |
||||
(*addresses_)->addrs[i] = CreateGRPCResolvedAddress((*addresses)[i]); |
||||
} |
||||
grpc_closure* cb = cb_; |
||||
delete this; |
||||
grpc_core::Closure::Run(DEBUG_LOCATION, cb, |
||||
absl_status_to_grpc_error(addresses.status())); |
||||
} |
||||
|
||||
std::unique_ptr<EventEngine::DNSResolver> dns_resolver_; |
||||
grpc_closure* cb_; |
||||
grpc_resolved_addresses** addresses_; |
||||
}; |
||||
|
||||
void resolve_address(const char* addr, const char* default_port, |
||||
grpc_pollset_set* /* interested_parties */, |
||||
grpc_closure* on_done, |
||||
grpc_resolved_addresses** addresses) { |
||||
auto dns_resolver = grpc_iomgr_event_engine()->GetDNSResolver(); |
||||
if (!dns_resolver.ok()) { |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, |
||||
absl_status_to_grpc_error(dns_resolver.status())); |
||||
return; |
||||
} |
||||
new DnsRequest(std::move(*dns_resolver), addr, default_port, on_done, |
||||
addresses); |
||||
} |
||||
|
||||
void blocking_handle_async_resolve_done(void* arg, grpc_error_handle error) { |
||||
static_cast<Promise<grpc_error_handle>*>(arg)->Set(std::move(error)); |
||||
} |
||||
|
||||
grpc_error* blocking_resolve_address(const char* name, const char* default_port, |
||||
grpc_resolved_addresses** addresses) { |
||||
grpc_closure on_done; |
||||
Promise<grpc_error_handle> evt; |
||||
GRPC_CLOSURE_INIT(&on_done, blocking_handle_async_resolve_done, &evt, |
||||
grpc_schedule_on_exec_ctx); |
||||
resolve_address(name, default_port, nullptr, &on_done, addresses); |
||||
return evt.Get(); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_address_resolver_vtable grpc_event_engine_resolver_vtable{ |
||||
resolve_address, blocking_resolve_address}; |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,243 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h" |
||||
#include "src/core/lib/event_engine/endpoint_config_internal.h" |
||||
#include "src/core/lib/event_engine/sockaddr.h" |
||||
#include "src/core/lib/gprpp/ref_counted.h" |
||||
#include "src/core/lib/iomgr/event_engine/closure.h" |
||||
#include "src/core/lib/iomgr/event_engine/endpoint.h" |
||||
#include "src/core/lib/iomgr/event_engine/iomgr.h" |
||||
#include "src/core/lib/iomgr/event_engine/pollset.h" |
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
#include "src/core/lib/iomgr/tcp_client.h" |
||||
#include "src/core/lib/iomgr/tcp_server.h" |
||||
#include "src/core/lib/surface/init.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
namespace { |
||||
using ::grpc_event_engine::experimental::ChannelArgsEndpointConfig; |
||||
using ::grpc_event_engine::experimental::EventEngine; |
||||
using ::grpc_event_engine::experimental::GrpcClosureToCallback; |
||||
using ::grpc_event_engine::experimental::SliceAllocator; |
||||
using ::grpc_event_engine::experimental::SliceAllocatorFactory; |
||||
} // namespace
|
||||
|
||||
struct grpc_tcp_server { |
||||
grpc_tcp_server(std::unique_ptr<EventEngine::Listener> listener, |
||||
grpc_resource_quota* rq) |
||||
: refcount(1, GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace) ? "tcp" : nullptr), |
||||
listener(std::move(listener)), |
||||
resource_quota(rq) { |
||||
shutdown_starting.head = nullptr; |
||||
shutdown_starting.tail = nullptr; |
||||
}; |
||||
~grpc_tcp_server() { |
||||
// TODO(nnoble): see if we can handle this in ~SliceAllocatorFactory
|
||||
grpc_resource_quota_unref_internal(resource_quota); |
||||
grpc_core::ExecCtx::RunList(DEBUG_LOCATION, &shutdown_starting); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
} |
||||
grpc_core::RefCount refcount; |
||||
grpc_core::Mutex mu; |
||||
std::unique_ptr<EventEngine::Listener> listener; |
||||
grpc_closure_list shutdown_starting ABSL_GUARDED_BY(mu); |
||||
grpc_resource_quota* resource_quota; |
||||
grpc_tcp_server_cb on_accept_internal; |
||||
void* on_accept_internal_arg; |
||||
}; |
||||
|
||||
namespace { |
||||
|
||||
/// Converts a grpc_closure to an EventEngine Callback. The closure is expected
|
||||
/// to already be initialized.
|
||||
EventEngine::OnConnectCallback GrpcClosureToOnConnectCallback( |
||||
grpc_closure* closure, grpc_endpoint** endpoint_ptr) { |
||||
return [closure, endpoint_ptr]( |
||||
absl::StatusOr<std::unique_ptr<EventEngine::Endpoint>> endpoint) { |
||||
grpc_core::ExecCtx exec_ctx; |
||||
if (endpoint.ok()) { |
||||
auto* grpc_endpoint_out = |
||||
reinterpret_cast<grpc_event_engine_endpoint*>(*endpoint_ptr); |
||||
grpc_endpoint_out->endpoint = std::move(*endpoint); |
||||
} else { |
||||
grpc_endpoint_destroy(*endpoint_ptr); |
||||
*endpoint_ptr = nullptr; |
||||
} |
||||
grpc_core::Closure::Run(DEBUG_LOCATION, closure, |
||||
absl_status_to_grpc_error(endpoint.status())); |
||||
exec_ctx.Flush(); |
||||
grpc_pollset_ee_broadcast_event(); |
||||
}; |
||||
} |
||||
|
||||
/// Usage note: this method does not take ownership of any pointer arguments.
|
||||
void tcp_connect(grpc_closure* on_connect, grpc_endpoint** endpoint, |
||||
grpc_pollset_set* /* interested_parties */, |
||||
const grpc_channel_args* channel_args, |
||||
const grpc_resolved_address* addr, grpc_millis deadline) { |
||||
grpc_event_engine_endpoint* ee_endpoint = |
||||
reinterpret_cast<grpc_event_engine_endpoint*>( |
||||
grpc_tcp_create(channel_args, grpc_sockaddr_to_uri(addr))); |
||||
*endpoint = &ee_endpoint->base; |
||||
EventEngine::OnConnectCallback ee_on_connect = |
||||
GrpcClosureToOnConnectCallback(on_connect, endpoint); |
||||
SliceAllocator sa(ee_endpoint->ru); |
||||
EventEngine::ResolvedAddress ra(reinterpret_cast<const sockaddr*>(addr->addr), |
||||
addr->len); |
||||
absl::Time ee_deadline = grpc_core::ToAbslTime( |
||||
grpc_millis_to_timespec(deadline, GPR_CLOCK_MONOTONIC)); |
||||
ChannelArgsEndpointConfig endpoint_config(channel_args); |
||||
absl::Status connected = grpc_iomgr_event_engine()->Connect( |
||||
ee_on_connect, ra, endpoint_config, std::move(sa), ee_deadline); |
||||
if (!connected.ok()) { |
||||
// EventEngine failed to start an asynchronous connect.
|
||||
grpc_endpoint_destroy(*endpoint); |
||||
*endpoint = nullptr; |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_connect, |
||||
absl_status_to_grpc_error(connected)); |
||||
} |
||||
} |
||||
|
||||
grpc_error* tcp_server_create(grpc_closure* shutdown_complete, |
||||
const grpc_channel_args* args, |
||||
grpc_tcp_server** server) { |
||||
ChannelArgsEndpointConfig endpoint_config(args); |
||||
grpc_resource_quota* rq = grpc_resource_quota_from_channel_args(args); |
||||
if (rq == nullptr) { |
||||
rq = grpc_resource_quota_create(nullptr); |
||||
} |
||||
EventEngine* event_engine = grpc_iomgr_event_engine(); |
||||
absl::StatusOr<std::unique_ptr<EventEngine::Listener>> listener = |
||||
event_engine->CreateListener( |
||||
[server](std::unique_ptr<EventEngine::Endpoint> ee_endpoint) { |
||||
grpc_core::ExecCtx exec_ctx; |
||||
GPR_ASSERT((*server)->on_accept_internal != nullptr); |
||||
grpc_event_engine_endpoint* iomgr_endpoint = |
||||
grpc_tcp_server_endpoint_create(std::move(ee_endpoint)); |
||||
grpc_tcp_server_acceptor* acceptor = |
||||
static_cast<grpc_tcp_server_acceptor*>( |
||||
gpr_zalloc(sizeof(*acceptor))); |
||||
acceptor->from_server = *server; |
||||
acceptor->external_connection = false; |
||||
(*server)->on_accept_internal((*server)->on_accept_internal_arg, |
||||
&iomgr_endpoint->base, nullptr, |
||||
acceptor); |
||||
exec_ctx.Flush(); |
||||
grpc_pollset_ee_broadcast_event(); |
||||
}, |
||||
GrpcClosureToCallback(shutdown_complete, GRPC_ERROR_NONE), |
||||
endpoint_config, SliceAllocatorFactory(rq)); |
||||
if (!listener.ok()) { |
||||
return absl_status_to_grpc_error(listener.status()); |
||||
} |
||||
*server = new grpc_tcp_server(std::move(*listener), rq); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
void tcp_server_start(grpc_tcp_server* server, |
||||
const std::vector<grpc_pollset*>* /* pollsets */, |
||||
grpc_tcp_server_cb on_accept_cb, void* cb_arg) { |
||||
server->on_accept_internal = on_accept_cb; |
||||
server->on_accept_internal_arg = cb_arg; |
||||
// The iomgr API does not handle situations where the server cannot start, so
|
||||
// a crash may be preferable for now.
|
||||
GPR_ASSERT(server->listener->Start().ok()); |
||||
} |
||||
|
||||
grpc_error* tcp_server_add_port(grpc_tcp_server* s, |
||||
const grpc_resolved_address* addr, |
||||
int* out_port) { |
||||
EventEngine::ResolvedAddress ra(reinterpret_cast<const sockaddr*>(addr->addr), |
||||
addr->len); |
||||
auto port = s->listener->Bind(ra); |
||||
if (!port.ok()) { |
||||
return absl_status_to_grpc_error(port.status()); |
||||
} |
||||
*out_port = *port; |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
grpc_core::TcpServerFdHandler* tcp_server_create_fd_handler( |
||||
grpc_tcp_server* /* s */) { |
||||
// EventEngine-iomgr does not support fds.
|
||||
return nullptr; |
||||
} |
||||
|
||||
unsigned tcp_server_port_fd_count(grpc_tcp_server* /* s */, |
||||
unsigned /* port_index */) { |
||||
return 0; |
||||
} |
||||
|
||||
int tcp_server_port_fd(grpc_tcp_server* /* s */, unsigned /* port_index */, |
||||
unsigned /* fd_index */) { |
||||
// Note: only used internally
|
||||
return -1; |
||||
} |
||||
|
||||
grpc_tcp_server* tcp_server_ref(grpc_tcp_server* s) { |
||||
s->refcount.Ref(DEBUG_LOCATION, "server ref"); |
||||
return s; |
||||
} |
||||
|
||||
void tcp_server_shutdown_starting_add(grpc_tcp_server* s, |
||||
grpc_closure* shutdown_starting) { |
||||
grpc_core::MutexLock lock(&s->mu); |
||||
grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, |
||||
GRPC_ERROR_NONE); |
||||
} |
||||
|
||||
void tcp_server_unref(grpc_tcp_server* s) { |
||||
if (GPR_UNLIKELY(s->refcount.Unref(DEBUG_LOCATION, "server unref"))) { |
||||
delete s; |
||||
} |
||||
} |
||||
|
||||
// No-op, all are handled on listener unref
|
||||
void tcp_server_shutdown_listeners(grpc_tcp_server* /* s */) {} |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_tcp_client_vtable grpc_event_engine_tcp_client_vtable = {tcp_connect}; |
||||
grpc_tcp_server_vtable grpc_event_engine_tcp_server_vtable = { |
||||
tcp_server_create, tcp_server_start, |
||||
tcp_server_add_port, tcp_server_create_fd_handler, |
||||
tcp_server_port_fd_count, tcp_server_port_fd, |
||||
tcp_server_ref, tcp_server_shutdown_starting_add, |
||||
tcp_server_unref, tcp_server_shutdown_listeners}; |
||||
|
||||
// Methods that are expected to exist elsewhere in the codebase.
|
||||
|
||||
struct grpc_fd { |
||||
int fd; |
||||
}; |
||||
|
||||
grpc_fd* grpc_fd_create(int /* fd */, const char* /* name */, |
||||
bool /* track_err */) { |
||||
return nullptr; |
||||
} |
||||
|
||||
grpc_endpoint* grpc_tcp_client_create_from_fd( |
||||
grpc_fd* /* fd */, const grpc_channel_args* /* channel_args */, |
||||
const char* /* addr_str */) { |
||||
return nullptr; |
||||
} |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,57 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_USE_EVENT_ENGINE |
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/event_engine/closure.h" |
||||
#include "src/core/lib/iomgr/event_engine/iomgr.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
#include "src/core/lib/surface/init.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
namespace { |
||||
using ::grpc_event_engine::experimental::EventEngine; |
||||
using ::grpc_event_engine::experimental::GrpcClosureToCallback; |
||||
|
||||
void timer_init(grpc_timer* timer, grpc_millis deadline, |
||||
grpc_closure* closure) { |
||||
timer->ee_task_handle = grpc_iomgr_event_engine()->RunAt( |
||||
grpc_core::ToAbslTime( |
||||
grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME)), |
||||
GrpcClosureToCallback(closure, GRPC_ERROR_NONE), {}); |
||||
} |
||||
|
||||
void timer_cancel(grpc_timer* timer) { |
||||
auto handle = timer->ee_task_handle; |
||||
grpc_iomgr_event_engine()->TryCancel(handle); |
||||
} |
||||
|
||||
/* Internal API */ |
||||
grpc_timer_check_result timer_check(grpc_millis* /* next */) { |
||||
return GRPC_TIMERS_NOT_CHECKED; |
||||
} |
||||
void timer_list_init() {} |
||||
void timer_list_shutdown(void) {} |
||||
void timer_consume_kick(void) {} |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_timer_vtable grpc_event_engine_timer_vtable = { |
||||
timer_init, timer_cancel, timer_check, |
||||
timer_list_init, timer_list_shutdown, timer_consume_kick}; |
||||
|
||||
#endif // GRPC_USE_EVENT_ENGINE
|
@ -0,0 +1,28 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed 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. |
||||
|
||||
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package") |
||||
|
||||
grpc_package(name = "test/core/event_engine") |
||||
|
||||
grpc_cc_test( |
||||
name = "endpoint_config_test", |
||||
srcs = ["endpoint_config_test.cc"], |
||||
external_deps = ["gtest"], |
||||
language = "C++", |
||||
deps = [ |
||||
"//:grpc", |
||||
"//test/core/util:grpc_test_util", |
||||
], |
||||
) |
@ -0,0 +1,46 @@ |
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// Licensed 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "grpc/event_engine/endpoint_config.h" |
||||
|
||||
#include <gmock/gmock.h> |
||||
#include <grpc/grpc.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/event_engine/endpoint_config_internal.h" |
||||
|
||||
using ::grpc_event_engine::experimental::ChannelArgsEndpointConfig; |
||||
|
||||
TEST(EndpointConfigTest, CanSRetrieveValuesFromChannelArgs) { |
||||
grpc_arg arg = grpc_channel_arg_integer_create(const_cast<char*>("arst"), 3); |
||||
const grpc_channel_args args = {1, &arg}; |
||||
ChannelArgsEndpointConfig config(&args); |
||||
EXPECT_EQ(absl::get<int>(config.Get("arst")), 3); |
||||
} |
||||
|
||||
TEST(EndpointConfigTest, ReturnsMonostateForMissingKeys) { |
||||
ChannelArgsEndpointConfig config(nullptr); |
||||
EXPECT_TRUE( |
||||
absl::holds_alternative<absl::monostate>(config.Get("nonexistent"))); |
||||
} |
||||
|
||||
int main(int argc, char** argv) { |
||||
testing::InitGoogleTest(&argc, argv); |
||||
auto result = RUN_ALL_TESTS(); |
||||
return result; |
||||
} |
Loading…
Reference in new issue