File: s3_buffer_pool.h

package info (click to toggle)
aws-crt-python 0.28.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 78,428 kB
  • sloc: ansic: 437,955; python: 27,657; makefile: 5,855; sh: 4,289; ruby: 208; java: 82; perl: 73; cpp: 25; xml: 11
file content (150 lines) | stat: -rw-r--r-- 6,434 bytes parent folder | download
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 */