📄 apr_buckets.h
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */#ifndef APR_BUCKETS_H#define APR_BUCKETS_H#include "apu.h"#include "apr_network_io.h"#include "apr_file_io.h"#include "apr_general.h"#include "apr_mmap.h"#include "apr_errno.h"#include "apr_ring.h"#include "apr.h"#if APR_HAVE_SYS_UIO_H#include <sys/uio.h> /* for struct iovec */#endif#if APR_HAVE_STDARG_H#include <stdarg.h>#endif#ifdef __cplusplusextern "C" {#endif/** * @package Bucket Brigades */#define APR_BUCKET_BUFF_SIZE 8192typedef enum { APR_BLOCK_READ, APR_NONBLOCK_READ} apr_read_type_e;/* * The one-sentence buzzword-laden overview: Bucket brigades represent * a complex data stream that can be passed through a layered IO * system without unnecessary copying. A longer overview follows... * * A bucket brigade is a doubly linked list (ring) of buckets, so we * aren't limited to inserting at the front and removing at the end. * Buckets are only passed around as members of a brigade, although * singleton buckets can occur for short periods of time. * * Buckets are data stores of various types. They can refer to data in * memory, or part of a file or mmap area, or the output of a process, * etc. Buckets also have some type-dependent accessor functions: * read, split, copy, setaside, and destroy. * * read returns the address and size of the data in the bucket. If the * data isn't in memory then it is read in and the bucket changes type * so that it can refer to the new location of the data. If all the * data doesn't fit in the bucket then a new bucket is inserted into * the brigade to hold the rest of it. * * split divides the data in a bucket into two regions. After a split * the original bucket refers to the first part of the data and a new * bucket inserted into the brigade after the original bucket refers * to the second part of the data. Reference counts are maintained as * necessary. * * setaside ensures that the data in the bucket has a long enough * lifetime. Sometimes it is convenient to create a bucket referring * to data on the stack in the expectation that it will be consumed * (output to the network) before the stack is unwound. If that * expectation turns out not to be valid, the setaside function is * called to move the data somewhere safer. * * copy makes a duplicate of the bucket structure as long as it's * possible to have multiple references to a single copy of the * data itself. Not all bucket types can be copied. * * destroy maintains the reference counts on the resources used by a * bucket and frees them if necessary. * * Note: all of the above functions have wrapper macros (apr_bucket_read(), * apr_bucket_destroy(), etc), and those macros should be used rather * than using the function pointers directly. * * To write a bucket brigade, they are first made into an iovec, so that we * don't write too little data at one time. Currently we ignore compacting the * buckets into as few buckets as possible, but if we really want good * performance, then we need to compact the buckets before we convert to an * iovec, or possibly while we are converting to an iovec. *//** * Forward declaration of the main types. */typedef struct apr_bucket_brigade apr_bucket_brigade;typedef struct apr_bucket apr_bucket;typedef struct apr_bucket_type_t apr_bucket_type_t;struct apr_bucket_type_t { /** * The name of the bucket type */ const char *name; /** * The number of functions this bucket understands. Can not be less than * five. */ int num_func; /** * Free the private data and any resources used by the bucket * (if they aren't shared with another bucket). * @param data The private data pointer from the bucket to be destroyed */ void (*destroy)(void *data); /** * Read the data from the bucket. This is guaranteed to be implemented * for all bucket types. * @param b The bucket to read from * @param str A place to store the data read. Allocation should only be * done if absolutely necessary. * @param len The amount of data read. * @param block Should this read function block if there is more data that * cannot be read immediately. * @deffunc apr_status_t read(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block) */ apr_status_t (*read)(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block); /** * Make it possible to set aside the data. Buckets containing data that * dies when the stack is un-wound must convert the bucket into a heap * bucket. For most bucket types, though, this is a no-op and this * function will return APR_ENOTIMPL. * @param e The bucket to convert * @deffunc apr_status_t setaside(apr_bucket *e) */ apr_status_t (*setaside)(apr_bucket *e); /** * Split one bucket in two at the specified position by duplicating * the bucket structure (not the data) and modifying any necessary * start/end/offset information. If it's not possible to do this * for the bucket type (perhaps the length of the data is indeterminate, * as with pipe and socket buckets), then APR_ENOTIMPL is returned. * @param e The bucket to split * @param point The offset of the first byte in the new bucket * @deffunc apr_status_t split(apr_bucket *e, apr_off_t point) */ apr_status_t (*split)(apr_bucket *e, apr_off_t point); /** * Copy the bucket structure (not the data), assuming that this is * possible for the bucket type. If it's not, APR_ENOTIMPL is returned. * @param e The bucket to copy * @param c Returns a pointer to the new bucket * @deffunc apr_status_t copy */ apr_status_t (*copy)(apr_bucket *e, apr_bucket **c);};/** * apr_bucket structures are allocated on the malloc() heap and * their lifetime is controlled by the parent apr_bucket_brigade * structure. Buckets can move from one brigade to another e.g. by * calling apr_brigade_concat(). In general the data in a bucket has * the same lifetime as the bucket and is freed when the bucket is * destroyed; if the data is shared by more than one bucket (e.g. * after a split) the data is freed when the last bucket goes away. */struct apr_bucket { /** Links to the rest of the brigade */ APR_RING_ENTRY(apr_bucket) link; /** The type of bucket. */ const apr_bucket_type_t *type; /** The length of the data in the bucket. This could have been implemented * with a function, but this is an optimization, because the most * common thing to do will be to get the length. If the length is unknown, * the value of this field will be -1. */ apr_off_t length; /** The start of the data in the bucket relative to the private base * pointer. The vast majority of bucket types allow a fixed block of * data to be referenced by multiple buckets, each bucket pointing to * a different segment of the data. That segment starts at base+start * and ends at base+start+length. If length == -1, start == -1. */ apr_off_t start; /** type-dependent data hangs off this pointer */ void *data; };/** A list of buckets */struct apr_bucket_brigade { /** The pool to associate the brigade with. The data is not allocated out * of the pool, but a cleanup is registered with this pool. If the * brigade is destroyed by some mechanism other than pool destruction, * the destroying function is responsible for killing the cleanup. */ apr_pool_t *p; /** The buckets in the brigade are on this list. */ /* * The apr_bucket_list structure doesn't actually need a name tag * because it has no existence independent of struct apr_bucket_brigade; * the ring macros are designed so that you can leave the name tag * argument empty in this situation but apparently the Windows compiler * doesn't like that. */ APR_RING_HEAD(apr_bucket_list, apr_bucket) list;};typedef apr_status_t (*apr_brigade_flush)(apr_bucket_brigade *bb, void *ctx);/** * Wrappers around the RING macros to reduce the verbosity of the code * that handles bucket brigades. *//** * The magic pointer value that indicates the head of the brigade * @tip This is used to find the beginning and end of the brigade, eg: * <pre> * while (e != APR_BRIGADE_SENTINEL(b)) { * ... * e = APR_BUCKET_NEXT(e); * } * </pre> * @param b The brigade * @return The magic pointer value * @deffunc apr_bucket *APR_BRIGADE_SENTINEL(apr_bucket_brigade *b) */#define APR_BRIGADE_SENTINEL(b) APR_RING_SENTINEL(&(b)->list, apr_bucket, link)/** * Determine if the bucket brigade is empty * @param b The brigade to check * @return true or false * @deffunc int APR_BRIGADE_EMPTY(apr_bucket_brigade *b) */#define APR_BRIGADE_EMPTY(b) APR_RING_EMPTY(&(b)->list, apr_bucket, link)/** * Return the first bucket in a brigade * @param b The brigade to query * @return The first bucket in the brigade * @deffunc apr_bucket *APR_BUCKET_FIRST(apr_bucket_brigade *b) */#define APR_BRIGADE_FIRST(b) APR_RING_FIRST(&(b)->list)/** * Return the last bucket in a brigade * @param b The brigade to query * @return The last bucket in the brigade * @deffunc apr_bucket *APR_BUCKET_LAST(apr_bucket_brigade *b) */#define APR_BRIGADE_LAST(b) APR_RING_LAST(&(b)->list)/** * Iterate through a bucket brigade * @param e The current bucket * @param b The brigade to iterate over * @tip This is the same as either: * <pre> * e = APR_BUCKET_FIRST(b); * while (e != APR_BRIGADE_SENTINEL(b)) { * ...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -