1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#ifndef AWS_S3_BUFFER_POOL_H
#define AWS_S3_BUFFER_POOL_H
#include <aws/common/ref_count.h>
#include <aws/io/future.h>
#include <aws/s3/s3.h>
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
/**
* Generic memory pool interface.
* Allows consumers of aws-c-s3 to override how buffer allocation for part buffers is done.
* Refer to docs/memory_aware_request_execution.md for details on how default implementation works.
* WARNING: this is currently experimental feature and does not provide API stability guarantees so should be used with
* caution. At highlevel the flow is as follows:
* - crt scheduler queues up requests to be prepared
* - requests being prepared will try to reserve mem (i.e. obtain a ticket) and wait until they get it before proceeding
* - once mem is reserved requests will proceed with the pipeline
* - request will acquire buffer from the ticket when needed
* - ticket is released when request is done with the buffer
* Note: in some cases pipeline can stall if new buffer cannot be allocated (ex. async writes flow).
* In this case reserve request will indicate that not granting the ticket can block and buffer pool should try to
* allocate ticket right away (or wait and call waker when mem is allocated for the case of async writes).
* Note for custom pool implementations: Scheduler keeps track of all outstanding futures and will error them out when
* request is paused or cancelled. Its still fine for memory pool implementation to deliver ticket (it will just be
* released by future right away with no side effects) or just ignore the future if its already in error state.
*/
AWS_PUSH_SANE_WARNING_LEVEL
AWS_EXTERN_C_BEGIN
struct aws_s3_buffer_ticket;
/**
* aws_future<aws_s3_buffer_ticket*>
* Buffer ticket future used for reservations.
*/
AWS_FUTURE_T_POINTER_WITH_RELEASE_DECLARATION(aws_future_s3_buffer_ticket, struct aws_s3_buffer_ticket, AWS_S3_API)
/**
* Meta information about ticket reservation request.
*/
struct aws_s3_buffer_pool_reserve_meta {
/* client reserving the ticket. accounts for buffer pool being shared between clients. */
struct aws_s3_client *client;
/* meta request ticket is being reserved for. */
struct aws_s3_meta_request *meta_request;
/* size of the buffer to reserve. */
size_t size;
/* whether not granting reservation can result in request pipeline being blocked.
* Note: blocking is currently a terminal condition and that cannot be recovered from,
* i.e. meta request will be stuck and not make any process.
* As such buffer pool should either grant or error out reservation in sync.
* This scenario currently only occurs in the async_write flows. */
bool can_block;
};
struct aws_s3_buffer_ticket;
struct aws_s3_buffer_ticket_vtable {
/**
* Get buffer associated with the ticket.
* Note: can be called multiple times and the same buffer should be returned. In some cases ticket might not be
* claimed at all.
*/
struct aws_byte_buf (*claim)(struct aws_s3_buffer_ticket *ticket);
/* Implement below for custom ref count behavior. Alternatively set those to null and init the ref count. */
struct aws_s3_buffer_ticket *(*acquire)(struct aws_s3_buffer_ticket *ticket);
struct aws_s3_buffer_ticket *(*release)(struct aws_s3_buffer_ticket *ticket);
};
/**
* Polymorphic ticket.
*/
struct aws_s3_buffer_ticket {
struct aws_s3_buffer_ticket_vtable *vtable;
struct aws_ref_count ref_count;
void *impl;
};
AWS_S3_API struct aws_byte_buf aws_s3_buffer_ticket_claim(struct aws_s3_buffer_ticket *ticket);
AWS_S3_API struct aws_s3_buffer_ticket *aws_s3_buffer_ticket_acquire(struct aws_s3_buffer_ticket *ticket);
AWS_S3_API struct aws_s3_buffer_ticket *aws_s3_buffer_ticket_release(struct aws_s3_buffer_ticket *ticket);
struct aws_s3_buffer_pool;
struct aws_s3_buffer_pool_vtable {
/* Reserve a ticket. Returns a future that is granted whenever reservation can be made. */
struct aws_future_s3_buffer_ticket *(
*reserve)(struct aws_s3_buffer_pool *pool, struct aws_s3_buffer_pool_reserve_meta meta);
/**
* Trim the pool. This is mostly a suggestion, which pool can decide to ignore. Triggered by CRT when
* client has been idle for some time.
**/
void (*trim)(struct aws_s3_buffer_pool *pool);
/* Implement below for custom ref count behavior. Alternatively set those to null and init the ref count. */
struct aws_s3_buffer_pool *(*acquire)(struct aws_s3_buffer_pool *pool);
struct aws_s3_buffer_pool *(*release)(struct aws_s3_buffer_pool *pool);
};
/**
* Polymorphic buffer pool.
*/
struct aws_s3_buffer_pool {
struct aws_s3_buffer_pool_vtable *vtable;
struct aws_ref_count ref_count;
void *impl;
};
AWS_S3_API struct aws_future_s3_buffer_ticket *aws_s3_buffer_pool_reserve(
struct aws_s3_buffer_pool *buffer_pool,
struct aws_s3_buffer_pool_reserve_meta meta);
AWS_S3_API void aws_s3_buffer_pool_trim(struct aws_s3_buffer_pool *buffer_pool);
AWS_S3_API struct aws_s3_buffer_pool *aws_s3_buffer_pool_acquire(struct aws_s3_buffer_pool *buffer_pool);
AWS_S3_API struct aws_s3_buffer_pool *aws_s3_buffer_pool_release(struct aws_s3_buffer_pool *buffer_pool);
/**
* Buffer pool configuration options.
*/
struct aws_s3_buffer_pool_config {
struct aws_s3_client *client; /* Client creating the pool. */
size_t part_size; /* Default part size of the client. */
size_t max_part_size; /* Max part size configured on the client. */
size_t memory_limit; /* Memory limit set on the client. */
};
/**
* Factory to construct the pool for the given config. Passes along buffer related info configured on the client, which
* factory may ignore when considering how to construct pool.
* This implementation should fail if pool cannot be constructed for some reason (ex. if config params cannot be met),
* by logging failure reason, returning null and raising aws_error.
*/
typedef struct aws_s3_buffer_pool *(aws_s3_buffer_pool_factory_fn)(struct aws_allocator *allocator,
struct aws_s3_buffer_pool_config config,
void *user_data);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_S3_BUFFER_POOL_H */
|