mirror of https://github.com/grpc/grpc.git
[EventEngine] Modify iomgr to allow creation of event engine clients and client side endpoints (#31661)
* [WIP] EventEngine iomgr endpoint shims * [WIP] EventEngine::Endpoint iomgr shims for the PosixEventEngine * Util functions to help with posix engine listener implementation * sanity * update comments in posix_engine_listener_utils.h * review comments * iwyu * revert prev commit * iwyu * update build * update * regenerate projects * regenerate projects * minor fixes * update BUILD * sanity * update build * regenerate projects * fix unused parameter * sanity * update * sanity * regenerate_projects * remove unused variable * start * update * regenerate_projects * sanity * update * fixes * update * regenerate_projects * update * fix sanity and msan failure * more fixes * build failure * update * fix * sanity * fixes * update * regenerate projects * fix sanity * review comments * An EventEngine subclass to be implemented by all posix based event engines * sanity * comments * update * review comments * re-word * fix * update * review comments * regenerate projects * syntax fix * add lock free event benchmark * releasable mutex lock * fix build isue * update * start * regenerate projects * update * fix * windows build * update * windows portability issue * update * update * update * update * format * update * update * update * update * update * fix sanity * regenerate projects * update * iwyu * Fix resolved address length related bugs in tcp_socket_utils and listener_utils * iwyu * cleanup src/core/lib/event_engine/tcp_socket_utils.cc * iwyu * fix * regenerate projects * fix sanity * re-write endpoint shim * more re-write * cleanup * update * review comments * build issue * more build issue fixes plus adding event_engine_trace * even more build issue fixes * iwyu * add static_cast * update * remove redundant code * update * deduplicate * iwyu * Fix review comments and regenerate_projects * sanity * review comments * fix include guards Co-authored-by: AJ Heller <hork@google.com>pull/32174/head
parent
2f0734272d
commit
8cf04e9a54
39 changed files with 1057 additions and 75 deletions
@ -0,0 +1,34 @@ |
||||
// Copyright 2022 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_SRC_CORE_LIB_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H |
||||
#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H |
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/resolved_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_SRC_CORE_LIB_EVENT_ENGINE_RESOLVED_ADDRESS_INTERNAL_H
|
@ -0,0 +1,36 @@ |
||||
// Copyright 2022 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/event_engine/shim.h" |
||||
|
||||
#include "src/core/lib/experiments/experiments.h" |
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
bool UseEventEngineClient() { |
||||
// TODO(hork, eryu): Adjust the ifdefs accordingly when event engine's become
|
||||
// available for other platforms.
|
||||
#ifdef GRPC_POSIX_SOCKET_TCP |
||||
return grpc_core::IsEventEngineClientEnabled(); |
||||
#else |
||||
return false; |
||||
#endif |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,27 @@ |
||||
// Copyright 2022 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_SRC_CORE_LIB_EVENT_ENGINE_SHIM_H |
||||
#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_SHIM_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
bool UseEventEngineClient(); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_SHIM_H
|
@ -0,0 +1,388 @@ |
||||
// Copyright 2022 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_shims/endpoint.h" |
||||
|
||||
#include <atomic> |
||||
#include <memory> |
||||
|
||||
#include "absl/status/status.h" |
||||
#include "absl/strings/string_view.h" |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
#include <grpc/impl/codegen/slice.h> |
||||
#include <grpc/slice.h> |
||||
#include <grpc/slice_buffer.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/time.h> |
||||
|
||||
#include "src/core/lib/event_engine/posix.h" |
||||
#include "src/core/lib/event_engine/tcp_socket_utils.h" |
||||
#include "src/core/lib/event_engine/trace.h" |
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "src/core/lib/gprpp/sync.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/iomgr/port.h" |
||||
#include "src/core/lib/slice/slice_string_helpers.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
namespace { |
||||
|
||||
constexpr int64_t kShutdownBit = static_cast<int64_t>(1) << 32; |
||||
|
||||
// A wrapper class to manage Event Engine endpoint ref counting and
|
||||
// asynchronous shutdown.
|
||||
class EventEngineEndpointWrapper { |
||||
public: |
||||
struct grpc_event_engine_endpoint { |
||||
grpc_endpoint base; |
||||
EventEngineEndpointWrapper* wrapper; |
||||
std::aligned_storage<sizeof(SliceBuffer), alignof(SliceBuffer)>::type |
||||
read_buffer; |
||||
std::aligned_storage<sizeof(SliceBuffer), alignof(SliceBuffer)>::type |
||||
write_buffer; |
||||
}; |
||||
|
||||
explicit EventEngineEndpointWrapper( |
||||
std::unique_ptr<EventEngine::Endpoint> endpoint); |
||||
|
||||
int Fd() { |
||||
grpc_core::MutexLock lock(&mu_); |
||||
return fd_; |
||||
} |
||||
|
||||
absl::string_view PeerAddress() { |
||||
grpc_core::MutexLock lock(&mu_); |
||||
return peer_address_; |
||||
} |
||||
|
||||
absl::string_view LocalAddress() { |
||||
grpc_core::MutexLock lock(&mu_); |
||||
return local_address_; |
||||
} |
||||
|
||||
void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); } |
||||
void Unref() { |
||||
if (refs_.fetch_sub(1, std::memory_order_acq_rel) == 1) { |
||||
delete this; |
||||
} |
||||
} |
||||
|
||||
// Returns a managed grpc_endpoint object. It retains ownership of the
|
||||
// object.
|
||||
grpc_endpoint* GetGrpcEndpoint() { return &eeep_->base; } |
||||
|
||||
// Read using the underlying EventEngine endpoint object.
|
||||
void Read(absl::AnyInvocable<void(absl::Status)> on_read, SliceBuffer* buffer, |
||||
const EventEngine::Endpoint::ReadArgs* args) { |
||||
endpoint_->Read(std::move(on_read), buffer, args); |
||||
} |
||||
|
||||
// Write using the underlying EventEngine endpoint object
|
||||
void Write(absl::AnyInvocable<void(absl::Status)> on_writable, |
||||
SliceBuffer* data, const EventEngine::Endpoint::WriteArgs* args) { |
||||
endpoint_->Write(std::move(on_writable), data, args); |
||||
} |
||||
|
||||
// Returns true if the endpoint is not yet shutdown. In that case, it also
|
||||
// acquires a shutdown ref. Otherwise it returns false and doesn't modify
|
||||
// the shutdown ref.
|
||||
bool ShutdownRef() { |
||||
int64_t curr = shutdown_ref_.load(std::memory_order_acquire); |
||||
while (true) { |
||||
if (curr & kShutdownBit) { |
||||
return false; |
||||
} |
||||
if (shutdown_ref_.compare_exchange_strong(curr, curr + 1, |
||||
std::memory_order_acq_rel, |
||||
std::memory_order_relaxed)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Decrement the shutdown ref. If this is the last shutdown ref, it also
|
||||
// deletes the underlying event engine endpoint. Deletion of the event
|
||||
// engine endpoint should trigger execution of any pending read/write
|
||||
// callbacks with NOT-OK status.
|
||||
void ShutdownUnref() { |
||||
if (shutdown_ref_.fetch_sub(1, std::memory_order_acq_rel) == |
||||
kShutdownBit + 1) { |
||||
OnShutdownInternal(); |
||||
} |
||||
} |
||||
|
||||
// If trigger shutdown is called the first time, it sets the shutdown bit
|
||||
// and decrements the shutdown ref. If trigger shutdown has been called
|
||||
// before or in parallel, only one of them would win the race. The other
|
||||
// invocation would simply return.
|
||||
void TriggerShutdown() { |
||||
int64_t curr = shutdown_ref_.load(std::memory_order_acquire); |
||||
while (true) { |
||||
if (curr & kShutdownBit) { |
||||
return; |
||||
} |
||||
if (shutdown_ref_.compare_exchange_strong(curr, curr | kShutdownBit, |
||||
std::memory_order_acq_rel, |
||||
std::memory_order_relaxed)) { |
||||
Ref(); |
||||
if (shutdown_ref_.fetch_sub(1, std::memory_order_acq_rel) == |
||||
kShutdownBit + 1) { |
||||
OnShutdownInternal(); |
||||
} |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private: |
||||
void OnShutdownInternal() { |
||||
{ |
||||
grpc_core::MutexLock lock(&mu_); |
||||
fd_ = -1; |
||||
local_address_ = ""; |
||||
peer_address_ = ""; |
||||
} |
||||
endpoint_.reset(); |
||||
// For the Ref taken in TriggerShutdown
|
||||
Unref(); |
||||
} |
||||
std::unique_ptr<EventEngine::Endpoint> endpoint_; |
||||
std::unique_ptr<grpc_event_engine_endpoint> eeep_; |
||||
std::atomic<int64_t> refs_{1}; |
||||
std::atomic<int64_t> shutdown_ref_{1}; |
||||
grpc_core::Mutex mu_; |
||||
std::string peer_address_; |
||||
std::string local_address_; |
||||
int fd_{-1}; |
||||
}; |
||||
|
||||
// Read from the endpoint and place the data in slices slice buffer. The
|
||||
// provided closure is also invoked asynchronously.
|
||||
void EndpointRead(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb, bool /* urgent */, int min_progress_size) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
if (!eeep->wrapper->ShutdownRef()) { |
||||
// Shutdown has already been triggered on the endpoint.
|
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, absl::CancelledError()); |
||||
return; |
||||
} |
||||
|
||||
eeep->wrapper->Ref(); |
||||
EventEngine::Endpoint::ReadArgs read_args = {min_progress_size}; |
||||
|
||||
// TODO(vigneshbabu): Use SliceBufferCast<> here.
|
||||
SliceBuffer* read_buffer = new (&eeep->read_buffer) |
||||
SliceBuffer(SliceBuffer::TakeCSliceBuffer(*slices)); |
||||
read_buffer->Clear(); |
||||
eeep->wrapper->Read( |
||||
[eeep, cb, slices](absl::Status status) { |
||||
auto* read_buffer = reinterpret_cast<SliceBuffer*>(&eeep->read_buffer); |
||||
grpc_slice_buffer_move_into(read_buffer->c_slice_buffer(), slices); |
||||
read_buffer->~SliceBuffer(); |
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { |
||||
size_t i; |
||||
gpr_log(GPR_INFO, "TCP: %p READ (peer=%s) error=%s", eeep->wrapper, |
||||
std::string(eeep->wrapper->PeerAddress()).c_str(), |
||||
status.ToString().c_str()); |
||||
if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { |
||||
for (i = 0; i < slices->count; i++) { |
||||
char* dump = grpc_dump_slice(slices->slices[i], |
||||
GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "READ DATA: %s", dump); |
||||
gpr_free(dump); |
||||
} |
||||
} |
||||
} |
||||
{ |
||||
grpc_core::ApplicationCallbackExecCtx app_ctx; |
||||
grpc_core::ExecCtx exec_ctx; |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status); |
||||
} |
||||
// For the ref taken in EndpointRead
|
||||
eeep->wrapper->Unref(); |
||||
}, |
||||
read_buffer, &read_args); |
||||
|
||||
eeep->wrapper->ShutdownUnref(); |
||||
} |
||||
|
||||
// Write the data from slices and invoke the provided closure asynchronously
|
||||
// after the write is complete.
|
||||
void EndpointWrite(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb, void* arg, int max_frame_size) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
if (!eeep->wrapper->ShutdownRef()) { |
||||
// Shutdown has already been triggered on the endpoint.
|
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, absl::CancelledError()); |
||||
return; |
||||
} |
||||
|
||||
eeep->wrapper->Ref(); |
||||
EventEngine::Endpoint::WriteArgs write_args = {arg, max_frame_size}; |
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { |
||||
size_t i; |
||||
gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s)", eeep->wrapper, |
||||
std::string(eeep->wrapper->PeerAddress()).c_str()); |
||||
if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { |
||||
for (i = 0; i < slices->count; i++) { |
||||
char* dump = |
||||
grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "WRITE DATA: %s", dump); |
||||
gpr_free(dump); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// TODO(vigneshbabu): Use SliceBufferCast<> here.
|
||||
SliceBuffer* write_buffer = new (&eeep->write_buffer) |
||||
SliceBuffer(SliceBuffer::TakeCSliceBuffer(*slices)); |
||||
eeep->wrapper->Write( |
||||
[eeep, cb](absl::Status status) { |
||||
auto* write_buffer = |
||||
reinterpret_cast<SliceBuffer*>(&eeep->write_buffer); |
||||
write_buffer->~SliceBuffer(); |
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { |
||||
gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s) error=%s", eeep->wrapper, |
||||
std::string(eeep->wrapper->PeerAddress()).c_str(), |
||||
status.ToString().c_str()); |
||||
} |
||||
{ |
||||
grpc_core::ApplicationCallbackExecCtx app_ctx; |
||||
grpc_core::ExecCtx exec_ctx; |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status); |
||||
} |
||||
// For the ref taken in EndpointWrite
|
||||
eeep->wrapper->Unref(); |
||||
}, |
||||
write_buffer, &write_args); |
||||
|
||||
eeep->wrapper->ShutdownUnref(); |
||||
} |
||||
|
||||
void EndpointAddToPollset(grpc_endpoint* /* ep */, |
||||
grpc_pollset* /* pollset */) {} |
||||
void EndpointAddToPollsetSet(grpc_endpoint* /* ep */, |
||||
grpc_pollset_set* /* pollset */) {} |
||||
void EndpointDeleteFromPollsetSet(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 EndpointShutdown
|
||||
/// are synchronized.
|
||||
void EndpointShutdown(grpc_endpoint* ep, grpc_error_handle why) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { |
||||
gpr_log(GPR_INFO, "TCP Endpoint %p shutdown why=%s", eeep->wrapper, |
||||
why.ToString().c_str()); |
||||
} |
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::Endpoint %p Shutdown:%s", eeep->wrapper, |
||||
why.ToString().c_str()); |
||||
eeep->wrapper->TriggerShutdown(); |
||||
} |
||||
|
||||
// Attempts to free the underlying data structures.
|
||||
void EndpointDestroy(grpc_endpoint* ep) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
eeep->wrapper->Unref(); |
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::Endpoint %p Destroy", eeep->wrapper); |
||||
} |
||||
|
||||
absl::string_view EndpointGetPeerAddress(grpc_endpoint* ep) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
return eeep->wrapper->PeerAddress(); |
||||
} |
||||
|
||||
absl::string_view EndpointGetLocalAddress(grpc_endpoint* ep) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
return eeep->wrapper->LocalAddress(); |
||||
} |
||||
|
||||
int EndpointGetFd(grpc_endpoint* ep) { |
||||
auto* eeep = |
||||
reinterpret_cast<EventEngineEndpointWrapper::grpc_event_engine_endpoint*>( |
||||
ep); |
||||
return eeep->wrapper->Fd(); |
||||
} |
||||
|
||||
bool EndpointCanTrackErr(grpc_endpoint* /* ep */) { return false; } |
||||
|
||||
grpc_endpoint_vtable grpc_event_engine_endpoint_vtable = { |
||||
EndpointRead, |
||||
EndpointWrite, |
||||
EndpointAddToPollset, |
||||
EndpointAddToPollsetSet, |
||||
EndpointDeleteFromPollsetSet, |
||||
EndpointShutdown, |
||||
EndpointDestroy, |
||||
EndpointGetPeerAddress, |
||||
EndpointGetLocalAddress, |
||||
EndpointGetFd, |
||||
EndpointCanTrackErr}; |
||||
|
||||
EventEngineEndpointWrapper::EventEngineEndpointWrapper( |
||||
std::unique_ptr<EventEngine::Endpoint> endpoint) |
||||
: endpoint_(std::move(endpoint)), |
||||
eeep_(std::make_unique<grpc_event_engine_endpoint>()) { |
||||
eeep_->base.vtable = &grpc_event_engine_endpoint_vtable; |
||||
eeep_->wrapper = this; |
||||
auto local_addr = ResolvedAddressToURI(endpoint_->GetLocalAddress()); |
||||
if (local_addr.ok()) { |
||||
local_address_ = *local_addr; |
||||
} |
||||
auto peer_addr = ResolvedAddressToURI(endpoint_->GetPeerAddress()); |
||||
if (peer_addr.ok()) { |
||||
peer_address_ = *peer_addr; |
||||
} |
||||
#ifdef GRPC_POSIX_SOCKET_TCP |
||||
fd_ = reinterpret_cast<PosixEndpointWithFdSupport*>(endpoint_.get()) |
||||
->GetWrappedFd(); |
||||
#else // GRPC_POSIX_SOCKET_TCP
|
||||
fd_ = -1; |
||||
#endif // GRPC_POSIX_SOCKET_TCP
|
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::Endpoint %p Create", eeep_->wrapper); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_endpoint* grpc_event_engine_endpoint_create( |
||||
std::unique_ptr<EventEngine::Endpoint> ee_endpoint) { |
||||
GPR_DEBUG_ASSERT(ee_endpoint != nullptr); |
||||
auto wrapper = new EventEngineEndpointWrapper(std::move(ee_endpoint)); |
||||
return wrapper->GetGrpcEndpoint(); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,34 @@ |
||||
// Copyright 2022 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_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_ENDPOINT_H |
||||
#define GRPC_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_ENDPOINT_H |
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
/// Creates an internal grpc_endpoint struct from an EventEngine Endpoint.
|
||||
/// Server code needs to create grpc_endpoints after the EventEngine has made
|
||||
/// connections.
|
||||
grpc_endpoint* grpc_event_engine_endpoint_create( |
||||
std::unique_ptr<EventEngine::Endpoint> ee_endpoint); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_ENDPOINT_H
|
@ -0,0 +1,82 @@ |
||||
// Copyright 2022 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_shims/tcp_client.h" |
||||
|
||||
#include "absl/status/status.h" |
||||
#include "absl/strings/string_view.h" |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
#include <grpc/support/time.h> |
||||
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h" |
||||
#include "src/core/lib/event_engine/default_event_engine.h" |
||||
#include "src/core/lib/event_engine/resolved_address_internal.h" |
||||
#include "src/core/lib/event_engine/trace.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/event_engine_shims/endpoint.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/resource_quota/resource_quota.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
int64_t event_engine_tcp_client_connect( |
||||
grpc_closure* on_connect, grpc_endpoint** endpoint, |
||||
const grpc_event_engine::experimental::EndpointConfig& config, |
||||
const grpc_resolved_address* addr, grpc_core::Timestamp deadline) { |
||||
auto resource_quota = reinterpret_cast<grpc_core::ResourceQuota*>( |
||||
config.GetVoidPointer(GRPC_ARG_RESOURCE_QUOTA)); |
||||
auto addr_uri = grpc_sockaddr_to_uri(addr); |
||||
EventEngine::ConnectionHandle handle = GetDefaultEventEngine()->Connect( |
||||
[on_connect, |
||||
endpoint](absl::StatusOr<std::unique_ptr<EventEngine::Endpoint>> ep) { |
||||
grpc_core::ApplicationCallbackExecCtx app_ctx; |
||||
grpc_core::ExecCtx exec_ctx; |
||||
absl::Status conn_status = ep.ok() ? absl::OkStatus() : ep.status(); |
||||
if (ep.ok()) { |
||||
*endpoint = grpc_event_engine_endpoint_create(std::move(*ep)); |
||||
} else { |
||||
*endpoint = nullptr; |
||||
} |
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::Connect Status: %s", |
||||
ep.status().ToString().c_str()); |
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_connect, |
||||
absl_status_to_grpc_error(conn_status)); |
||||
}, |
||||
CreateResolvedAddress(*addr), config, |
||||
resource_quota != nullptr |
||||
? resource_quota->memory_quota()->CreateMemoryOwner( |
||||
absl::StrCat("tcp-client:", addr_uri.value())) |
||||
: grpc_event_engine::experimental::MemoryAllocator(), |
||||
std::max(grpc_core::Duration::Milliseconds(1), |
||||
deadline - grpc_core::Timestamp::Now())); |
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::Connect Peer: %s, handle: %" PRId64, |
||||
(*addr_uri).c_str(), |
||||
static_cast<int64_t>(handle.keys[0])); |
||||
return handle.keys[0]; |
||||
} |
||||
|
||||
bool event_engine_tcp_client_cancel_connect(int64_t connection_handle) { |
||||
GRPC_EVENT_ENGINE_TRACE("EventEngine::CancelConnect handle: %" PRId64, |
||||
connection_handle); |
||||
return GetDefaultEventEngine()->CancelConnect( |
||||
{static_cast<intptr_t>(connection_handle), 0}); |
||||
} |
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
@ -0,0 +1,44 @@ |
||||
// Copyright 2022 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_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_TCP_CLIENT_H |
||||
#define GRPC_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_TCP_CLIENT_H |
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/event_engine/event_engine.h> |
||||
|
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/resolved_address.h" |
||||
|
||||
namespace grpc_event_engine { |
||||
namespace experimental { |
||||
|
||||
/// Attempts to use event engine to connect to the specified remote address and
|
||||
/// invokes the on_connect callback asynchronously upon connection
|
||||
/// establishment, failure or timeout. It returns a 64 bit connection handle
|
||||
/// which can later be used to cancel an in progress connection attempt.
|
||||
int64_t event_engine_tcp_client_connect(grpc_closure* on_connect, |
||||
grpc_endpoint** endpoint, |
||||
const EndpointConfig& config, |
||||
const grpc_resolved_address* addr, |
||||
grpc_core::Timestamp deadline); |
||||
|
||||
/// Attempts to cancel an in progress connection attempt represented by the
|
||||
/// passed in connection handle. It returns true if the cancellation attempt
|
||||
/// succeeded. Otherwise it returns false.
|
||||
bool event_engine_tcp_client_cancel_connect(int64_t connection_handle); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_IOMGR_EVENT_ENGINE_SHIMS_TCP_CLIENT_H
|
Loading…
Reference in new issue