chromium/third_party/grpc/src/src/core/lib/channel/channel_stack.h

//
//
// Copyright 2015 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_CHANNEL_CHANNEL_STACK_H
#define GRPC_SRC_CORE_LIB_CHANNEL_CHANNEL_STACK_H

//////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE:
//
// When you update this API, please make the corresponding changes to
// the C++ API in src/cpp/common/channel_filter.{h,cc}
//////////////////////////////////////////////////////////////////////////////

// A channel filter defines how operations on a channel are implemented.
// Channel filters are chained together to create full channels, and if those
// chains are linear, then channel stacks provide a mechanism to minimize
// allocations for that chain.
// Call stacks are created by channel stacks and represent the per-call data
// for that stack.

// Implementations should take care of the following details for a batch -
// 1. Synchronization is achieved with a CallCombiner. View
// src/core/lib/iomgr/call_combiner.h for more details.
// 2. If the filter wants to inject an error on the way down, it needs to call
// grpc_transport_stream_op_batch_finish_with_failure from within the call
// combiner. This will cause any batch callbacks to be called with that error.
// 3. If the filter wants to inject an error on the way up (from a callback), it
// should also inject that error in the recv_trailing_metadata callback so that
// it can have an effect on the call status.
//

#include <grpc/support/port_platform.h>

#include <stddef.h>

#include <functional>
#include <memory>

#include <grpc/event_engine/event_engine.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/time_precise.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/transport/transport.h"

struct grpc_channel_element_args {};
struct grpc_call_element_args {};
struct grpc_call_stats {};
/// Information about the call upon completion.
struct grpc_call_final_info {};

// Channel filters specify:
// 1. the amount of memory needed in the channel & call (via the sizeof_XXX
//    members)
// 2. functions to initialize and destroy channel & call data
//    (init_XXX, destroy_XXX)
// 3. functions to implement call operations and channel operations (call_op,
//    channel_op)
// 4. a name, which is useful when debugging

// Members are laid out in approximate frequency of use order.
struct grpc_channel_filter {};
// A channel_element tracks its filter and the filter requested memory within
// a channel allocation
struct grpc_channel_element {};

// A call_element tracks its filter, the filter requested memory within
// a channel allocation, and the filter requested memory within a call
// allocation
struct grpc_call_element {};

// A channel stack tracks a set of related filters for one channel, and
// guarantees they live within a single malloc() allocation
struct grpc_channel_stack {};

// A call stack tracks a set of related filters for one call, and guarantees
// they live within a single malloc() allocation
struct grpc_call_stack {};

// Get a channel element given a channel stack and its index
grpc_channel_element* grpc_channel_stack_element(grpc_channel_stack* stack,
                                                 size_t i);
// Get the last channel element in a channel stack
grpc_channel_element* grpc_channel_stack_last_element(
    grpc_channel_stack* stack);

// A utility function for a filter to determine how many other instances
// of the same filter exist above it in the same stack.  Intended to be
// used in the filter's init_channel_elem() method.
size_t grpc_channel_stack_filter_instance_number(
    grpc_channel_stack* channel_stack, grpc_channel_element* elem);

// Get a call stack element given a call stack and an index
grpc_call_element* grpc_call_stack_element(grpc_call_stack* stack, size_t i);

// Determine memory required for a channel stack containing a set of filters
size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
                               size_t filter_count);
// Initialize a channel stack given some filters
grpc_error_handle grpc_channel_stack_init(
    int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg,
    const grpc_channel_filter** filters, size_t filter_count,
    const grpc_core::ChannelArgs& args, const char* name,
    grpc_channel_stack* stack);
// Destroy a channel stack
void grpc_channel_stack_destroy(grpc_channel_stack* stack);

// Initialize a call stack given a channel stack. transport_server_data is
// expected to be NULL on a client, or an opaque transport owned pointer on the
// server.
grpc_error_handle grpc_call_stack_init(grpc_channel_stack* channel_stack,
                                       int initial_refs,
                                       grpc_iomgr_cb_func destroy,
                                       void* destroy_arg,
                                       const grpc_call_element_args* elem_args);
// Set a pollset or a pollset_set for a call stack: must occur before the first
// op is started
void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack,
                                                grpc_polling_entity* pollent);

#ifndef NDEBUG
#define GRPC_CALL_STACK_REF(call_stack, reason)
#define GRPC_CALL_STACK_UNREF(call_stack, reason)
#define GRPC_CHANNEL_STACK_REF(channel_stack, reason)
#define GRPC_CHANNEL_STACK_UNREF(channel_stack, reason)
#else
#define GRPC_CALL_STACK_REF
#define GRPC_CALL_STACK_UNREF
#define GRPC_CHANNEL_STACK_REF
#define GRPC_CHANNEL_STACK_UNREF
#endif

inline void grpc_channel_stack::IncrementRefCount() {}

inline void grpc_channel_stack::Unref() {}

inline void grpc_call_stack::IncrementRefCount() {}

inline void grpc_call_stack::Unref() {}

// Destroy a call stack
void grpc_call_stack_destroy(grpc_call_stack* stack,
                             const grpc_call_final_info* final_info,
                             grpc_closure* then_schedule_closure);

// Ignore set pollset{_set} - used by filters if they don't care about pollsets
// at all. Does nothing.
void grpc_call_stack_ignore_set_pollset_or_pollset_set(
    grpc_call_element* elem, grpc_polling_entity* pollent);
// Call the next operation in a call stack
void grpc_call_next_op(grpc_call_element* elem,
                       grpc_transport_stream_op_batch* op);
// Call the next operation (depending on call directionality) in a channel
// stack
void grpc_channel_next_op(grpc_channel_element* elem, grpc_transport_op* op);
// Pass through a request to get_channel_info() to the next child element
void grpc_channel_next_get_info(grpc_channel_element* elem,
                                const grpc_channel_info* channel_info);

// Given the top element of a channel stack, get the channel stack itself
grpc_channel_stack* grpc_channel_stack_from_top_element(
    grpc_channel_element* elem);
// Given the top element of a call stack, get the call stack itself
grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem);

void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
                      grpc_call_element* elem,
                      grpc_transport_stream_op_batch* op);

void grpc_channel_stack_no_post_init(grpc_channel_stack* stk,
                                     grpc_channel_element* elem);

extern grpc_core::TraceFlag grpc_trace_channel;

#define GRPC_CALL_LOG_OP(sev, elem, op)

#endif  // GRPC_SRC_CORE_LIB_CHANNEL_CHANNEL_STACK_H