You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by rb...@covalent.net on 2000/07/01 19:04:41 UTC

bucket brigades.

OK.

This is a VERY rough first pass at bucket brigades as I understand
them.  If this is incorrect, then it is my implementation, not the design
IMHO.  

What does this implement?
	ap_bucket_brigade
	ap_bucket_list
	ap_bucket
	ap_bucket_rwmeme

None of this is complete.  This compiles cleanly, but it has never
actually been run.  As I have said, there are bugs.  This patch is just a
very small start to what it needs to become.  It is a total of 523
lines.  Much of that is comments.  It should be relatively easy to
review.  If you have a hard time with any of it, please let me know where
more comments are needed.

This patch has grown from some stuff Dean did a while ago, and from one of
Roy's messages.  There may be some cruft left in it, but I am working on
removing that.  This patch is progressing VERY slowly because I am
considering things VERY carefully before I write them.  If you want to
take this and move it along faster, please feel free.  If you plan to wait
for me, plan to wait until at least late next week for a VERY minimal
patch.

This code doesn't touch the core AT ALL.  All this does is start to
implement a few types.  I will commit this if people want me to, so that
everybody can play with it.

Ryan


------------
ap_buf.c
------------

/* ====================================================================
 * Copyright (c) 1996-1999 The Apache Group.  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. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" 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 names without prior written
 *    permission of the Apache Group.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */

#include "ap_config.h"
#include "apr_lib.h"
#include "apr_errno.h"
#include <stdlib.h>
#include <sys/uio.h>
#include "ap_buf.h"

/* We are creating a new bucket here.  We could replace the switch with a
 * function pointer if we want to.  I'm not sure it's a real win though.
 */
API_EXPORT(ap_bucket *) ap_bucket_new(ap_bucket_color_e color)
{
    /* TODO: keep a free list of ap_bufels... and allocate them in big chunks */
    ap_bucket *newbuf;
    newbuf = malloc(sizeof(newbuf));
    newbuf->color = color;
    switch (color) {
        case AP_BUCKET_rwmem:
            newbuf->data = ap_rwmem_create();
            newbuf->free = ap_rwmem_destroy;
            break;
        case AP_BUCKET_rmem:
        case AP_BUCKET_file_t:
        case AP_BUCKET_mmap_t:
        case AP_BUCKET_filename:
        case AP_BUCKET_cached_entity:
        case AP_BUCKET_URI:
            /* not implemented yet */
            break;
    }
    return newbuf;
}

API_EXPORT(ap_status_t) ap_bucket_destroy(ap_bucket *e)
{
    e->free(e);
    free(e);
    return APR_SUCCESS;
}

API_EXPORT(ap_status_t) ap_bucket_brigade_destroy(void *data)
{
    ap_bucket_brigade *b = data;
    ap_bucket_list *bl = b->head;

    ap_destroy_bucket_list(bl);

    return APR_SUCCESS;
}        

API_EXPORT(ap_bucket_brigade *) ap_bucket_brigade_create(ap_pool_t *p)
{
    ap_bucket_brigade *b;

    b = malloc(sizeof(b));
    b->p = p;
    b->head = b->tail = NULL;

    ap_register_cleanup(b->p, b, ap_bucket_brigade_destroy, 
                        ap_bucket_brigade_destroy);
    return b;
}

API_EXPORT(void) ap_bucket_list_init(ap_bucket_list *b)
{
    b->bucket = NULL;
    b->next = b->prev = NULL;
}

API_EXPORT(void) ap_bucket_brigade_append(ap_bucket_brigade *b, 
                                          ap_bucket_list *e)
{
    e->next = b->tail;
    b->tail->prev = e;
    b->tail = e->next;
}

/*
API_EXPORT(void) ap_bucket_list_consume(ap_bucket_list *b, int nbytes)
{
    ap_bucket *e;
    ap_bucket *n;
    int amt;

    b->size -= nbytes;
    e = b->head;
    while (e && nbytes) {
	amt = e->end - e->start;
	if (nbytes < amt) {
            e->start += nbytes;
            break;
	}
	n = e->next;
	ap_bucket_destroy(e);
	nbytes -= amt;
	e = n;
    }
    b->head = e;
    if (!e) {
	b->tail = &b->head;
    }
}*/

API_EXPORT(int) ap_bucket_brigade_to_iovec(ap_bucket_brigade *b, 
                                           struct iovec *vec, int nvec)
{
    ap_bucket_list *e;
    struct iovec *orig;

    orig = vec;
    e = b->head;
    while (e && nvec) {
	vec->iov_base = ap_get_bucket_char_str(e->bucket);
	vec->iov_len = ap_get_bucket_len(e->bucket);
	e = e->next;
	--nvec;
	++vec;
    }
    return vec - orig;
}

API_EXPORT(void) ap_bucket_brigade_catenate(ap_bucket_brigade *a, 
                                            ap_bucket_brigade *b)
{
    if (b->head) {
	a->tail = b->head;
	a->tail = b->tail;
	b->head = NULL;
	b->tail = b->head;
    }
}

API_EXPORT(ap_status_t) ap_bucket_brigade_to_iol(ap_bucket_brigade *b, 
                                                 ap_iol *iol)
{
    ap_status_t status;
    int iov_used;
    struct iovec vec[16];   /* seems like a reasonable number to me */
    ap_ssize_t bytes;

    do {
        iov_used = ap_bucket_brigade_to_iovec(b, vec, 16);
        status = iol_writev(iol, vec, iov_used, &bytes);
        if (status != APR_SUCCESS) {
            return status;
        }
    } while (iov_used == 16);
    return APR_SUCCESS;
}

API_EXPORT(ap_status_t) ap_destroy_bucket_list(ap_bucket_list *buf)
{
    ap_bucket_list *dptr = buf;
   
    while (dptr) {
        ap_bucket_destroy(dptr->bucket);
        dptr = dptr->next;
    }
    ap_bucket_destroy(dptr->bucket);
    return APR_SUCCESS;
}

API_EXPORT(char *) ap_get_bucket_char_str(ap_bucket *b)
{
    switch (b->color) {
        case AP_BUCKET_rwmem:
            return ap_rwmem_get_char_str(b->data);
        case AP_BUCKET_rmem:
        case AP_BUCKET_file_t:
        case AP_BUCKET_mmap_t:
        case AP_BUCKET_filename:
        case AP_BUCKET_cached_entity:
        case AP_BUCKET_URI:
            /* not implemented yet */
            return NULL;
    }
    /* We should NEVER actually get here */
    return NULL;
}    

API_EXPORT(int) ap_get_bucket_len(ap_bucket *b)
{
    switch (b->color) {
        case AP_BUCKET_rwmem:
            return ap_rwmem_get_len(b->data);
        case AP_BUCKET_rmem:
        case AP_BUCKET_file_t:
        case AP_BUCKET_mmap_t:
        case AP_BUCKET_filename:
        case AP_BUCKET_cached_entity:
        case AP_BUCKET_URI:
            /* not implemented yet */
            return 0;
    }
    /* We should NEVER actually get here */
    return 0;
}    

--------------
ap_rwmem_buf.c
--------------

/* ====================================================================
 * Copyright (c) 1996-1999 The Apache Group.  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. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" 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 names without prior written
 *    permission of the Apache Group.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */

#include "ap_config.h"
#include "ap_buf.h"

#ifndef DEFAULT_RWBUF_SIZE
#define DEFAULT_RWBUF_SIZE (4096)
#endif

API_EXPORT(ap_bucket_rwmem *) ap_rwmem_create(void)
{
    ap_bucket_rwmem *newbuf;
    newbuf = malloc(sizeof(newbuf));
    newbuf->alloc_addr = calloc(DEFAULT_RWBUF_SIZE, 1);
    newbuf->alloc_len  = DEFAULT_RWBUF_SIZE;
    newbuf->start      = newbuf->alloc_addr;
    newbuf->end        = newbuf->alloc_addr;
    return newbuf;
}

API_EXPORT(void) ap_rwmem_destroy(void *e)
{
    ap_bucket_rwmem *d = (ap_bucket_rwmem *)e;
    free(d->alloc_addr);
    free(d);
}

API_EXPORT(char *) ap_rwmem_get_char_str(ap_bucket_rwmem *b)
{
    return b->start;
}

API_EXPORT(int) ap_rwmem_get_len(ap_bucket_rwmem *b)
{
    return b->end - b->start;
}

-------------
ap_buf.h
-------------

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000 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 AP_BUF_H
#define AP_BUF_H

#include "apr_errno.h"
#include "ap_iol.h"
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>	/* for struct iovec */
#endif

typedef enum {
    AP_BUCKET_rwmem,
    AP_BUCKET_rmem,
    AP_BUCKET_file_t,
    AP_BUCKET_mmap_t,
    AP_BUCKET_filename,
    AP_BUCKET_cached_entity,
    AP_BUCKET_URI,
} ap_bucket_color_e;

typedef struct ap_bucket ap_bucket;
struct ap_bucket {
    ap_bucket_color_e color;            /* what type of bucket is it */
    void (*free)(void *e);              /* never NULL */
    void *data;				/* for use by free() */
};

typedef struct ap_bucket_list ap_bucket_list;
struct ap_bucket_list {
    ap_bucket *bucket;                   /* The bucket */
    ap_bucket_list *next;                /* The start of the bucket list */
    ap_bucket_list *prev;                /* The end of the bucket list */
};

typedef struct ap_bucket_brigade ap_bucket_brigade;
struct ap_bucket_brigade {
    ap_pool_t *p;                       /* The pool to associate this with.
                                           I do not allocate out of the pool,
                                           but this lets me register a cleanup
                                           to put a limit on the brigade's 
                                           lifetime. */
    ap_bucket_list *head;               /* The start of the brigade */
    ap_bucket_list *tail;               /* The end of the brigade */
};

/*   ******  Bucket Brigade Functions  *****  */

/* Create a new bucket brigade */
API_EXPORT(ap_bucket_brigade *) ap_bucket_brigade_create(ap_pool_t *p);

/* destroy an enitre bucket brigade */
API_EXPORT(ap_status_t) ap_bucket_brigade_destroy(void *b);

/* append a bucket_brigade to a bucket_brigade */
API_EXPORT(void) ap_bucket_brigade_append(ap_bucket_brigade *b, 
                                          ap_bucket_list *e);

/* consume nbytes from beginning of b -- call ap_bucket_destroy as
    appropriate, and/or modify start on last element */
API_EXPORT(void) ap_bucket_brigade_consume(ap_bucket_brigade *, int nbytes);

/* create an iovec of the elements in a bucket_brigade... return number 
    of elements used */
API_EXPORT(int) ap_bucket_brigade_to_iovec(ap_bucket_brigade *, 
                                           struct iovec *vec, int nvec);

/* catenate bucket_brigade b onto bucket_brigade a, bucket_brigade b is 
    empty after this */
API_EXPORT(void) ap_bucket_brigade_catenate(ap_bucket_brigade *a, 
                                            ap_bucket_brigade *b);

/* save the buf out to the specified iol.  This can be used to flush the
    data to the disk, or to send it out to the network. */
API_EXPORT(ap_status_t) ap_bucket_brigade_to_iol(ap_bucket_brigade *a, 
                                                 ap_iol *iol);

/*   ******  Bucket List Functions  *****  */

/* initialize a bucket_list */
API_EXPORT(void) ap_bucket_list_init(ap_bucket_list *b);

/* destroy an entire bucket_list */
API_EXPORT(ap_status_t) ap_destroy_bucket_list(ap_bucket_list *b);

/*   ******  Bucket Functions  *****  */

/* allocate a bucket of type color */
API_EXPORT(ap_bucket *) ap_bucket_new(ap_bucket_color_e color);

/* destroy a bucket */
API_EXPORT(ap_status_t) ap_bucket_destroy(ap_bucket *e);

/* Convert a bucket to a char * */
API_EXPORT(char *) ap_get_bucket_char_str(ap_bucket *b);

/* get the length of the data in the bucket */
API_EXPORT(int) ap_get_bucket_len(ap_bucket *b);

/*   ******  RWMEM Functions  *****  */

typedef struct ap_bucket_rwmem ap_bucket_rwmem;
struct ap_bucket_rwmem {
    void    *alloc_addr;                /* Where does the data start */
    size_t  alloc_len;                  /* how much was allocated */
    void    *start;                     /* Where does the actual data start
                                           in the alloc'ed block */
    void    *end;                       /* where does the data actually end? */
};

/* Create a read/write memory bucket */
API_EXPORT(ap_bucket_rwmem *) ap_rwmem_create(void);

/* destroy a read/write memory bucket */
API_EXPORT(void) ap_rwmem_destroy(void *e);

/* Convert a rwmem bucket into a char * */
API_EXPORT(char *) ap_rwmem_get_char_str(ap_bucket_rwmem *b);

/* get the length of the data in the rwmem bucket */
API_EXPORT(int) ap_rwmem_get_len(ap_bucket_rwmem *b);

#endif

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------