ウォンツテック

そでやまのーと

  • /srclib/apr-util/include/apr_buckets.h
struct apr_bucket_type_t {
    //このbucketのタイプ名
    const char *name;
    //このbucketが理解出来る関数の数. 5未満は駄目
    int num_func;
    
    //bucketがメタデータを含んでいるかどうか
    enum {
        APR_BUCKET_DATA = 0,
        APR_BUCKET_METADATA = 1
    } is_metadata;

    //bucketが使っているデータの開放(free)。ただし、他のbucketと
  //共有してない場合。
    void (*destroy)(void *data);

    //bucketからデータを読み取る
    apr_status_t (*read)(apr_bucket *b, const char **str, 
                  apr_size_t *len,
                  apr_read_type_e block);

    //bucketのデータをpoolに入れて取っておく?
    //通常bucketデータはこのpoolに入れておかないと破棄される?
    apr_status_t (*setaside)(apr_bucket *e, apr_pool_t *pool);

    //bucketの分割
    apr_status_t (*split)(apr_bucket *e, apr_size_t point);

    //bucketのコピー
    apr_status_t (*copy)(apr_bucket *e, apr_bucket **c);
};

bucketの基本操作を関数ポインタで持った構造体

struct apr_bucket {
    APR_RING_ENTRY(apr_bucket) link;
    const apr_bucket_type_t *type;
    apr_size_t length; //bucketの長さ、知られていなければ-1
    apr_off_t start;
    void *data;
    void (*free)(void *e);
    apr_bucket_alloc_t *list;
};

bucket構造体の本体でring構造を持ち(APR_RING_ENTRY)brigateのLinkとして繋いでいく。
dataがこのbucketが示すデータへのポインタで
freeはこのbucketを開放する関数ポインタ(たとえばfree())
listはこのbucketがallocateされているfreelistへのポインタ。
※このポインタとfreeで実際に開放が行われている?

struct apr_bucket_brigade {
  // brigade用のpool?よくわからない。
  apr_pool_t *p;
  // このbrigadeに繋げるbucket ringのhead
  APR_RING_HEAD(apr_bucket_list, par_bucket) list;
  // このbucketがallocateされているfreelistへのポインタ
  apr_bucket_alloc_t *bucket_alloc;
};
||

*brigadeの操作用マクロ群
>|c|
#define APR_BRIGADE_SENTINEL(b) APR_RING_SENTINEL(&(b)->list, apr_bucket, link) //このbrigadeの番兵(head位置)
#define APR_BRIGADE_EMPTY(b)    APR_RING_EMPTY(&(b)->list, apr_bucket, link) //brigadeが空かどうか
#define APR_BRIGADE_FIRST(b)    APR_RING_FIRST(&(b)->list)
#define APR_BRIGADE_LAST(b) APR_RING_LAST(&(b)->list)
#define APR_BRIGADE_INSERT_HEAD(b, e) do {              \
    apr_bucket *ap__b = (e);                                        \
    APR_RING_INSERT_HEAD(&(b)->list, ap__b, apr_bucket, link);  \
        APR_BRIGADE_CHECK_CONSISTENCY((b));             \
    } while (0)
||
brigade「b」の先頭にbucket「e」を挿入

>|c|
#define APR_BRIGADE_INSERT_TAIL(b, e) do {              \
    apr_bucket *ap__b = (e);                    \
    APR_RING_INSERT_TAIL(&(b)->list, ap__b, apr_bucket, link);  \
        APR_BRIGADE_CHECK_CONSISTENCY((b));             \
    } while (0)

brigade「b」の最後尾にbucket「e」を挿入

#define APR_BRIGADE_CONCAT(a, b)
#define APR_BRIGADE_PREPEND(a, b)
#define APR_BUCKET_NEXT(e)  APR_RING_NEXT((e), link)
#define APR_BUCKET_REMOVE(e)    APR_RING_REMOVE((e), link)
#define APR_BUCKET_INIT(e)  APR_RING_ELEM_INIT((e), link)
#define APR_BUCKET_IS_XXX // bucket内のtype調査マクロ群
union apr_bucket_structs {
    apr_bucket      b;      /**< Bucket */
    apr_bucket_heap heap;   /**< Heap */
    apr_bucket_pool pool;   /**< Pool */
#if APR_HAS_MMAP
    apr_bucket_mmap mmap;   /**< MMap */
#endif
    apr_bucket_file file;   /**< File */
};

apr_bucketの共用体。heap用、pool用、mmap用、file用などがある。


以下brigade関連の操作関数

//brigadeを新しく作る
APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
                                                apr_bucket_alloc_t *list);
//このbrigadeのbucket全て消し、自分も消す
APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b);
//このbrigadeのbucketを全て消し空にする。
APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data);
//eでbrigadeを分割し新しく出来たbrigade(eを含む)を返す
APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
                                                    apr_bucket *e);
//brigade bをオフセット pointの位置で分割し、after_pointで分割後のポインタ位置を返す。(splitとの違いは新しくbrigadeを作ってそれを返すかどうか???)
APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
                                                apr_off_t point,
                                                apr_bucket **after_point);
//このbrigadeの長さを返す
APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
                                             int read_all,
                                             apr_off_t *length);
//byte系のデータをこのbrigadeに追加?(新しくbucketを作ってる?) 
APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
                                              char *c,
                                              apr_size_t *len);

APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
                                               char **c,
                                               apr_size_t *len,
                                               apr_pool_t *pool);
//1行毎の分割用 HTTP用
APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
                                                 apr_bucket_brigade *bbIn,
                                                 apr_read_type_e block,
                                                 apr_off_t maxbytes);
APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
                                            struct iovec *vec, int *nvec);


//以下brigadeへの書き込み関数
APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
                                               apr_brigade_flush flush,
                                               void *ctx,
                                               va_list va);
APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
                                       apr_brigade_flush flush, void *ctx,
                                       const char *str, apr_size_t nbyte);
APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
                                             apr_brigade_flush flush,
                                             void *ctx,
                                             const struct iovec *vec,
                                             apr_size_t nvec);
APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
                                       apr_brigade_flush flush, void *ctx,
                                       const char *str);
APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
                                       apr_brigade_flush flush, void *ctx,
                                       const char c);
APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
                                                 apr_brigade_flush flush,
                                                 void *ctx, ...);
APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
                                                  apr_brigade_flush flush,
                                                  void *ctx,
                                                  const char *fmt, ...)
        __attribute__((format(printf,4,5)));

//ファイル挿入用
APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
                                                  apr_file_t *f,
                                                  apr_off_t start,
                                                  apr_off_t len,
                                                  apr_pool_t *p);