Merge branch 'master' into grpc_namespace_completion_queue

pull/18731/head
Karthik Ravi Shankar 6 years ago
commit 5de22c4bd4
  1. 1
      BUILD
  2. 1
      BUILD.gn
  3. 3
      CMakeLists.txt
  4. 3
      Makefile
  5. 1
      build.yaml
  6. 1
      gRPC-C++.podspec
  7. 3
      include/grpc/impl/codegen/port_platform.h
  8. 2
      include/grpc/support/alloc.h
  9. 10
      include/grpcpp/impl/codegen/async_generic_service.h
  10. 2
      include/grpcpp/impl/codegen/async_stream.h
  11. 2
      include/grpcpp/impl/codegen/client_callback.h
  12. 6
      include/grpcpp/impl/codegen/completion_queue_impl.h
  13. 4
      include/grpcpp/impl/codegen/server_context.h
  14. 8
      include/grpcpp/impl/codegen/service_type.h
  15. 2
      include/grpcpp/impl/server_initializer_impl.h
  16. 4
      include/grpcpp/security/server_credentials.h
  17. 4
      include/grpcpp/security/server_credentials_impl.h
  18. 329
      include/grpcpp/server.h
  19. 3
      include/grpcpp/server_builder_impl.h
  20. 7
      include/grpcpp/server_impl.h
  21. 22
      src/core/ext/filters/client_channel/subchannel.cc
  22. 43
      src/core/lib/channel/channel_stack.cc
  23. 73
      src/core/lib/gpr/alloc.cc
  24. 10
      src/core/lib/gpr/alloc.h
  25. 8
      src/core/lib/gprpp/arena.cc
  26. 6
      src/core/lib/gprpp/arena.h
  27. 22
      src/core/lib/iomgr/tcp_posix.cc
  28. 6
      src/core/lib/surface/call.cc
  29. 6
      src/core/lib/transport/metadata.cc
  30. 2
      src/core/lib/transport/transport.cc
  31. 602
      src/cpp/server/server_cc.cc
  32. 18
      test/core/gpr/alloc_test.cc
  33. 26
      test/core/util/memory_counters.cc
  34. 2
      test/cpp/util/metrics_server.h
  35. 1
      tools/doxygen/Doxyfile.c++
  36. 1
      tools/doxygen/Doxyfile.c++.internal
  37. 2
      tools/run_tests/generated/sources_and_headers.json

@ -257,6 +257,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/security/server_credentials.h",
"include/grpcpp/security/server_credentials_impl.h",
"include/grpcpp/server.h",
"include/grpcpp/server_impl.h",
"include/grpcpp/server_builder.h",
"include/grpcpp/server_builder_impl.h",
"include/grpcpp/server_context.h",

@ -1105,6 +1105,7 @@ config("grpc_config") {
"include/grpcpp/server_builder.h",
"include/grpcpp/server_builder_impl.h",
"include/grpcpp/server_context.h",
"include/grpcpp/server_impl.h",
"include/grpcpp/server_posix.h",
"include/grpcpp/server_posix_impl.h",
"include/grpcpp/support/async_stream.h",

@ -3072,6 +3072,7 @@ foreach(_hdr
include/grpcpp/server_builder.h
include/grpcpp/server_builder_impl.h
include/grpcpp/server_context.h
include/grpcpp/server_impl.h
include/grpcpp/server_posix.h
include/grpcpp/server_posix_impl.h
include/grpcpp/support/async_stream.h
@ -3687,6 +3688,7 @@ foreach(_hdr
include/grpcpp/server_builder.h
include/grpcpp/server_builder_impl.h
include/grpcpp/server_context.h
include/grpcpp/server_impl.h
include/grpcpp/server_posix.h
include/grpcpp/server_posix_impl.h
include/grpcpp/support/async_stream.h
@ -4676,6 +4678,7 @@ foreach(_hdr
include/grpcpp/server_builder.h
include/grpcpp/server_builder_impl.h
include/grpcpp/server_context.h
include/grpcpp/server_impl.h
include/grpcpp/server_posix.h
include/grpcpp/server_posix_impl.h
include/grpcpp/support/async_stream.h

@ -5412,6 +5412,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/server_builder.h \
include/grpcpp/server_builder_impl.h \
include/grpcpp/server_context.h \
include/grpcpp/server_impl.h \
include/grpcpp/server_posix.h \
include/grpcpp/server_posix_impl.h \
include/grpcpp/support/async_stream.h \
@ -6035,6 +6036,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/server_builder.h \
include/grpcpp/server_builder_impl.h \
include/grpcpp/server_context.h \
include/grpcpp/server_impl.h \
include/grpcpp/server_posix.h \
include/grpcpp/server_posix_impl.h \
include/grpcpp/support/async_stream.h \
@ -6973,6 +6975,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/server_builder.h \
include/grpcpp/server_builder_impl.h \
include/grpcpp/server_context.h \
include/grpcpp/server_impl.h \
include/grpcpp/server_posix.h \
include/grpcpp/server_posix_impl.h \
include/grpcpp/support/async_stream.h \

@ -1385,6 +1385,7 @@ filegroups:
- include/grpcpp/server_builder.h
- include/grpcpp/server_builder_impl.h
- include/grpcpp/server_context.h
- include/grpcpp/server_impl.h
- include/grpcpp/server_posix.h
- include/grpcpp/server_posix_impl.h
- include/grpcpp/support/async_stream.h

@ -124,6 +124,7 @@ Pod::Spec.new do |s|
'include/grpcpp/server_builder.h',
'include/grpcpp/server_builder_impl.h',
'include/grpcpp/server_context.h',
'include/grpcpp/server_impl.h',
'include/grpcpp/server_posix.h',
'include/grpcpp/server_posix_impl.h',
'include/grpcpp/support/async_stream.h',

@ -77,6 +77,7 @@
#define GPR_WINDOWS 1
#define GPR_WINDOWS_SUBPROCESS 1
#define GPR_WINDOWS_ENV
#define GPR_HAS_ALIGNED_MALLOC 1
#ifdef __MSYS__
#define GPR_GETPID_IN_UNISTD_H 1
#define GPR_MSYS_TMPFILE
@ -173,6 +174,7 @@
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_HAS_PTHREAD_H 1
#define GPR_HAS_ALIGNED_ALLOC 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifdef _LP64
#define GPR_ARCH_64 1
@ -238,6 +240,7 @@
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_HAS_POSIX_MEMALIGN 1
#define GPR_HAS_PTHREAD_H 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifndef GRPC_CFSTREAM

@ -32,6 +32,8 @@ typedef struct gpr_allocation_functions {
void* (*zalloc_fn)(size_t size); /** if NULL, uses malloc_fn then memset */
void* (*realloc_fn)(void* ptr, size_t size);
void (*free_fn)(void* ptr);
void* (*aligned_alloc_fn)(size_t size, size_t alignment);
void (*aligned_free_fn)(void* ptr);
} gpr_allocation_functions;
/** malloc.

@ -39,7 +39,7 @@ class GenericServerContext final : public ServerContext {
const grpc::string& host() const { return host_; }
private:
friend class Server;
friend class grpc_impl::Server;
friend class ServerInterface;
void Clear() {
@ -79,8 +79,8 @@ class AsyncGenericService final {
ServerCompletionQueue* notification_cq, void* tag);
private:
friend class Server;
Server* server_;
friend class grpc_impl::Server;
grpc_impl::Server* server_;
};
namespace experimental {
@ -135,14 +135,14 @@ class CallbackGenericService {
}
private:
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
internal::CallbackBidiHandler<ByteBuffer, ByteBuffer>* Handler() {
return new internal::CallbackBidiHandler<ByteBuffer, ByteBuffer>(
[this] { return CreateReactor(); });
}
Server* server_{nullptr};
grpc_impl::Server* server_{nullptr};
};
} // namespace experimental
} // namespace grpc

@ -1097,7 +1097,7 @@ class ServerAsyncReaderWriter final
}
private:
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
void BindCall(::grpc::internal::Call* call) override { call_ = *call; }

@ -176,6 +176,8 @@ class ClientCallbackUnary {
// StartWrite, or AddHold operations on the streaming object. Note that none of
// the classes are pure; all reactions have a default empty reaction so that the
// user class only needs to override those classes that it cares about.
// The reactor must be passed to the stub invocation before any of the below
// operations can be called.
/// \a ClientBidiReactor is the interface for a bidirectional streaming RPC.
template <class Request, class Response>

@ -44,11 +44,11 @@ struct grpc_completion_queue;
namespace grpc_impl {
class Channel;
class Server;
class ServerBuilder;
} // namespace grpc_impl
namespace grpc {
class Server;
template <class R>
class ClientReader;
template <class W>
@ -277,7 +277,7 @@ class CompletionQueue : private ::grpc::GrpcLibraryCodegen {
friend class ::grpc::internal::TemplatedBidiStreamingHandler;
template <::grpc::StatusCode code>
friend class ::grpc::internal::ErrorMethodHandler;
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
friend class ::grpc::ServerContext;
friend class ::grpc::ServerInterface;
template <class InputMessage, class OutputMessage>
@ -414,7 +414,7 @@ class ServerCompletionQueue : public CompletionQueue {
grpc_cq_polling_type polling_type_;
friend class ::grpc_impl::ServerBuilder;
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
};
} // namespace grpc_impl

@ -44,11 +44,11 @@ struct census_context;
namespace grpc_impl {
class CompletionQueue;
class Server;
} // namespace grpc_impl
namespace grpc {
class ClientContext;
class GenericServerContext;
class Server;
class ServerInterface;
template <class W, class R>
class ServerAsyncReader;
@ -273,7 +273,7 @@ class ServerContext {
friend class ::grpc::testing::InteropServerContextInspector;
friend class ::grpc::testing::ServerContextTestSpouse;
friend class ::grpc::ServerInterface;
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
template <class W, class R>
friend class ::grpc::ServerAsyncReader;
template <class W>

@ -26,9 +26,13 @@
#include <grpcpp/impl/codegen/server_interface.h>
#include <grpcpp/impl/codegen/status.h>
namespace grpc {
namespace grpc_impl {
class Server;
class CompletionQueue;
} // namespace grpc_impl
namespace grpc {
class ServerInterface;
class ServerContext;
@ -231,7 +235,7 @@ class Service {
}
private:
friend class Server;
friend class grpc_impl::Server;
friend class ServerInterface;
ServerInterface* server_;
std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;

@ -26,10 +26,10 @@
namespace grpc {
class Server;
class Service;
} // namespace grpc
namespace grpc_impl {
class Server;
class ServerInitializer {
public:

@ -21,6 +21,10 @@
#include <grpcpp/security/server_credentials_impl.h>
namespace grpc_impl {
class Server;
} // namespace grpc_impl
namespace grpc {
typedef ::grpc_impl::ServerCredentials ServerCredentials;

@ -30,10 +30,10 @@ struct grpc_server;
namespace grpc {
class Server;
struct SslServerCredentialsOptions;
} // namespace grpc
namespace grpc_impl {
class Server;
/// Wrapper around \a grpc_server_credentials, a way to authenticate a server.
class ServerCredentials {
@ -46,7 +46,7 @@ class ServerCredentials {
const std::shared_ptr<grpc::AuthMetadataProcessor>& processor) = 0;
private:
friend class ::grpc::Server;
friend class ::grpc_impl::Server;
/// Tries to bind \a server to the given \a addr (eg, localhost:1234,
/// 192.168.1.1:31416, [::1]:27182, etc.)

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,334 +19,11 @@
#ifndef GRPCPP_SERVER_H
#define GRPCPP_SERVER_H
#include <condition_variable>
#include <list>
#include <memory>
#include <mutex>
#include <vector>
#include <grpcpp/server_impl.h>
#include <grpc/compression.h>
#include <grpc/support/atm.h>
#include <grpcpp/channel.h>
#include <grpcpp/completion_queue.h>
#include <grpcpp/health_check_service_interface.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/impl/codegen/server_interface.h>
#include <grpcpp/impl/rpc_service_method.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/config.h>
#include <grpcpp/support/status.h>
struct grpc_server;
namespace grpc_impl {
class ServerInitializer;
}
namespace grpc {
class AsyncGenericService;
class ServerContext;
/// Represents a gRPC server.
///
/// Use a \a grpc::ServerBuilder to create, configure, and start
/// \a Server instances.
class Server : public ServerInterface, private GrpcLibraryCodegen {
public:
~Server();
/// Block until the server shuts down.
///
/// \warning The server must be either shutting down or some other thread must
/// call \a Shutdown for this function to ever return.
void Wait() override;
/// Global callbacks are a set of hooks that are called when server
/// events occur. \a SetGlobalCallbacks method is used to register
/// the hooks with gRPC. Note that
/// the \a GlobalCallbacks instance will be shared among all
/// \a Server instances in an application and can be set exactly
/// once per application.
class GlobalCallbacks {
public:
virtual ~GlobalCallbacks() {}
/// Called before server is created.
virtual void UpdateArguments(ChannelArguments* args) {}
/// Called before application callback for each synchronous server request
virtual void PreSynchronousRequest(ServerContext* context) = 0;
/// Called after application callback for each synchronous server request
virtual void PostSynchronousRequest(ServerContext* context) = 0;
/// Called before server is started.
virtual void PreServerStart(Server* server) {}
/// Called after a server port is added.
virtual void AddPort(Server* server, const grpc::string& addr,
ServerCredentials* creds, int port) {}
};
/// Set the global callback object. Can only be called once per application.
/// Does not take ownership of callbacks, and expects the pointed to object
/// to be alive until all server objects in the process have been destroyed.
/// The same \a GlobalCallbacks object will be used throughout the
/// application and is shared among all \a Server objects.
static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
/// Returns a \em raw pointer to the underlying \a grpc_server instance.
/// EXPERIMENTAL: for internal/test use only
grpc_server* c_server();
/// Returns the health check service.
HealthCheckServiceInterface* GetHealthCheckService() const {
return health_check_service_.get();
}
/// Establish a channel for in-process communication
std::shared_ptr<Channel> InProcessChannel(const ChannelArguments& args);
/// NOTE: class experimental_type is not part of the public API of this class.
/// TODO(yashykt): Integrate into public API when this is no longer
/// experimental.
class experimental_type {
public:
explicit experimental_type(Server* server) : server_(server) {}
/// Establish a channel for in-process communication with client
/// interceptors
std::shared_ptr<Channel> InProcessChannelWithInterceptors(
const ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
private:
Server* server_;
};
/// NOTE: The function experimental() is not stable public API. It is a view
/// to the experimental components of this class. It may be changed or removed
/// at any time.
experimental_type experimental() { return experimental_type(this); }
protected:
/// Register a service. This call does not take ownership of the service.
/// The service must exist for the lifetime of the Server instance.
bool RegisterService(const grpc::string* host, Service* service) override;
/// Try binding the server to the given \a addr endpoint
/// (port, and optionally including IP address to bind to).
///
/// It can be invoked multiple times. Should be used before
/// starting the server.
///
/// \param addr The address to try to bind to the server (eg, localhost:1234,
/// 192.168.1.1:31416, [::1]:27182, etc.).
/// \param creds The credentials associated with the server.
///
/// \return bound port number on success, 0 on failure.
///
/// \warning It is an error to call this method on an already started server.
int AddListeningPort(const grpc::string& addr,
ServerCredentials* creds) override;
/// NOTE: This is *NOT* a public API. The server constructors are supposed to
/// be used by \a ServerBuilder class only. The constructor will be made
/// 'private' very soon.
///
/// Server constructors. To be used by \a ServerBuilder only.
///
/// \param max_message_size Maximum message length that the channel can
/// receive.
///
/// \param args The channel args
///
/// \param sync_server_cqs The completion queues to use if the server is a
/// synchronous server (or a hybrid server). The server polls for new RPCs on
/// these queues
///
/// \param min_pollers The minimum number of polling threads per server
/// completion queue (in param sync_server_cqs) to use for listening to
/// incoming requests (used only in case of sync server)
///
/// \param max_pollers The maximum number of polling threads per server
/// completion queue (in param sync_server_cqs) to use for listening to
/// incoming requests (used only in case of sync server)
///
/// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on
/// server completion queues passed via sync_server_cqs param.
Server(int max_message_size, ChannelArguments* args,
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
sync_server_cqs,
int min_pollers, int max_pollers, int sync_cq_timeout_msec,
grpc_resource_quota* server_rq = nullptr,
std::vector<
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>
interceptor_creators = std::vector<std::unique_ptr<
experimental::ServerInterceptorFactoryInterface>>());
/// Start the server.
///
/// \param cqs Completion queues for handling asynchronous services. The
/// caller is required to keep all completion queues live until the server is
/// destroyed.
/// \param num_cqs How many completion queues does \a cqs hold.
void Start(ServerCompletionQueue** cqs, size_t num_cqs) override;
grpc_server* server() override { return server_; }
private:
std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>*
interceptor_creators() override {
return &interceptor_creators_;
}
friend class AsyncGenericService;
friend class grpc_impl::ServerBuilder;
friend class grpc_impl::ServerInitializer;
class SyncRequest;
class CallbackRequestBase;
template <class ServerContextType>
class CallbackRequest;
class UnimplementedAsyncRequest;
class UnimplementedAsyncResponse;
/// SyncRequestThreadManager is an implementation of ThreadManager. This class
/// is responsible for polling for incoming RPCs and calling the RPC handlers.
/// This is only used in case of a Sync server (i.e a server exposing a sync
/// interface)
class SyncRequestThreadManager;
/// Register a generic service. This call does not take ownership of the
/// service. The service must exist for the lifetime of the Server instance.
void RegisterAsyncGenericService(AsyncGenericService* service) override;
/// NOTE: class experimental_registration_type is not part of the public API
/// of this class
/// TODO(vjpai): Move these contents to the public API of Server when
/// they are no longer experimental
class experimental_registration_type final
: public experimental_registration_interface {
public:
explicit experimental_registration_type(Server* server) : server_(server) {}
void RegisterCallbackGenericService(
experimental::CallbackGenericService* service) override {
server_->RegisterCallbackGenericService(service);
}
private:
Server* server_;
};
/// TODO(vjpai): Mark this override when experimental type above is deleted
void RegisterCallbackGenericService(
experimental::CallbackGenericService* service);
/// NOTE: The function experimental_registration() is not stable public API.
/// It is a view to the experimental components of this class. It may be
/// changed or removed at any time.
experimental_registration_interface* experimental_registration() override {
return &experimental_registration_;
}
void PerformOpsOnCall(internal::CallOpSetInterface* ops,
internal::Call* call) override;
void ShutdownInternal(gpr_timespec deadline) override;
int max_receive_message_size() const override {
return max_receive_message_size_;
}
CompletionQueue* CallbackCQ() override;
grpc_impl::ServerInitializer* initializer();
// A vector of interceptor factory objects.
// This should be destroyed after health_check_service_ and this requirement
// is satisfied by declaring interceptor_creators_ before
// health_check_service_. (C++ mandates that member objects be destroyed in
// the reverse order of initialization.)
std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>
interceptor_creators_;
const int max_receive_message_size_;
/// The following completion queues are ONLY used in case of Sync API
/// i.e. if the server has any services with sync methods. The server uses
/// these completion queues to poll for new RPCs
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
sync_server_cqs_;
/// List of \a ThreadManager instances (one for each cq in
/// the \a sync_server_cqs)
std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
// Outstanding unmatched callback requests, indexed by method.
// NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't
// copyable or movable and thus will cause compilation errors. We
// actually only want to extend the vector before the threaded use
// starts, but this is still a limitation.
std::vector<gpr_atm> callback_unmatched_reqs_count_;
// List of callback requests to start when server actually starts.
std::list<CallbackRequestBase*> callback_reqs_to_start_;
// For registering experimental callback generic service; remove when that
// method longer experimental
experimental_registration_type experimental_registration_{this};
// Server status
grpc::internal::Mutex mu_;
bool started_;
bool shutdown_;
bool shutdown_notified_; // Was notify called on the shutdown_cv_
grpc::internal::CondVar shutdown_cv_;
// It is ok (but not required) to nest callback_reqs_mu_ under mu_ .
// Incrementing callback_reqs_outstanding_ is ok without a lock but it must be
// decremented under the lock in case it is the last request and enables the
// server shutdown. The increment is performance-critical since it happens
// during periods of increasing load; the decrement happens only when memory
// is maxed out, during server shutdown, or (possibly in a future version)
// during decreasing load, so it is less performance-critical.
grpc::internal::Mutex callback_reqs_mu_;
grpc::internal::CondVar callback_reqs_done_cv_;
std::atomic_int callback_reqs_outstanding_{0};
std::shared_ptr<GlobalCallbacks> global_callbacks_;
std::vector<grpc::string> services_;
bool has_async_generic_service_{false};
bool has_callback_generic_service_{false};
// Pointer to the wrapped grpc_server.
grpc_server* server_;
std::unique_ptr<grpc_impl::ServerInitializer> server_initializer_;
std::unique_ptr<HealthCheckServiceInterface> health_check_service_;
bool health_check_service_disabled_;
// When appropriate, use a default callback generic service to handle
// unimplemented methods
std::unique_ptr<experimental::CallbackGenericService> unimplemented_service_;
// A special handler for resource exhausted in sync case
std::unique_ptr<internal::MethodHandler> resource_exhausted_handler_;
// Handler for callback generic service, if any
std::unique_ptr<internal::MethodHandler> generic_handler_;
// callback_cq_ references the callbackable completion queue associated
// with this server (if any). It is set on the first call to CallbackCQ().
// It is _not owned_ by the server; ownership belongs with its internal
// shutdown callback tag (invoked when the CQ is fully shutdown).
// It is protected by mu_
CompletionQueue* callback_cq_ = nullptr;
};
typedef ::grpc_impl::Server Server;
} // namespace grpc

@ -31,6 +31,7 @@
#include <grpcpp/impl/codegen/server_interceptor.h>
#include <grpcpp/impl/server_builder_option.h>
#include <grpcpp/impl/server_builder_plugin.h>
#include <grpcpp/server.h>
#include <grpcpp/support/config.h>
struct grpc_resource_quota;
@ -39,13 +40,13 @@ namespace grpc_impl {
class CompletionQueue;
class ResourceQuota;
class Server;
class ServerCompletionQueue;
class ServerCredentials;
} // namespace grpc_impl
namespace grpc {
class AsyncGenericService;
class Server;
class Service;
namespace testing {

@ -27,7 +27,9 @@
#include <grpc/compression.h>
#include <grpc/support/atm.h>
#include <grpcpp/channel.h>
#include <grpcpp/completion_queue.h>
#include <grpcpp/health_check_service_interface.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/impl/codegen/grpc_library.h>
@ -49,7 +51,6 @@ class ServerContext;
namespace grpc_impl {
class HealthCheckServiceInterface;
class ServerInitializer;
/// Represents a gRPC server.
@ -99,7 +100,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
grpc_server* c_server();
/// Returns the health check service.
grpc_impl::HealthCheckServiceInterface* GetHealthCheckService() const {
grpc::HealthCheckServiceInterface* GetHealthCheckService() const {
return health_check_service_.get();
}
@ -333,7 +334,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
std::unique_ptr<grpc_impl::ServerInitializer> server_initializer_;
std::unique_ptr<grpc_impl::HealthCheckServiceInterface> health_check_service_;
std::unique_ptr<grpc::HealthCheckServiceInterface> health_check_service_;
bool health_check_service_disabled_;
// When appropriate, use a default callback generic service to handle

@ -66,12 +66,13 @@
#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
// Conversion between subchannel call and call stack.
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \
(grpc_call_stack*)((char*)(call) + \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)))
#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \
(SubchannelCall*)(((char*)(call_stack)) - \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)))
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \
(grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE( \
sizeof(SubchannelCall)))
#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \
(SubchannelCall*)(((char*)(call_stack)) - \
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE( \
sizeof(SubchannelCall)))
namespace grpc_core {
@ -151,10 +152,10 @@ RefCountedPtr<SubchannelCall> ConnectedSubchannel::CreateCall(
size_t ConnectedSubchannel::GetInitialCallSizeEstimate(
size_t parent_data_size) const {
size_t allocation_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(SubchannelCall));
if (parent_data_size > 0) {
allocation_size +=
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
parent_data_size;
} else {
allocation_size += channel_stack_->call_stack_size;
@ -178,8 +179,9 @@ void SubchannelCall::StartTransportStreamOpBatch(
void* SubchannelCall::GetParentData() {
grpc_channel_stack* chanstk = connected_subchannel_->channel_stack();
return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size);
return (char*)this +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(chanstk->call_stack_size);
}
grpc_call_stack* SubchannelCall::GetCallStack() {

@ -47,9 +47,9 @@ grpc_core::TraceFlag grpc_trace_channel(false, "channel");
size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
size_t filter_count) {
/* always need the header, and size for the channel elements */
size_t size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
sizeof(grpc_channel_element));
size_t size = GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(
filter_count * sizeof(grpc_channel_element));
size_t i;
GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
@ -57,18 +57,18 @@ size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
/* add the size for each filter */
for (i = 0; i < filter_count; i++) {
size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
size += GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
}
return size;
}
#define CHANNEL_ELEMS_FROM_STACK(stk) \
((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
#define CHANNEL_ELEMS_FROM_STACK(stk) \
((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE( \
sizeof(grpc_channel_stack))))
#define CALL_ELEMS_FROM_STACK(stk) \
((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
#define CALL_ELEMS_FROM_STACK(stk) \
((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE( \
sizeof(grpc_call_stack))))
grpc_channel_element* grpc_channel_stack_element(
@ -92,8 +92,9 @@ grpc_error* grpc_channel_stack_init(
const grpc_channel_args* channel_args, grpc_transport* optional_transport,
const char* name, grpc_channel_stack* stack) {
size_t call_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(filter_count *
sizeof(grpc_call_element));
grpc_channel_element* elems;
grpc_channel_element_args args;
char* user_data;
@ -104,8 +105,8 @@ grpc_error* grpc_channel_stack_init(
name);
elems = CHANNEL_ELEMS_FROM_STACK(stack);
user_data = (reinterpret_cast<char*>(elems)) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
sizeof(grpc_channel_element));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(filter_count *
sizeof(grpc_channel_element));
/* init per-filter data */
grpc_error* first_error = GRPC_ERROR_NONE;
@ -126,8 +127,9 @@ grpc_error* grpc_channel_stack_init(
}
}
user_data +=
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
call_size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
call_size +=
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
}
GPR_ASSERT(user_data > (char*)stack);
@ -162,8 +164,9 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy,
destroy_arg, "CALL_STACK");
call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
user_data = (reinterpret_cast<char*>(call_elems)) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
user_data =
(reinterpret_cast<char*>(call_elems)) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
/* init per-filter data */
grpc_error* first_error = GRPC_ERROR_NONE;
@ -171,8 +174,8 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data;
user_data +=
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
user_data += GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(
call_elems[i].filter->sizeof_call_data);
}
for (size_t i = 0; i < count; i++) {
grpc_error* error =
@ -242,11 +245,11 @@ grpc_channel_stack* grpc_channel_stack_from_top_element(
grpc_channel_element* elem) {
return reinterpret_cast<grpc_channel_stack*>(
reinterpret_cast<char*>(elem) -
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
}
grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
return reinterpret_cast<grpc_call_stack*>(
reinterpret_cast<char*>(elem) -
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
}

@ -23,6 +23,7 @@
#include <grpc/support/log.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/profiling/timers.h"
static void* zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }
@ -33,8 +34,56 @@ static void* zalloc_with_gpr_malloc(size_t sz) {
return p;
}
static gpr_allocation_functions g_alloc_functions = {malloc, zalloc_with_calloc,
realloc, free};
#ifndef NDEBUG
static constexpr bool is_power_of_two(size_t value) {
// 2^N = 100000...000
// 2^N - 1 = 011111...111
// (2^N) && ((2^N)-1)) = 0
return (value & (value - 1)) == 0;
}
#endif
static void* platform_malloc_aligned(size_t size, size_t alignment) {
#if defined(GPR_HAS_ALIGNED_ALLOC)
GPR_DEBUG_ASSERT(is_power_of_two(alignment));
size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size, alignment);
void* ret = aligned_alloc(alignment, size);
GPR_ASSERT(ret != nullptr);
return ret;
#elif defined(GPR_HAS_ALIGNED_MALLOC)
GPR_DEBUG_ASSERT(is_power_of_two(alignment));
void* ret = _aligned_malloc(size, alignment);
GPR_ASSERT(ret != nullptr);
return ret;
#elif defined(GPR_HAS_POSIX_MEMALIGN)
GPR_DEBUG_ASSERT(is_power_of_two(alignment));
GPR_DEBUG_ASSERT(alignment % sizeof(void*) == 0);
void* ret = nullptr;
GPR_ASSERT(posix_memalign(&ret, alignment, size) == 0);
return ret;
#else
GPR_DEBUG_ASSERT(is_power_of_two(alignment));
size_t extra = alignment - 1 + sizeof(void*);
void* p = gpr_malloc(size + extra);
void** ret = (void**)(((uintptr_t)p + extra) & ~(alignment - 1));
ret[-1] = p;
return (void*)ret;
#endif
}
static void platform_free_aligned(void* ptr) {
#if defined(GPR_HAS_ALIGNED_ALLOC) || defined(GPR_HAS_POSIX_MEMALIGN)
free(ptr);
#elif defined(GPR_HAS_ALIGNED_MALLOC)
_aligned_free(ptr);
#else
gpr_free((static_cast<void**>(ptr))[-1]);
#endif
}
static gpr_allocation_functions g_alloc_functions = {
malloc, zalloc_with_calloc, realloc,
free, platform_malloc_aligned, platform_free_aligned};
gpr_allocation_functions gpr_get_allocation_functions() {
return g_alloc_functions;
@ -47,6 +96,12 @@ void gpr_set_allocation_functions(gpr_allocation_functions functions) {
if (functions.zalloc_fn == nullptr) {
functions.zalloc_fn = zalloc_with_gpr_malloc;
}
GPR_ASSERT((functions.aligned_alloc_fn == nullptr) ==
(functions.aligned_free_fn == nullptr));
if (functions.aligned_alloc_fn == nullptr) {
functions.aligned_alloc_fn = platform_malloc_aligned;
functions.aligned_free_fn = platform_free_aligned;
}
g_alloc_functions = functions;
}
@ -88,12 +143,12 @@ void* gpr_realloc(void* p, size_t size) {
}
void* gpr_malloc_aligned(size_t size, size_t alignment) {
GPR_ASSERT(((alignment - 1) & alignment) == 0); // Must be power of 2.
size_t extra = alignment - 1 + sizeof(void*);
void* p = gpr_malloc(size + extra);
void** ret = (void**)(((uintptr_t)p + extra) & ~(alignment - 1));
ret[-1] = p;
return (void*)ret;
GPR_TIMER_SCOPE("gpr_malloc_aligned", 0);
if (size == 0) return nullptr;
return g_alloc_functions.aligned_alloc_fn(size, alignment);
}
void gpr_free_aligned(void* ptr) { gpr_free((static_cast<void**>(ptr))[-1]); }
void gpr_free_aligned(void* ptr) {
GPR_TIMER_SCOPE("gpr_free_aligned", 0);
g_alloc_functions.aligned_free_fn(ptr);
}

@ -22,7 +22,13 @@
#include <grpc/support/port_platform.h>
/// Given a size, round up to the next multiple of sizeof(void*).
#define GPR_ROUND_UP_TO_ALIGNMENT_SIZE(x) \
(((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
#define GPR_ROUND_UP_TO_ALIGNMENT_SIZE(x, align) \
(((x) + (align)-1u) & ~((align)-1u))
#define GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(x) \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE((x), GPR_MAX_ALIGNMENT)
#define GPR_ROUND_UP_TO_CACHELINE_SIZE(x) \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE((x), GPR_CACHELINE_SIZE)
#endif /* GRPC_CORE_LIB_GPR_ALLOC_H */

@ -35,8 +35,8 @@ namespace {
void* ArenaStorage(size_t initial_size) {
static constexpr size_t base_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_core::Arena));
initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_core::Arena));
initial_size = GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(initial_size);
size_t alloc_size = base_size + initial_size;
static constexpr size_t alignment =
(GPR_CACHELINE_SIZE > GPR_MAX_ALIGNMENT &&
@ -67,7 +67,7 @@ Arena* Arena::Create(size_t initial_size) {
Pair<Arena*, void*> Arena::CreateWithAlloc(size_t initial_size,
size_t alloc_size) {
static constexpr size_t base_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Arena));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(Arena));
auto* new_arena =
new (ArenaStorage(initial_size)) Arena(initial_size, alloc_size);
void* first_alloc = reinterpret_cast<char*>(new_arena) + base_size;
@ -88,7 +88,7 @@ void* Arena::AllocZone(size_t size) {
// sizing hysteresis (that is, most calls should have a large enough initial
// zone and will not need to grow the arena).
static constexpr size_t zone_base_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Zone));
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(Zone));
size_t alloc_size = zone_base_size + size;
Zone* z = new (gpr_malloc_aligned(alloc_size, GPR_MAX_ALIGNMENT)) Zone();
{

@ -58,10 +58,10 @@ class Arena {
// Allocate \a size bytes from the arena.
void* Alloc(size_t size) {
static constexpr size_t base_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Arena));
size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size);
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(Arena));
size = GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(size);
size_t begin = total_used_.FetchAdd(size, MemoryOrder::RELAXED);
if (begin + size <= initial_zone_size_) {
if (GPR_LIKELY(begin + size <= initial_zone_size_)) {
return reinterpret_cast<char*>(this) + base_size + begin;
} else {
return AllocZone(size);

@ -271,16 +271,8 @@ static void notify_on_write(grpc_tcp* tcp) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p notify_on_write", tcp);
}
if (grpc_event_engine_run_in_background()) {
// If there is a polling engine always running in the background, there is
// no need to run the backup poller.
GRPC_CLOSURE_INIT(&tcp->write_done_closure, tcp_handle_write, tcp,
grpc_schedule_on_exec_ctx);
} else {
if (!grpc_event_engine_run_in_background()) {
cover_self(tcp);
GRPC_CLOSURE_INIT(&tcp->write_done_closure,
tcp_drop_uncovered_then_handle_write, tcp,
grpc_schedule_on_exec_ctx);
}
grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_done_closure);
}
@ -884,8 +876,6 @@ static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) {
* ready. */
grpc_fd_set_readable(tcp->em_fd);
grpc_fd_set_writable(tcp->em_fd);
GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure);
}
@ -1248,6 +1238,16 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
tcp->tb_head = nullptr;
GRPC_CLOSURE_INIT(&tcp->read_done_closure, tcp_handle_read, tcp,
grpc_schedule_on_exec_ctx);
if (grpc_event_engine_run_in_background()) {
// If there is a polling engine always running in the background, there is
// no need to run the backup poller.
GRPC_CLOSURE_INIT(&tcp->write_done_closure, tcp_handle_write, tcp,
grpc_schedule_on_exec_ctx);
} else {
GRPC_CLOSURE_INIT(&tcp->write_done_closure,
tcp_drop_uncovered_then_handle_write, tcp,
grpc_schedule_on_exec_ctx);
}
/* Always assume there is something on the queue to read. */
tcp->inq = 1;
#ifdef GRPC_HAVE_TCP_INQ

@ -260,10 +260,10 @@ grpc_core::TraceFlag grpc_compression_trace(false, "compression");
#define CALL_STACK_FROM_CALL(call) \
(grpc_call_stack*)((char*)(call) + \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_call)))
#define CALL_FROM_CALL_STACK(call_stack) \
(grpc_call*)(((char*)(call_stack)) - \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_call)))
#define CALL_ELEM_FROM_CALL(call, idx) \
grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
@ -329,7 +329,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
size_t initial_size = grpc_channel_get_call_size_estimate(args->channel);
GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
size_t call_and_stack_size =
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(grpc_call)) +
channel_stack->call_stack_size;
size_t call_alloc_size =
call_and_stack_size + (args->parent ? sizeof(child_call) : 0);

@ -211,7 +211,6 @@ void grpc_mdctx_global_shutdown() {
mdtab_shard* shard = &g_shards[i];
gpr_mu_destroy(&shard->mu);
gc_mdtab(shard);
/* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked",
shard->count);
@ -219,6 +218,7 @@ void grpc_mdctx_global_shutdown() {
abort();
}
}
GPR_DEBUG_ASSERT(shard->count == 0);
gpr_free(shard->elems);
}
}
@ -251,7 +251,9 @@ static void gc_mdtab(mdtab_shard* shard) {
GPR_TIMER_SCOPE("gc_mdtab", 0);
size_t num_freed = 0;
for (size_t i = 0; i < shard->capacity; ++i) {
num_freed += InternedMetadata::CleanupLinkedMetadata(&shard->elems[i]);
intptr_t freed = InternedMetadata::CleanupLinkedMetadata(&shard->elems[i]);
num_freed += freed;
shard->count -= freed;
}
gpr_atm_no_barrier_fetch_add(&shard->free_estimate,
-static_cast<intptr_t>(num_freed));

@ -115,7 +115,7 @@ void grpc_transport_move_stats(grpc_transport_stream_stats* from,
}
size_t grpc_transport_stream_size(grpc_transport* transport) {
return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(transport->vtable->sizeof_stream);
return GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(transport->vtable->sizeof_stream);
}
void grpc_transport_destroy(grpc_transport* transport) {

@ -106,15 +106,183 @@ class UnimplementedAsyncRequestContext {
} // namespace
ServerInterface::BaseAsyncRequest::BaseAsyncRequest(
ServerInterface* server, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
: server_(server),
context_(context),
stream_(stream),
call_cq_(call_cq),
notification_cq_(notification_cq),
tag_(tag),
delete_on_finalize_(delete_on_finalize),
call_(nullptr),
done_intercepting_(false) {
/* Set up interception state partially for the receive ops. call_wrapper_ is
* not filled at this point, but it will be filled before the interceptors are
* run. */
interceptor_methods_.SetCall(&call_wrapper_);
interceptor_methods_.SetReverse();
call_cq_->RegisterAvalanching(); // This op will trigger more ops
}
ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() {
call_cq_->CompleteAvalanching();
}
bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
bool* status) {
if (done_intercepting_) {
*tag = tag_;
if (delete_on_finalize_) {
delete this;
}
return true;
}
context_->set_call(call_);
context_->cq_ = call_cq_;
if (call_wrapper_.call() == nullptr) {
// Fill it since it is empty.
call_wrapper_ = internal::Call(
call_, server_, call_cq_, server_->max_receive_message_size(), nullptr);
}
// just the pointers inside call are copied here
stream_->BindCall(&call_wrapper_);
if (*status && call_ && call_wrapper_.server_rpc_info()) {
done_intercepting_ = true;
// Set interception point for RECV INITIAL METADATA
interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
interceptor_methods_.SetRecvInitialMetadata(&context_->client_metadata_);
if (interceptor_methods_.RunInterceptors(
[this]() { ContinueFinalizeResultAfterInterception(); })) {
// There are no interceptors to run. Continue
} else {
// There were interceptors to be run, so
// ContinueFinalizeResultAfterInterception will be run when interceptors
// are done.
return false;
}
}
if (*status && call_) {
context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
}
*tag = tag_;
if (delete_on_finalize_) {
delete this;
}
return true;
}
void ServerInterface::BaseAsyncRequest::
ContinueFinalizeResultAfterInterception() {
context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
// Queue a tag which will be returned immediately
grpc_core::ExecCtx exec_ctx;
grpc_cq_begin_op(notification_cq_->cq(), this);
grpc_cq_end_op(
notification_cq_->cq(), this, GRPC_ERROR_NONE,
[](void* arg, grpc_cq_completion* completion) { delete completion; },
nullptr, new grpc_cq_completion());
}
ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
ServerInterface* server, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, const char* name,
internal::RpcMethod::RpcType type)
: BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
true),
name_(name),
type_(type) {}
void ServerInterface::RegisteredAsyncRequest::IssueRequest(
void* registered_method, grpc_byte_buffer** payload,
ServerCompletionQueue* notification_cq) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call(
server_->server(), registered_method, &call_,
&context_->deadline_,
context_->client_metadata_.arr(), payload,
call_cq_->cq(), notification_cq->cq(), this));
}
ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
ServerInterface* server, GenericServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
: BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
delete_on_finalize) {
grpc_call_details_init(&call_details_);
GPR_ASSERT(notification_cq);
GPR_ASSERT(call_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
server->server(), &call_, &call_details_,
context->client_metadata_.arr(), call_cq->cq(),
notification_cq->cq(), this));
}
bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
bool* status) {
// If we are done intercepting, there is nothing more for us to do
if (done_intercepting_) {
return BaseAsyncRequest::FinalizeResult(tag, status);
}
// TODO(yangg) remove the copy here.
if (*status) {
static_cast<GenericServerContext*>(context_)->method_ =
StringFromCopiedSlice(call_details_.method);
static_cast<GenericServerContext*>(context_)->host_ =
StringFromCopiedSlice(call_details_.host);
context_->deadline_ = call_details_.deadline;
}
grpc_slice_unref(call_details_.method);
grpc_slice_unref(call_details_.host);
call_wrapper_ = internal::Call(
call_, server_, call_cq_, server_->max_receive_message_size(),
context_->set_server_rpc_info(
static_cast<GenericServerContext*>(context_)->method_.c_str(),
internal::RpcMethod::BIDI_STREAMING,
*server_->interceptor_creators()));
return BaseAsyncRequest::FinalizeResult(tag, status);
}
namespace {
class ShutdownCallback : public grpc_experimental_completion_queue_functor {
public:
ShutdownCallback() { functor_run = &ShutdownCallback::Run; }
// TakeCQ takes ownership of the cq into the shutdown callback
// so that the shutdown callback will be responsible for destroying it
void TakeCQ(CompletionQueue* cq) { cq_ = cq; }
// The Run function will get invoked by the completion queue library
// when the shutdown is actually complete
static void Run(grpc_experimental_completion_queue_functor* cb, int) {
auto* callback = static_cast<ShutdownCallback*>(cb);
delete callback->cq_;
delete callback;
}
private:
CompletionQueue* cq_ = nullptr;
};
} // namespace
} // namespace grpc
namespace grpc_impl {
/// Use private inheritance rather than composition only to establish order
/// of construction, since the public base class should be constructed after the
/// elements belonging to the private base class are constructed. This is not
/// possible using true composition.
class Server::UnimplementedAsyncRequest final
: private UnimplementedAsyncRequestContext,
: private grpc::UnimplementedAsyncRequestContext,
public GenericAsyncRequest {
public:
UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq)
UnimplementedAsyncRequest(Server* server, grpc::ServerCompletionQueue* cq)
: GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq,
nullptr, false),
server_(server),
@ -122,27 +290,29 @@ class Server::UnimplementedAsyncRequest final
bool FinalizeResult(void** tag, bool* status) override;
ServerContext* context() { return &server_context_; }
GenericServerAsyncReaderWriter* stream() { return &generic_stream_; }
grpc::ServerContext* context() { return &server_context_; }
grpc::GenericServerAsyncReaderWriter* stream() { return &generic_stream_; }
private:
Server* const server_;
ServerCompletionQueue* const cq_;
grpc::ServerCompletionQueue* const cq_;
};
/// UnimplementedAsyncResponse should not post user-visible completions to the
/// C++ completion queue, but is generated as a CQ event by the core
class Server::UnimplementedAsyncResponse final
: public internal::CallOpSet<internal::CallOpSendInitialMetadata,
internal::CallOpServerSendStatus> {
: public grpc::internal::CallOpSet<
grpc::internal::CallOpSendInitialMetadata,
grpc::internal::CallOpServerSendStatus> {
public:
UnimplementedAsyncResponse(UnimplementedAsyncRequest* request);
~UnimplementedAsyncResponse() { delete request_; }
bool FinalizeResult(void** tag, bool* status) override {
if (internal::CallOpSet<
internal::CallOpSendInitialMetadata,
internal::CallOpServerSendStatus>::FinalizeResult(tag, status)) {
if (grpc::internal::CallOpSet<
grpc::internal::CallOpSendInitialMetadata,
grpc::internal::CallOpServerSendStatus>::FinalizeResult(tag,
status)) {
delete this;
} else {
// The tag was swallowed due to interception. We will see it again.
@ -154,15 +324,16 @@ class Server::UnimplementedAsyncResponse final
UnimplementedAsyncRequest* const request_;
};
class Server::SyncRequest final : public internal::CompletionQueueTag {
class Server::SyncRequest final : public grpc::internal::CompletionQueueTag {
public:
SyncRequest(internal::RpcServiceMethod* method, void* method_tag)
SyncRequest(grpc::internal::RpcServiceMethod* method, void* method_tag)
: method_(method),
method_tag_(method_tag),
in_flight_(false),
has_request_payload_(
method->method_type() == internal::RpcMethod::NORMAL_RPC ||
method->method_type() == internal::RpcMethod::SERVER_STREAMING),
has_request_payload_(method->method_type() ==
grpc::internal::RpcMethod::NORMAL_RPC ||
method->method_type() ==
grpc::internal::RpcMethod::SERVER_STREAMING),
call_details_(nullptr),
cq_(nullptr) {
grpc_metadata_array_init(&request_metadata_);
@ -273,7 +444,8 @@ class Server::SyncRequest final : public internal::CompletionQueueTag {
interceptor_methods_.SetReverse();
// Set interception point for RECV INITIAL METADATA
interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
grpc::experimental::InterceptionHookPoints::
POST_RECV_INITIAL_METADATA);
interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_);
if (has_request_payload_) {
@ -285,7 +457,7 @@ class Server::SyncRequest final : public internal::CompletionQueueTag {
request_payload_ = nullptr;
interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
interceptor_methods_.SetRecvMessage(request_, nullptr);
}
@ -304,40 +476,40 @@ class Server::SyncRequest final : public internal::CompletionQueueTag {
global_callbacks_->PreSynchronousRequest(&ctx_);
auto* handler = resources_ ? method_->handler()
: server_->resource_exhausted_handler_.get();
handler->RunHandler(internal::MethodHandler::HandlerParameter(
handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter(
&call_, &ctx_, request_, request_status_, nullptr, nullptr));
request_ = nullptr;
global_callbacks_->PostSynchronousRequest(&ctx_);
cq_.Shutdown();
internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag();
grpc::internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag();
cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME));
/* Ensure the cq_ is shutdown */
DummyTag ignored_tag;
grpc::DummyTag ignored_tag;
GPR_ASSERT(cq_.Pluck(&ignored_tag) == false);
}
delete this;
}
private:
CompletionQueue cq_;
ServerContext ctx_;
grpc::CompletionQueue cq_;
grpc::ServerContext ctx_;
const bool has_request_payload_;
grpc_byte_buffer* request_payload_;
void* request_;
Status request_status_;
internal::RpcServiceMethod* const method_;
internal::Call call_;
grpc::Status request_status_;
grpc::internal::RpcServiceMethod* const method_;
grpc::internal::Call call_;
Server* server_;
std::shared_ptr<GlobalCallbacks> global_callbacks_;
bool resources_;
internal::InterceptorBatchMethodsImpl interceptor_methods_;
grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_;
};
private:
internal::RpcServiceMethod* const method_;
grpc::internal::RpcServiceMethod* const method_;
void* const method_tag_;
bool in_flight_;
const bool has_request_payload_;
@ -349,7 +521,7 @@ class Server::SyncRequest final : public internal::CompletionQueueTag {
grpc_completion_queue* cq_;
};
class Server::CallbackRequestBase : public internal::CompletionQueueTag {
class Server::CallbackRequestBase : public grpc::internal::CompletionQueueTag {
public:
virtual ~CallbackRequestBase() {}
virtual bool Request() = 0;
@ -358,7 +530,7 @@ class Server::CallbackRequestBase : public internal::CompletionQueueTag {
template <class ServerContextType>
class Server::CallbackRequest final : public Server::CallbackRequestBase {
public:
static_assert(std::is_base_of<ServerContext, ServerContextType>::value,
static_assert(std::is_base_of<grpc::ServerContext, ServerContextType>::value,
"ServerContextType must be derived from ServerContext");
// The constructor needs to know the server for this callback request and its
@ -368,15 +540,16 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
// requested. For generic services, method and method_tag are nullptr since
// these services don't have pre-defined methods or method registration tags.
CallbackRequest(Server* server, size_t method_idx,
internal::RpcServiceMethod* method, void* method_tag)
grpc::internal::RpcServiceMethod* method, void* method_tag)
: server_(server),
method_index_(method_idx),
method_(method),
method_tag_(method_tag),
has_request_payload_(
method_ != nullptr &&
(method->method_type() == internal::RpcMethod::NORMAL_RPC ||
method->method_type() == internal::RpcMethod::SERVER_STREAMING)),
(method->method_type() == grpc::internal::RpcMethod::NORMAL_RPC ||
method->method_type() ==
grpc::internal::RpcMethod::SERVER_STREAMING)),
cq_(server->CallbackCQ()),
tag_(this) {
server_->callback_reqs_outstanding_++;
@ -440,7 +613,7 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
private:
Server::CallbackRequest<ServerContextType>* req_;
internal::Call* call_;
grpc::internal::Call* call_;
static void StaticRun(grpc_experimental_completion_queue_functor* cb,
int ok) {
@ -491,21 +664,24 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
req_->request_metadata_.count = 0;
// Create a C++ Call to control the underlying core call
call_ = new (grpc_call_arena_alloc(req_->call_, sizeof(internal::Call)))
internal::Call(req_->call_, req_->server_, req_->cq_,
req_->server_->max_receive_message_size(),
req_->ctx_.set_server_rpc_info(
req_->method_name(),
(req_->method_ != nullptr)
? req_->method_->method_type()
: internal::RpcMethod::BIDI_STREAMING,
req_->server_->interceptor_creators_));
call_ =
new (grpc_call_arena_alloc(req_->call_, sizeof(grpc::internal::Call)))
grpc::internal::Call(
req_->call_, req_->server_, req_->cq_,
req_->server_->max_receive_message_size(),
req_->ctx_.set_server_rpc_info(
req_->method_name(),
(req_->method_ != nullptr)
? req_->method_->method_type()
: grpc::internal::RpcMethod::BIDI_STREAMING,
req_->server_->interceptor_creators_));
req_->interceptor_methods_.SetCall(call_);
req_->interceptor_methods_.SetReverse();
// Set interception point for RECV INITIAL METADATA
req_->interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
grpc::experimental::InterceptionHookPoints::
POST_RECV_INITIAL_METADATA);
req_->interceptor_methods_.SetRecvInitialMetadata(
&req_->ctx_.client_metadata_);
@ -516,7 +692,7 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
&req_->handler_data_);
req_->request_payload_ = nullptr;
req_->interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr);
}
@ -532,7 +708,7 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
auto* handler = (req_->method_ != nullptr)
? req_->method_->handler()
: req_->server_->generic_handler_.get();
handler->RunHandler(internal::MethodHandler::HandlerParameter(
handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter(
call_, &req_->ctx_, req_->request_, req_->request_status_,
req_->handler_data_, [this] {
// Recycle this request if there aren't too many outstanding.
@ -580,41 +756,41 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
request_payload_ = nullptr;
request_ = nullptr;
handler_data_ = nullptr;
request_status_ = Status();
request_status_ = grpc::Status();
}
Server* const server_;
const size_t method_index_;
internal::RpcServiceMethod* const method_;
grpc::internal::RpcServiceMethod* const method_;
void* const method_tag_;
const bool has_request_payload_;
grpc_byte_buffer* request_payload_;
void* request_;
void* handler_data_;
Status request_status_;
grpc::Status request_status_;
grpc_call_details* call_details_ = nullptr;
grpc_call* call_;
gpr_timespec deadline_;
grpc_metadata_array request_metadata_;
CompletionQueue* cq_;
grpc::CompletionQueue* cq_;
CallbackCallTag tag_;
ServerContextType ctx_;
internal::InterceptorBatchMethodsImpl interceptor_methods_;
grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_;
};
template <>
bool Server::CallbackRequest<ServerContext>::FinalizeResult(void** tag,
bool* status) {
bool Server::CallbackRequest<grpc::ServerContext>::FinalizeResult(
void** tag, bool* status) {
return false;
}
template <>
bool Server::CallbackRequest<GenericServerContext>::FinalizeResult(
bool Server::CallbackRequest<grpc::GenericServerContext>::FinalizeResult(
void** tag, bool* status) {
if (*status) {
// TODO(yangg) remove the copy here
ctx_.method_ = StringFromCopiedSlice(call_details_->method);
ctx_.host_ = StringFromCopiedSlice(call_details_->host);
ctx_.method_ = grpc::StringFromCopiedSlice(call_details_->method);
ctx_.host_ = grpc::StringFromCopiedSlice(call_details_->host);
}
grpc_slice_unref(call_details_->method);
grpc_slice_unref(call_details_->host);
@ -622,21 +798,22 @@ bool Server::CallbackRequest<GenericServerContext>::FinalizeResult(
}
template <>
const char* Server::CallbackRequest<ServerContext>::method_name() const {
const char* Server::CallbackRequest<grpc::ServerContext>::method_name() const {
return method_->name();
}
template <>
const char* Server::CallbackRequest<GenericServerContext>::method_name() const {
const char* Server::CallbackRequest<grpc::GenericServerContext>::method_name()
const {
return ctx_.method().c_str();
}
// Implementation of ThreadManager. Each instance of SyncRequestThreadManager
// manages a pool of threads that poll for incoming Sync RPCs and call the
// appropriate RPC handlers
class Server::SyncRequestThreadManager : public ThreadManager {
class Server::SyncRequestThreadManager : public grpc::ThreadManager {
public:
SyncRequestThreadManager(Server* server, CompletionQueue* server_cq,
SyncRequestThreadManager(Server* server, grpc::CompletionQueue* server_cq,
std::shared_ptr<GlobalCallbacks> global_callbacks,
grpc_resource_quota* rq, int min_pollers,
int max_pollers, int cq_timeout_msec)
@ -655,11 +832,11 @@ class Server::SyncRequestThreadManager : public ThreadManager {
gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN));
switch (server_cq_->AsyncNext(tag, ok, deadline)) {
case CompletionQueue::TIMEOUT:
case grpc::CompletionQueue::TIMEOUT:
return TIMEOUT;
case CompletionQueue::SHUTDOWN:
case grpc::CompletionQueue::SHUTDOWN:
return SHUTDOWN;
case CompletionQueue::GOT_EVENT:
case grpc::CompletionQueue::GOT_EVENT:
return WORK_FOUND;
}
@ -694,15 +871,15 @@ class Server::SyncRequestThreadManager : public ThreadManager {
// object
}
void AddSyncMethod(internal::RpcServiceMethod* method, void* tag) {
void AddSyncMethod(grpc::internal::RpcServiceMethod* method, void* tag) {
sync_requests_.emplace_back(new SyncRequest(method, tag));
}
void AddUnknownSyncMethod() {
if (!sync_requests_.empty()) {
unknown_method_.reset(new internal::RpcServiceMethod(
"unknown", internal::RpcMethod::BIDI_STREAMING,
new internal::UnknownMethodHandler));
unknown_method_.reset(new grpc::internal::RpcServiceMethod(
"unknown", grpc::internal::RpcMethod::BIDI_STREAMING,
new grpc::internal::UnknownMethodHandler));
sync_requests_.emplace_back(
new SyncRequest(unknown_method_.get(), nullptr));
}
@ -746,22 +923,22 @@ class Server::SyncRequestThreadManager : public ThreadManager {
private:
Server* server_;
CompletionQueue* server_cq_;
grpc::CompletionQueue* server_cq_;
int cq_timeout_msec_;
std::vector<std::unique_ptr<SyncRequest>> sync_requests_;
std::unique_ptr<internal::RpcServiceMethod> unknown_method_;
std::unique_ptr<grpc::internal::RpcServiceMethod> unknown_method_;
std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
};
static internal::GrpcLibraryInitializer g_gli_initializer;
static grpc::internal::GrpcLibraryInitializer g_gli_initializer;
Server::Server(
int max_receive_message_size, ChannelArguments* args,
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
int max_receive_message_size, grpc::ChannelArguments* args,
std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
sync_server_cqs,
int min_pollers, int max_pollers, int sync_cq_timeout_msec,
grpc_resource_quota* server_rq,
std::vector<
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>
std::unique_ptr<grpc::experimental::ServerInterceptorFactoryInterface>>
interceptor_creators)
: interceptor_creators_(std::move(interceptor_creators)),
max_receive_message_size_(max_receive_message_size),
@ -773,8 +950,8 @@ Server::Server(
server_initializer_(new grpc_impl::ServerInitializer(this)),
health_check_service_disabled_(false) {
g_gli_initializer.summon();
gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
global_callbacks_ = g_callbacks;
gpr_once_init(&grpc::g_once_init_callbacks, grpc::InitGlobalCallbacks);
global_callbacks_ = grpc::g_callbacks;
global_callbacks_->UpdateArguments(args);
if (sync_server_cqs_ != nullptr) {
@ -801,13 +978,14 @@ Server::Server(
args->SetChannelArgs(&channel_args);
for (size_t i = 0; i < channel_args.num_args; i++) {
if (0 ==
strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) {
if (0 == strcmp(channel_args.args[i].key,
grpc::kHealthCheckServiceInterfaceArg)) {
if (channel_args.args[i].value.pointer.p == nullptr) {
health_check_service_disabled_ = true;
} else {
health_check_service_.reset(static_cast<HealthCheckServiceInterface*>(
channel_args.args[i].value.pointer.p));
health_check_service_.reset(
static_cast<grpc::HealthCheckServiceInterface*>(
channel_args.args[i].value.pointer.p));
}
break;
}
@ -844,49 +1022,49 @@ Server::~Server() {
}
void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
GPR_ASSERT(!g_callbacks);
GPR_ASSERT(!grpc::g_callbacks);
GPR_ASSERT(callbacks);
g_callbacks.reset(callbacks);
grpc::g_callbacks.reset(callbacks);
}
grpc_server* Server::c_server() { return server_; }
std::shared_ptr<Channel> Server::InProcessChannel(
const ChannelArguments& args) {
std::shared_ptr<grpc::Channel> Server::InProcessChannel(
const grpc::ChannelArguments& args) {
grpc_channel_args channel_args = args.c_channel_args();
return ::grpc::CreateChannelInternal(
return grpc::CreateChannelInternal(
"inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr),
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>());
}
std::shared_ptr<Channel>
std::shared_ptr<grpc::Channel>
Server::experimental_type::InProcessChannelWithInterceptors(
const ChannelArguments& args,
const grpc::ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
grpc_channel_args channel_args = args.c_channel_args();
return ::grpc::CreateChannelInternal(
return grpc::CreateChannelInternal(
"inproc",
grpc_inproc_channel_create(server_->server_, &channel_args, nullptr),
std::move(interceptor_creators));
}
static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
internal::RpcServiceMethod* method) {
grpc::internal::RpcServiceMethod* method) {
switch (method->method_type()) {
case internal::RpcMethod::NORMAL_RPC:
case internal::RpcMethod::SERVER_STREAMING:
case grpc::internal::RpcMethod::NORMAL_RPC:
case grpc::internal::RpcMethod::SERVER_STREAMING:
return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
case internal::RpcMethod::CLIENT_STREAMING:
case internal::RpcMethod::BIDI_STREAMING:
case grpc::internal::RpcMethod::CLIENT_STREAMING:
case grpc::internal::RpcMethod::BIDI_STREAMING:
return GRPC_SRM_PAYLOAD_NONE;
}
GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
}
bool Server::RegisterService(const grpc::string* host, Service* service) {
bool Server::RegisterService(const grpc::string* host, grpc::Service* service) {
bool has_async_methods = service->has_async_methods();
if (has_async_methods) {
GPR_ASSERT(service->server_ == nullptr &&
@ -902,7 +1080,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
continue;
}
internal::RpcServiceMethod* method = it->get();
grpc::internal::RpcServiceMethod* method = it->get();
void* method_registration_tag = grpc_server_register_method(
server_, method->name(), host ? host->c_str() : nullptr,
PayloadHandlingForMethod(method), 0);
@ -915,7 +1093,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
if (method->handler() == nullptr) { // Async method without handler
method->set_server_tag(method_registration_tag);
} else if (method->api_type() ==
internal::RpcServiceMethod::ApiType::SYNC) {
grpc::internal::RpcServiceMethod::ApiType::SYNC) {
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->AddSyncMethod(method, method_registration_tag);
}
@ -925,8 +1103,9 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
auto method_index = callback_unmatched_reqs_count_.size() - 1;
// TODO(vjpai): Register these dynamically based on need
for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
callback_reqs_to_start_.push_back(new CallbackRequest<ServerContext>(
this, method_index, method, method_registration_tag));
callback_reqs_to_start_.push_back(
new CallbackRequest<grpc::ServerContext>(this, method_index, method,
method_registration_tag));
}
// Enqueue it so that it will be Request'ed later after all request
// matchers are created at core server startup
@ -947,7 +1126,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
return true;
}
void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
void Server::RegisterAsyncGenericService(grpc::AsyncGenericService* service) {
GPR_ASSERT(service->server_ == nullptr &&
"Can only register an async generic service against one server.");
service->server_ = this;
@ -955,7 +1134,7 @@ void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
}
void Server::RegisterCallbackGenericService(
experimental::CallbackGenericService* service) {
grpc::experimental::CallbackGenericService* service) {
GPR_ASSERT(
service->server_ == nullptr &&
"Can only register a callback generic service against one server.");
@ -967,44 +1146,45 @@ void Server::RegisterCallbackGenericService(
auto method_index = callback_unmatched_reqs_count_.size() - 1;
// TODO(vjpai): Register these dynamically based on need
for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
callback_reqs_to_start_.push_back(new CallbackRequest<GenericServerContext>(
this, method_index, nullptr, nullptr));
callback_reqs_to_start_.push_back(
new CallbackRequest<grpc::GenericServerContext>(this, method_index,
nullptr, nullptr));
}
}
int Server::AddListeningPort(const grpc::string& addr,
ServerCredentials* creds) {
grpc::ServerCredentials* creds) {
GPR_ASSERT(!started_);
int port = creds->AddPortToServer(addr, server_);
global_callbacks_->AddPort(this, addr, creds, port);
return port;
}
void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
GPR_ASSERT(!started_);
global_callbacks_->PreServerStart(this);
started_ = true;
// Only create default health check service when user did not provide an
// explicit one.
ServerCompletionQueue* health_check_cq = nullptr;
DefaultHealthCheckService::HealthCheckServiceImpl*
grpc::ServerCompletionQueue* health_check_cq = nullptr;
grpc::DefaultHealthCheckService::HealthCheckServiceImpl*
default_health_check_service_impl = nullptr;
if (health_check_service_ == nullptr && !health_check_service_disabled_ &&
DefaultHealthCheckServiceEnabled()) {
auto* default_hc_service = new DefaultHealthCheckService;
grpc::DefaultHealthCheckServiceEnabled()) {
auto* default_hc_service = new grpc::DefaultHealthCheckService;
health_check_service_.reset(default_hc_service);
// We create a non-polling CQ to avoid impacting application
// performance. This ensures that we don't introduce thread hops
// for application requests that wind up on this CQ, which is polled
// in its own thread.
health_check_cq =
new ServerCompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr);
health_check_cq = new grpc::ServerCompletionQueue(
GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr);
grpc_server_register_completion_queue(server_, health_check_cq->cq(),
nullptr);
default_health_check_service_impl =
default_hc_service->GetHealthCheckService(
std::unique_ptr<ServerCompletionQueue>(health_check_cq));
std::unique_ptr<grpc::ServerCompletionQueue>(health_check_cq));
RegisterService(nullptr, default_health_check_service_impl);
}
@ -1012,7 +1192,8 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
// service to handle any unimplemented methods using the default reactor
// creator
if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) {
unimplemented_service_.reset(new experimental::CallbackGenericService);
unimplemented_service_.reset(
new grpc::experimental::CallbackGenericService);
RegisterCallbackGenericService(unimplemented_service_.get());
}
@ -1037,7 +1218,8 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
// server CQs), make sure that we have a ResourceExhausted handler
// to deal with the case of thread exhaustion
if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) {
resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler);
resource_exhausted_handler_.reset(
new grpc::internal::ResourceExhaustedHandler);
}
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
@ -1063,20 +1245,20 @@ void Server::ShutdownInternal(gpr_timespec deadline) {
shutdown_ = true;
/// The completion queue to use for server shutdown completion notification
CompletionQueue shutdown_cq;
ShutdownTag shutdown_tag; // Dummy shutdown tag
grpc::CompletionQueue shutdown_cq;
grpc::ShutdownTag shutdown_tag; // Dummy shutdown tag
grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag);
shutdown_cq.Shutdown();
void* tag;
bool ok;
CompletionQueue::NextStatus status =
grpc::CompletionQueue::NextStatus status =
shutdown_cq.AsyncNext(&tag, &ok, deadline);
// If this timed out, it means we are done with the grace period for a clean
// shutdown. We should force a shutdown now by cancelling all inflight calls
if (status == CompletionQueue::NextStatus::TIMEOUT) {
if (status == grpc::CompletionQueue::NextStatus::TIMEOUT) {
grpc_server_cancel_all_calls(server_);
}
// Else in case of SHUTDOWN or GOT_EVENT, it means that the server has
@ -1128,154 +1310,11 @@ void Server::Wait() {
}
}
void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops,
internal::Call* call) {
void Server::PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops,
grpc::internal::Call* call) {
ops->FillOps(call);
}
ServerInterface::BaseAsyncRequest::BaseAsyncRequest(
ServerInterface* server, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
: server_(server),
context_(context),
stream_(stream),
call_cq_(call_cq),
notification_cq_(notification_cq),
tag_(tag),
delete_on_finalize_(delete_on_finalize),
call_(nullptr),
done_intercepting_(false) {
/* Set up interception state partially for the receive ops. call_wrapper_ is
* not filled at this point, but it will be filled before the interceptors are
* run. */
interceptor_methods_.SetCall(&call_wrapper_);
interceptor_methods_.SetReverse();
call_cq_->RegisterAvalanching(); // This op will trigger more ops
}
ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() {
call_cq_->CompleteAvalanching();
}
bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
bool* status) {
if (done_intercepting_) {
*tag = tag_;
if (delete_on_finalize_) {
delete this;
}
return true;
}
context_->set_call(call_);
context_->cq_ = call_cq_;
if (call_wrapper_.call() == nullptr) {
// Fill it since it is empty.
call_wrapper_ = internal::Call(
call_, server_, call_cq_, server_->max_receive_message_size(), nullptr);
}
// just the pointers inside call are copied here
stream_->BindCall(&call_wrapper_);
if (*status && call_ && call_wrapper_.server_rpc_info()) {
done_intercepting_ = true;
// Set interception point for RECV INITIAL METADATA
interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
interceptor_methods_.SetRecvInitialMetadata(&context_->client_metadata_);
if (interceptor_methods_.RunInterceptors(
[this]() { ContinueFinalizeResultAfterInterception(); })) {
// There are no interceptors to run. Continue
} else {
// There were interceptors to be run, so
// ContinueFinalizeResultAfterInterception will be run when interceptors
// are done.
return false;
}
}
if (*status && call_) {
context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
}
*tag = tag_;
if (delete_on_finalize_) {
delete this;
}
return true;
}
void ServerInterface::BaseAsyncRequest::
ContinueFinalizeResultAfterInterception() {
context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
// Queue a tag which will be returned immediately
grpc_core::ExecCtx exec_ctx;
grpc_cq_begin_op(notification_cq_->cq(), this);
grpc_cq_end_op(
notification_cq_->cq(), this, GRPC_ERROR_NONE,
[](void* arg, grpc_cq_completion* completion) { delete completion; },
nullptr, new grpc_cq_completion());
}
ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
ServerInterface* server, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, const char* name,
internal::RpcMethod::RpcType type)
: BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
true),
name_(name),
type_(type) {}
void ServerInterface::RegisteredAsyncRequest::IssueRequest(
void* registered_method, grpc_byte_buffer** payload,
ServerCompletionQueue* notification_cq) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call(
server_->server(), registered_method, &call_,
&context_->deadline_,
context_->client_metadata_.arr(), payload,
call_cq_->cq(), notification_cq->cq(), this));
}
ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
ServerInterface* server, GenericServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
: BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
delete_on_finalize) {
grpc_call_details_init(&call_details_);
GPR_ASSERT(notification_cq);
GPR_ASSERT(call_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
server->server(), &call_, &call_details_,
context->client_metadata_.arr(), call_cq->cq(),
notification_cq->cq(), this));
}
bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
bool* status) {
// If we are done intercepting, there is nothing more for us to do
if (done_intercepting_) {
return BaseAsyncRequest::FinalizeResult(tag, status);
}
// TODO(yangg) remove the copy here.
if (*status) {
static_cast<GenericServerContext*>(context_)->method_ =
StringFromCopiedSlice(call_details_.method);
static_cast<GenericServerContext*>(context_)->host_ =
StringFromCopiedSlice(call_details_.host);
context_->deadline_ = call_details_.deadline;
}
grpc_slice_unref(call_details_.method);
grpc_slice_unref(call_details_.host);
call_wrapper_ = internal::Call(
call_, server_, call_cq_, server_->max_receive_message_size(),
context_->set_server_rpc_info(
static_cast<GenericServerContext*>(context_)->method_.c_str(),
internal::RpcMethod::BIDI_STREAMING,
*server_->interceptor_creators()));
return BaseAsyncRequest::FinalizeResult(tag, status);
}
bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag,
bool* status) {
if (GenericAsyncRequest::FinalizeResult(tag, status)) {
@ -1295,41 +1334,22 @@ bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag,
Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse(
UnimplementedAsyncRequest* request)
: request_(request) {
Status status(StatusCode::UNIMPLEMENTED, "");
internal::UnknownMethodHandler::FillOps(request_->context(), this);
grpc::Status status(grpc::StatusCode::UNIMPLEMENTED, "");
grpc::internal::UnknownMethodHandler::FillOps(request_->context(), this);
request_->stream()->call_.PerformOps(this);
}
ServerInitializer* Server::initializer() { return server_initializer_.get(); }
namespace {
class ShutdownCallback : public grpc_experimental_completion_queue_functor {
public:
ShutdownCallback() { functor_run = &ShutdownCallback::Run; }
// TakeCQ takes ownership of the cq into the shutdown callback
// so that the shutdown callback will be responsible for destroying it
void TakeCQ(CompletionQueue* cq) { cq_ = cq; }
// The Run function will get invoked by the completion queue library
// when the shutdown is actually complete
static void Run(grpc_experimental_completion_queue_functor* cb, int) {
auto* callback = static_cast<ShutdownCallback*>(cb);
delete callback->cq_;
delete callback;
}
private:
CompletionQueue* cq_ = nullptr;
};
} // namespace
grpc::ServerInitializer* Server::initializer() {
return server_initializer_.get();
}
CompletionQueue* Server::CallbackCQ() {
grpc::CompletionQueue* Server::CallbackCQ() {
// TODO(vjpai): Consider using a single global CQ for the default CQ
// if there is no explicit per-server CQ registered
grpc::internal::MutexLock l(&mu_);
if (callback_cq_ == nullptr) {
auto* shutdown_callback = new ShutdownCallback;
callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{
auto* shutdown_callback = new grpc::ShutdownCallback;
callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING,
shutdown_callback});
@ -1339,4 +1359,4 @@ CompletionQueue* Server::CallbackCQ() {
return callback_cq_;
}
} // namespace grpc
} // namespace grpc_impl

@ -31,12 +31,21 @@ static void fake_free(void* addr) {
*(static_cast<intptr_t*>(addr)) = static_cast<intptr_t>(0xdeadd00d);
}
static void* fake_aligned_malloc(size_t size, size_t alignment) {
return (void*)(size + alignment);
}
static void fake_aligned_free(void* addr) {
*(static_cast<intptr_t*>(addr)) = static_cast<intptr_t>(0xcafef00d);
}
static void test_custom_allocs() {
const gpr_allocation_functions default_fns = gpr_get_allocation_functions();
intptr_t addr_to_free = 0;
char* i;
gpr_allocation_functions fns = {fake_malloc, nullptr, fake_realloc,
fake_free};
gpr_allocation_functions fns = {fake_malloc, nullptr,
fake_realloc, fake_free,
fake_aligned_malloc, fake_aligned_free};
gpr_set_allocation_functions(fns);
GPR_ASSERT((void*)(size_t)0xdeadbeef == gpr_malloc(0xdeadbeef));
@ -45,6 +54,11 @@ static void test_custom_allocs() {
gpr_free(&addr_to_free);
GPR_ASSERT(addr_to_free == (intptr_t)0xdeadd00d);
GPR_ASSERT((void*)(size_t)(0xdeadbeef + 64) ==
gpr_malloc_aligned(0xdeadbeef, 64));
gpr_free_aligned(&addr_to_free);
GPR_ASSERT(addr_to_free == (intptr_t)0xcafef00d);
/* Restore and check we don't get funky values and that we don't leak */
gpr_set_allocation_functions(default_fns);
GPR_ASSERT((void*)sizeof(*i) !=

@ -54,9 +54,10 @@ static void* guard_malloc(size_t size) {
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1);
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, (gpr_atm)1);
void* ptr = g_old_allocs.malloc_fn(
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size)) + size);
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size)) + size);
*static_cast<size_t*>(ptr) = size;
return static_cast<char*>(ptr) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size));
return static_cast<char*>(ptr) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size));
}
static void* guard_realloc(void* vptr, size_t size) {
@ -67,31 +68,36 @@ static void* guard_realloc(void* vptr, size_t size) {
guard_free(vptr);
return nullptr;
}
void* ptr =
static_cast<char*>(vptr) - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size));
void* ptr = static_cast<char*>(vptr) -
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size));
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size);
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative,
-*static_cast<gpr_atm*>(ptr));
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size);
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1);
ptr = g_old_allocs.realloc_fn(
ptr, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size)) + size);
ptr, GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size)) + size);
*static_cast<size_t*>(ptr) = size;
return static_cast<char*>(ptr) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size));
return static_cast<char*>(ptr) +
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size));
}
static void guard_free(void* vptr) {
if (vptr == nullptr) return;
void* ptr =
static_cast<char*>(vptr) - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(size_t));
void* ptr = static_cast<char*>(vptr) -
GPR_ROUND_UP_TO_MAX_ALIGNMENT_SIZE(sizeof(size_t));
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative,
-*static_cast<gpr_atm*>(ptr));
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, -(gpr_atm)1);
g_old_allocs.free_fn(ptr);
}
struct gpr_allocation_functions g_guard_allocs = {guard_malloc, nullptr,
guard_realloc, guard_free};
// NB: We do not specify guard_malloc_aligned/guard_free_aligned methods. Since
// they are null, calls to gpr_malloc_aligned/gpr_free_aligned are executed as a
// wrapper over gpr_malloc/gpr_free, which do use guard_malloc/guard_free, and
// thus their allocations are tracked as well.
struct gpr_allocation_functions g_guard_allocs = {
guard_malloc, nullptr, guard_realloc, guard_free, nullptr, nullptr};
void grpc_memory_counters_init() {
memset(&g_memory_counters, 0, sizeof(g_memory_counters));

@ -21,6 +21,8 @@
#include <map>
#include <mutex>
#include <grpcpp/server.h>
#include "src/proto/grpc/testing/metrics.grpc.pb.h"
#include "src/proto/grpc/testing/metrics.pb.h"

@ -1017,6 +1017,7 @@ include/grpcpp/server.h \
include/grpcpp/server_builder.h \
include/grpcpp/server_builder_impl.h \
include/grpcpp/server_context.h \
include/grpcpp/server_impl.h \
include/grpcpp/server_posix.h \
include/grpcpp/server_posix_impl.h \
include/grpcpp/support/async_stream.h \

@ -1019,6 +1019,7 @@ include/grpcpp/server.h \
include/grpcpp/server_builder.h \
include/grpcpp/server_builder_impl.h \
include/grpcpp/server_context.h \
include/grpcpp/server_impl.h \
include/grpcpp/server_posix.h \
include/grpcpp/server_posix_impl.h \
include/grpcpp/support/async_stream.h \

@ -10185,6 +10185,7 @@
"include/grpcpp/server_builder.h",
"include/grpcpp/server_builder_impl.h",
"include/grpcpp/server_context.h",
"include/grpcpp/server_impl.h",
"include/grpcpp/server_posix.h",
"include/grpcpp/server_posix_impl.h",
"include/grpcpp/support/async_stream.h",
@ -10309,6 +10310,7 @@
"include/grpcpp/server_builder.h",
"include/grpcpp/server_builder_impl.h",
"include/grpcpp/server_context.h",
"include/grpcpp/server_impl.h",
"include/grpcpp/server_posix.h",
"include/grpcpp/server_posix_impl.h",
"include/grpcpp/support/async_stream.h",

Loading…
Cancel
Save