mirror of https://github.com/grpc/grpc.git
Reland resource quota work (#28017)
* Check if memory owner available prior to polling it
The transport may drop the memory owner during its destruction sequence
* tcp_fix
* Revert "Revert "New resource quota integration (#27643)" (#28014)"
This reverts commit 0ea2c37263
.
* clang-format
* fix-path
* fix
pull/28030/head
parent
901e72edc0
commit
a629c9a03e
141 changed files with 1790 additions and 3688 deletions
@ -0,0 +1,57 @@ |
|||||||
|
// Copyright 2021 The gRPC Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#ifndef GRPC_EVENT_ENGINE_MEMORY_REQUEST_H |
||||||
|
#define GRPC_EVENT_ENGINE_MEMORY_REQUEST_H |
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include <stddef.h> |
||||||
|
|
||||||
|
#include "absl/strings/string_view.h" |
||||||
|
|
||||||
|
namespace grpc_event_engine { |
||||||
|
namespace experimental { |
||||||
|
|
||||||
|
/// Reservation request - how much memory do we want to allocate?
|
||||||
|
class MemoryRequest { |
||||||
|
public: |
||||||
|
/// Request a fixed amount of memory.
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
MemoryRequest(size_t n) : min_(n), max_(n) {} |
||||||
|
/// Request a range of memory.
|
||||||
|
/// Requires: \a min <= \a max.
|
||||||
|
/// Requires: \a max <= max_size()
|
||||||
|
MemoryRequest(size_t min, size_t max) : min_(min), max_(max) {} |
||||||
|
|
||||||
|
/// Maximum allowable request size - hard coded to 1GB.
|
||||||
|
static constexpr size_t max_allowed_size() { return 1024 * 1024 * 1024; } |
||||||
|
|
||||||
|
/// Increase the size by \a amount.
|
||||||
|
/// Undefined behavior if min() + amount or max() + amount overflows.
|
||||||
|
MemoryRequest Increase(size_t amount) const { |
||||||
|
return MemoryRequest(min_ + amount, max_ + amount); |
||||||
|
} |
||||||
|
|
||||||
|
size_t min() const { return min_; } |
||||||
|
size_t max() const { return max_; } |
||||||
|
|
||||||
|
private: |
||||||
|
size_t min_; |
||||||
|
size_t max_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace experimental
|
||||||
|
} // namespace grpc_event_engine
|
||||||
|
|
||||||
|
#endif // GRPC_EVENT_ENGINE_MEMORY_REQUEST_H
|
@ -0,0 +1,45 @@ |
|||||||
|
// Copyright 2021 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef GRPC_CORE_LIB_GPRPP_CPP_IMPL_OF_H |
||||||
|
#define GRPC_CORE_LIB_GPRPP_CPP_IMPL_OF_H |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
// Declares CppType to be the backing implementation of CType.
|
||||||
|
// Use via the curiously recursive template:
|
||||||
|
// class Foo : public CppImplOf<Foo, grpc_foo> {};
|
||||||
|
// Provides casting methods each way.
|
||||||
|
// grpc_foo should be `typedef struct grpc_foo grpc_foo` and otherwise
|
||||||
|
// not defined.
|
||||||
|
template <typename CppType, typename CType> |
||||||
|
class CppImplOf { |
||||||
|
public: |
||||||
|
// Convert the C struct to C++
|
||||||
|
static CppType* FromC(CType* c_type) { |
||||||
|
return reinterpret_cast<CppType*>(c_type); |
||||||
|
} |
||||||
|
|
||||||
|
// Retrieve a c pointer (of the same ownership as this)
|
||||||
|
CType* c_ptr() { |
||||||
|
return reinterpret_cast<CType*>(static_cast<CppType*>(this)); |
||||||
|
} |
||||||
|
|
||||||
|
protected: |
||||||
|
~CppImplOf() = default; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif // GRPC_CORE_LIB_GPRPP_CPP_IMPL_OF_H
|
File diff suppressed because it is too large
Load Diff
@ -1,226 +0,0 @@ |
|||||||
/*
|
|
||||||
* |
|
||||||
* Copyright 2016 gRPC authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H |
|
||||||
#define GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H |
|
||||||
|
|
||||||
#include <grpc/support/port_platform.h> |
|
||||||
|
|
||||||
#include <grpc/grpc.h> |
|
||||||
|
|
||||||
#include "src/core/lib/debug/trace.h" |
|
||||||
#include "src/core/lib/iomgr/closure.h" |
|
||||||
|
|
||||||
/** \file Tracks resource usage against a pool.
|
|
||||||
|
|
||||||
The current implementation tracks only memory usage, but in the future |
|
||||||
this may be extended to (for example) threads and file descriptors. |
|
||||||
|
|
||||||
A grpc_resource_quota represents the pooled resources, and |
|
||||||
grpc_resource_user instances attach to the quota and consume those |
|
||||||
resources. They also offer a vector for reclamation: if we become |
|
||||||
resource constrained, grpc_resource_user instances are asked (in turn) to |
|
||||||
free up whatever they can so that the system as a whole can make progress. |
|
||||||
|
|
||||||
There are three kinds of reclamation that take place, in order of increasing |
|
||||||
invasiveness: |
|
||||||
- an internal reclamation, where cached resource at the resource user level |
|
||||||
is returned to the quota |
|
||||||
- a benign reclamation phase, whereby resources that are in use but are not |
|
||||||
helping anything make progress are reclaimed |
|
||||||
- a destructive reclamation, whereby resources that are helping something |
|
||||||
make progress may be enacted so that at least one part of the system can |
|
||||||
complete. |
|
||||||
|
|
||||||
Only one reclamation will be outstanding for a given quota at a given time. |
|
||||||
On each reclamation attempt, the kinds of reclamation are tried in order of |
|
||||||
increasing invasiveness, stopping at the first one that succeeds. Thus, on a |
|
||||||
given reclamation attempt, if internal and benign reclamation both fail, it |
|
||||||
will wind up doing a destructive reclamation. However, the next reclamation |
|
||||||
attempt may then be able to get what it needs via internal or benign |
|
||||||
reclamation, due to resources that may have been freed up by the destructive |
|
||||||
reclamation in the previous attempt. |
|
||||||
|
|
||||||
Future work will be to expose the current resource pressure so that back |
|
||||||
pressure can be applied to avoid reclamation phases starting. |
|
||||||
|
|
||||||
Resource users own references to resource quotas, and resource quotas |
|
||||||
maintain lists of users (which users arrange to leave before they are |
|
||||||
destroyed) */ |
|
||||||
|
|
||||||
extern grpc_core::TraceFlag grpc_resource_quota_trace; |
|
||||||
|
|
||||||
// TODO(juanlishen): This is a hack. We need to do real accounting instead of
|
|
||||||
// hard coding.
|
|
||||||
constexpr size_t GRPC_RESOURCE_QUOTA_CALL_SIZE = 15 * 1024; |
|
||||||
constexpr size_t GRPC_RESOURCE_QUOTA_CHANNEL_SIZE = 50 * 1024; |
|
||||||
constexpr size_t GRPC_SLICE_ALLOCATOR_MIN_ALLOCATE_SIZE = 256; |
|
||||||
constexpr size_t GRPC_SLICE_ALLOCATOR_MAX_ALLOCATE_SIZE = 4 * 1024 * 1024; |
|
||||||
|
|
||||||
grpc_resource_quota* grpc_resource_quota_ref_internal( |
|
||||||
grpc_resource_quota* resource_quota); |
|
||||||
void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota); |
|
||||||
grpc_resource_quota* grpc_resource_quota_from_channel_args( |
|
||||||
const grpc_channel_args* channel_args, bool create = true); |
|
||||||
|
|
||||||
/* Return a number indicating current memory pressure:
|
|
||||||
0.0 ==> no memory usage |
|
||||||
1.0 ==> maximum memory usage */ |
|
||||||
double grpc_resource_quota_get_memory_pressure( |
|
||||||
grpc_resource_quota* resource_quota); |
|
||||||
|
|
||||||
size_t grpc_resource_quota_peek_size(grpc_resource_quota* resource_quota); |
|
||||||
|
|
||||||
typedef struct grpc_resource_user grpc_resource_user; |
|
||||||
|
|
||||||
grpc_resource_user* grpc_resource_user_create( |
|
||||||
grpc_resource_quota* resource_quota, absl::string_view name); |
|
||||||
|
|
||||||
/* Returns a borrowed reference to the underlying resource quota for this
|
|
||||||
resource user. */ |
|
||||||
grpc_resource_quota* grpc_resource_user_quota( |
|
||||||
grpc_resource_user* resource_user); |
|
||||||
|
|
||||||
void grpc_resource_user_ref(grpc_resource_user* resource_user); |
|
||||||
void grpc_resource_user_unref(grpc_resource_user* resource_user); |
|
||||||
void grpc_resource_user_shutdown(grpc_resource_user* resource_user); |
|
||||||
|
|
||||||
/* Attempts to get quota from the resource_user to create 'thread_count' number
|
|
||||||
* of threads. Returns true if successful (i.e the caller is now free to create |
|
||||||
* 'thread_count' number of threads) or false if quota is not available */ |
|
||||||
bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, |
|
||||||
int thread_count); |
|
||||||
/* Releases 'thread_count' worth of quota back to the resource user. The quota
|
|
||||||
* should have been previously obtained successfully by calling |
|
||||||
* grpc_resource_user_allocate_threads(). |
|
||||||
* |
|
||||||
* Note: There need not be an exact one-to-one correspondence between |
|
||||||
* grpc_resource_user_allocate_threads() and grpc_resource_user_free_threads() |
|
||||||
* calls. The only requirement is that the number of threads allocated should |
|
||||||
* all be eventually released */ |
|
||||||
void grpc_resource_user_free_threads(grpc_resource_user* resource_user, |
|
||||||
int thread_count); |
|
||||||
|
|
||||||
/* Allocates from the resource user 'size' worth of memory if this won't exceed
|
|
||||||
* the resource quota's total size. Returns whether the allocation is done |
|
||||||
* successfully. If allocated successfully, the memory should be freed by the |
|
||||||
* caller eventually. */ |
|
||||||
bool grpc_resource_user_safe_alloc(grpc_resource_user* resource_user, |
|
||||||
size_t size); |
|
||||||
/* Allocates from the resource user 'size' worth of memory.
|
|
||||||
* If optional_on_done is NULL, then allocate immediately. This may push the |
|
||||||
* quota over-limit, at which point reclamation will kick in. The caller is |
|
||||||
* always responsible to free the memory eventually. |
|
||||||
* Returns true if the allocation was successful. Otherwise, if optional_on_done |
|
||||||
* is non-NULL, it will be scheduled without error when the allocation has been |
|
||||||
* granted by the quota, and the caller is responsible to free the memory |
|
||||||
* eventually. Or it may be scheduled with an error, in which case the caller |
|
||||||
* fails to allocate the memory and shouldn't free the memory. |
|
||||||
*/ |
|
||||||
bool grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, |
|
||||||
grpc_closure* optional_on_done) |
|
||||||
GRPC_MUST_USE_RESULT; |
|
||||||
/* Release memory back to the quota */ |
|
||||||
void grpc_resource_user_free(grpc_resource_user* resource_user, size_t size); |
|
||||||
/* Post a memory reclaimer to the resource user. Only one benign and one
|
|
||||||
destructive reclaimer can be posted at once. When executed, the reclaimer |
|
||||||
MUST call grpc_resource_user_finish_reclamation before it completes, to |
|
||||||
return control to the resource quota. */ |
|
||||||
void grpc_resource_user_post_reclaimer(grpc_resource_user* resource_user, |
|
||||||
bool destructive, grpc_closure* closure); |
|
||||||
/* Finish a reclamation step */ |
|
||||||
void grpc_resource_user_finish_reclamation(grpc_resource_user* resource_user); |
|
||||||
|
|
||||||
/* Helper to allocate slices from a resource user */ |
|
||||||
typedef struct grpc_slice_allocator { |
|
||||||
/* Closure for when a resource user allocation completes */ |
|
||||||
grpc_closure on_allocated; |
|
||||||
/* Closure to call when slices have been allocated */ |
|
||||||
grpc_closure on_done; |
|
||||||
/* Length of slices to allocate on the current request */ |
|
||||||
size_t length; |
|
||||||
/* Number of slices to allocate on the current request */ |
|
||||||
size_t count; |
|
||||||
/* Minimum size to allocate under memory pressure. */ |
|
||||||
size_t min_length; |
|
||||||
/* Maximum size that can be allocated. */ |
|
||||||
size_t max_length; |
|
||||||
/* Destination for slices to allocate on the current request */ |
|
||||||
grpc_slice_buffer* dest; |
|
||||||
/* Parent resource user */ |
|
||||||
grpc_resource_user* resource_user; |
|
||||||
} grpc_slice_allocator; |
|
||||||
|
|
||||||
/// Constructs a slice allocator using configuration from \a args.
|
|
||||||
///
|
|
||||||
/// Minimum and maximum limits for memory allocation size can be defined in
|
|
||||||
/// \a args, and used to configure an allocator. See
|
|
||||||
/// \a grpc_slice_allocator_allocate for details on how those values are used.
|
|
||||||
///
|
|
||||||
/// Caller is responsible for calling \a grpc_slice_allocator_destroy.
|
|
||||||
grpc_slice_allocator* grpc_slice_allocator_create( |
|
||||||
grpc_resource_quota* resource_quota, absl::string_view name, |
|
||||||
const grpc_channel_args* args = nullptr); |
|
||||||
|
|
||||||
/* Cleans up after a slice_allocator. */ |
|
||||||
void grpc_slice_allocator_destroy(grpc_slice_allocator* slice_allocator); |
|
||||||
|
|
||||||
enum class grpc_slice_allocator_intent { |
|
||||||
kDefault, // Default intent allocates exactly the memory required.
|
|
||||||
kReadBuffer // ReadBuffer intent may return a smaller slice than requested if
|
|
||||||
// memory pressure is high.
|
|
||||||
}; |
|
||||||
|
|
||||||
/** Allocate \a count slices of length \a length into \a dest. Only one request
|
|
||||||
can be outstanding at a time. When an allocation is completed, calls \a cb |
|
||||||
with arg \a p. Returns whether the slice was allocated inline in the |
|
||||||
function. If true, the \a cb will not be called. The \a intent argument |
|
||||||
allows allocation of smaller slices if memory pressure is high; the size is |
|
||||||
implementation-dependent. */ |
|
||||||
bool grpc_slice_allocator_allocate(grpc_slice_allocator* slice_allocator, |
|
||||||
size_t length, size_t count, |
|
||||||
grpc_slice_allocator_intent intent, |
|
||||||
grpc_slice_buffer* dest, |
|
||||||
grpc_iomgr_cb_func cb, |
|
||||||
void* p) GRPC_MUST_USE_RESULT; |
|
||||||
|
|
||||||
/* Allows creation of slice_allocators (thus resource_users) without calling
|
|
||||||
* code having to understand resource_user concepts. */ |
|
||||||
typedef struct grpc_slice_allocator_factory { |
|
||||||
/* Parent resource quota */ |
|
||||||
grpc_resource_quota* resource_quota; |
|
||||||
} grpc_slice_allocator_factory; |
|
||||||
|
|
||||||
/* Constructs a slice allocator factory. Takes ownership of a ref on
|
|
||||||
* \a resource_quota from the caller. Caller is responsible for calling \a |
|
||||||
* grpc_slice_allocator_factory_destroy. */ |
|
||||||
grpc_slice_allocator_factory* grpc_slice_allocator_factory_create( |
|
||||||
grpc_resource_quota* resource_quota); |
|
||||||
|
|
||||||
/* Cleans up after a slice_allocator. */ |
|
||||||
void grpc_slice_allocator_factory_destroy( |
|
||||||
grpc_slice_allocator_factory* slice_allocator_factory); |
|
||||||
|
|
||||||
/** A factory method to create and initialize a slice_allocator using the
|
|
||||||
factory's resource quota. \a name is the resulting resource_user name. \a args |
|
||||||
are used to configure the \a slice_allocator */ |
|
||||||
grpc_slice_allocator* grpc_slice_allocator_factory_create_slice_allocator( |
|
||||||
grpc_slice_allocator_factory* slice_allocator_factory, |
|
||||||
absl::string_view name, grpc_channel_args* args = nullptr); |
|
||||||
|
|
||||||
#endif /* GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H */ |
|
@ -0,0 +1,102 @@ |
|||||||
|
// Copyright 2021 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/resource_quota/api.h" |
||||||
|
|
||||||
|
#include <grpc/grpc.h> |
||||||
|
|
||||||
|
#include "src/core/lib/gpr/useful.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
ResourceQuotaRefPtr ResourceQuotaFromChannelArgs( |
||||||
|
const grpc_channel_args* args) { |
||||||
|
return grpc_channel_args_find_pointer<ResourceQuota>(args, |
||||||
|
GRPC_ARG_RESOURCE_QUOTA) |
||||||
|
->Ref(); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
grpc_arg MakeArg(ResourceQuota* quota) { |
||||||
|
return grpc_channel_arg_pointer_create( |
||||||
|
const_cast<char*>(GRPC_ARG_RESOURCE_QUOTA), quota, |
||||||
|
grpc_resource_quota_arg_vtable()); |
||||||
|
} |
||||||
|
} // namespace
|
||||||
|
|
||||||
|
grpc_channel_args* EnsureResourceQuotaInChannelArgs( |
||||||
|
const grpc_channel_args* args) { |
||||||
|
if (grpc_channel_args_find(args, GRPC_ARG_RESOURCE_QUOTA) != nullptr) { |
||||||
|
return grpc_channel_args_copy(args); |
||||||
|
} |
||||||
|
// If there's no existing quota, add it to the default one - shared between
|
||||||
|
// all channel args declared thusly. This prevents us from accidentally not
|
||||||
|
// sharing subchannels due to their channel args not specifying a quota.
|
||||||
|
auto new_arg = MakeArg(ResourceQuota::Default().get()); |
||||||
|
return grpc_channel_args_copy_and_add(args, &new_arg, 1); |
||||||
|
} |
||||||
|
|
||||||
|
grpc_channel_args* ChannelArgsWrappingResourceQuota( |
||||||
|
ResourceQuotaRefPtr resource_quota) { |
||||||
|
auto new_arg = MakeArg(resource_quota.get()); |
||||||
|
return grpc_channel_args_copy_and_add(nullptr, &new_arg, 1); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
extern "C" const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable() { |
||||||
|
static const grpc_arg_pointer_vtable vtable = { |
||||||
|
// copy
|
||||||
|
[](void* p) -> void* { |
||||||
|
return static_cast<grpc_core::ResourceQuota*>(p)->Ref().release(); |
||||||
|
}, |
||||||
|
// destroy
|
||||||
|
[](void* p) { static_cast<grpc_core::ResourceQuota*>(p)->Unref(); }, |
||||||
|
// compare
|
||||||
|
[](void* p, void* q) { return grpc_core::QsortCompare(p, q); }}; |
||||||
|
return &vtable; |
||||||
|
} |
||||||
|
|
||||||
|
extern "C" grpc_resource_quota* grpc_resource_quota_create(const char* name) { |
||||||
|
static std::atomic<uintptr_t> anonymous_counter{0}; |
||||||
|
std::string quota_name = |
||||||
|
name == nullptr |
||||||
|
? absl::StrCat("anonymous-quota-", anonymous_counter.fetch_add(1)) |
||||||
|
: name; |
||||||
|
return (new grpc_core::ResourceQuota(std::move(quota_name)))->c_ptr(); |
||||||
|
} |
||||||
|
|
||||||
|
extern "C" void grpc_resource_quota_ref(grpc_resource_quota* resource_quota) { |
||||||
|
grpc_core::ResourceQuota::FromC(resource_quota)->Ref().release(); |
||||||
|
} |
||||||
|
|
||||||
|
extern "C" void grpc_resource_quota_unref(grpc_resource_quota* resource_quota) { |
||||||
|
grpc_core::ResourceQuota::FromC(resource_quota)->Unref(); |
||||||
|
} |
||||||
|
|
||||||
|
extern "C" void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, |
||||||
|
size_t new_size) { |
||||||
|
grpc_core::ResourceQuota::FromC(resource_quota) |
||||||
|
->memory_quota() |
||||||
|
->SetSize(new_size); |
||||||
|
} |
||||||
|
|
||||||
|
extern "C" void grpc_resource_quota_set_max_threads( |
||||||
|
grpc_resource_quota* resource_quota, int new_max_threads) { |
||||||
|
grpc_core::ResourceQuota::FromC(resource_quota) |
||||||
|
->thread_quota() |
||||||
|
->SetMax(new_max_threads); |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
// Copyright 2021 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef GRPC_CORE_LIB_RESOURCE_QUOTA_API_H |
||||||
|
#define GRPC_CORE_LIB_RESOURCE_QUOTA_API_H |
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_args.h" |
||||||
|
#include "src/core/lib/resource_quota/resource_quota.h" |
||||||
|
|
||||||
|
typedef struct grpc_resource_quota grpc_resource_quota; |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
// TODO(ctiller): This is a hack. We need to do real accounting instead of
|
||||||
|
// hard coding.
|
||||||
|
constexpr size_t kResourceQuotaCallSize = 15 * 1024; |
||||||
|
constexpr size_t kResourceQuotaChannelSize = 50 * 1024; |
||||||
|
|
||||||
|
// Retrieve the resource quota from the channel args.
|
||||||
|
// UB if not set.
|
||||||
|
ResourceQuotaRefPtr ResourceQuotaFromChannelArgs(const grpc_channel_args* args); |
||||||
|
|
||||||
|
// Take some channel args:
|
||||||
|
// If there is a resource quota set, copy args and return that.
|
||||||
|
// If there is no resource quota set, set a default, and return new
|
||||||
|
// channel args. Call grpc_channel_args_destroy on the input args.
|
||||||
|
grpc_channel_args* EnsureResourceQuotaInChannelArgs( |
||||||
|
const grpc_channel_args* args); |
||||||
|
|
||||||
|
// Create channel args with just the passed in resource quota
|
||||||
|
grpc_channel_args* ChannelArgsWrappingResourceQuota(ResourceQuotaRefPtr); |
||||||
|
|
||||||
|
inline ResourceQuota* ResourceQuotaFromC(grpc_resource_quota* quota) { |
||||||
|
return reinterpret_cast<ResourceQuota*>(quota); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif // GRPC_CORE_LIB_RESOURCE_QUOTA_API_H
|
@ -0,0 +1,19 @@ |
|||||||
|
// Copyright 2021 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/resource_quota/trace.h" |
||||||
|
|
||||||
|
grpc_core::TraceFlag grpc_resource_quota_trace(false, "resource_quota"); |
@ -0,0 +1,33 @@ |
|||||||
|
// Copyright 2021 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/core/lib/gprpp/cpp_impl_of.h" |
||||||
|
|
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
typedef struct grpc_foo grpc_foo; |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
namespace { |
||||||
|
class Foo : public CppImplOf<Foo, grpc_foo> {}; |
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(CppImplOfTest, CreateDestroy) { delete Foo::FromC((new Foo())->c_ptr()); } |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
::testing::InitGoogleTest(&argc, argv); |
||||||
|
return RUN_ALL_TESTS(); |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue