From b0470cc5acd2563f73d535687b0ea06ee77d7583 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Andr=C3=A9=20Malo?= FLUSH
buckets.
HEAP FLUSH FILE EOS
+ HEAP FLUSH FILE EOS
This shows a bucket brigade which may be passed to a filter; it
contains two metadata buckets (FLUSH
and
@@ -122,12 +123,18 @@
filter chain. But, for good defensive programming, filters should
be prepared to accept an empty brigade, and do nothing.
apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb) -{ - if (APR_BRIGADE_EMPTY(bb)) { - return APR_SUCCESS; - } - ....
+ apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)
+ {
+
+ if (APR_BRIGADE_EMPTY(bb)) {
+
+ return APR_SUCCESS;
+
+ }
+ ....
+
+
There are a variety of functions and macros for traversing and manipulating bucket brigades; see the apr_bucket.h - header for complete coverage. Commonly used macros include: + header for complete coverage. Commonly used macros include:
APR_BRIGADE_FIRST(bb)
APR_BUCKET_PREV(e)
The apr_bucket_brigade
structure itself is
allocated out of a pool, so if a filter creates a new brigade, it
@@ -194,7 +201,7 @@
When dealing with non-metadata buckets, it is important to
understand that the "apr_bucket *
" object is an
- abstract representation of data:
+ abstract representation of data:
Filters read the data from a bucket using the
apr_bucket_read
function. When this function is
invoked, the bucket may morph into a different bucket
type, and may also insert a new bucket into the bucket brigade.
@@ -220,7 +227,7 @@
single FILE
bucket representing an entire file, 24
kilobytes in size:
FILE(0K-24K)
FILE(0K-24K)
When this bucket is read, it will read a block of data from the
file, morph into a HEAP
bucket to represent that
@@ -229,7 +236,7 @@
after the apr_bucket_read
call, the brigade looks
like:
HEAP(8K) FILE(8K-24K)
HEAP(8K) FILE(8K-24K)
Taking an example which loops through the entire brigade as - follows: - -
apr_bucket *e = APR_BRIGADE_FIRST(bb); -const char *data; -apr_size_t len; - -while (e != APR_BRIGADE_SENTINEL(bb)) { - apr_bucket_read(e, &data, &length, APR_BLOCK_READ); - e = APR_BUCKET_NEXT(e); -} - -return ap_pass_brigade(bb);
+ apr_bucket *e = APR_BRIGADE_FIRST(bb);
+const char *data;
+apr_size_t len;
+
+while (e != APR_BRIGADE_SENTINEL(bb)) {
+
+ apr_bucket_read(e, &data, &length, APR_BLOCK_READ);
+ e = APR_BUCKET_NEXT(e);
+
+}
+
+return ap_pass_brigade(bb);
+
The above implementation would consume memory proportional to
content size. If passed a FILE
bucket, for example,
the entire file contents would be read into memory as each
apr_bucket_read
call morphed a FILE
@@ -265,22 +276,26 @@ return ap_pass_brigade(bb);
apr_bucket *e; -const char *data; -apr_size_t len; - -while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) { - rv = apr_bucket_read(e, &data, &length, APR_BLOCK_READ); - if (rv) ...; - /* Remove bucket e from bb. */ - APR_BUCKET_REMOVE(e); - /* Insert it into temporary brigade. */ - APR_BRIGADE_INSERT_HEAD(tmpbb, e); - /* Pass brigade downstream. */ - rv = ap_pass_brigade(f->next, tmpbb); - if (rv) ...; - apr_brigade_cleanup(tmpbb); -}
+apr_bucket *e;
+const char *data;
+apr_size_t len;
+
+while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {
+
+ rv = apr_bucket_read(e, &data, &length, APR_BLOCK_READ);
+ if (rv) ...;
+ /* Remove bucket e from bb. */
+ APR_BUCKET_REMOVE(e);
+ /* Insert it into temporary brigade. */
+ APR_BRIGADE_INSERT_HEAD(tmpbb, e);
+ /* Pass brigade downstream. */
+ rv = ap_pass_brigade(f->next, tmpbb);
+ if (rv) ...;
+ apr_brigade_cleanup(tmpbb);
+
+}
+
struct dummy_state { - apr_bucket_brigade *tmpbb; - int filter_state; - .... -}; - -apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb) -{ - struct dummy_state *state; - - state = f->ctx; - if (state == NULL) { - /* First invocation for this response: initialise state structure. */ - f->ctx = state = apr_palloc(sizeof *state, f->r->pool); - - state->tmpbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); - state->filter_state = ...; - } - ...
+struct dummy_state {
+
+ apr_bucket_brigade *tmpbb;
+ int filter_state;
+ ....
+
+};
+
+apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)
+{
+
+ struct dummy_state *state;
+
+ state = f->ctx;
+ if (state == NULL) {
+
+ /* First invocation for this response: initialise state structure.
+ */
+ f->ctx = state = apr_palloc(sizeof *state, f->r->pool);
+
+ state->tmpbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+ state->filter_state = ...;
+
+ }
+ ...
+
+
ap_save_brigade
guarantees that all
@@ -356,7 +380,7 @@ apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)
non-NULL "saveto
" (destination) brigade parameter,
the function will create a new brigade, which may cause memory
use to be proportional to content size as described in the Brigade structure section.apr_bucket *e; -apr_read_type_e mode = APR_NONBLOCK_READ; - -while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) { - apr_status_t rv; - - rv = apr_bucket_read(e, &data, &length, mode); - if (rv == APR_EAGAIN && mode == APR_NONBLOCK_READ) { - /* Pass down a brigade containing a flush bucket: */ - APR_BRIGADE_INSERT_TAIL(tmpbb, apr_bucket_flush_create(...)); - rv = ap_pass_brigade(f->next, tmpbb); - apr_brigade_cleanup(tmpbb); - if (rv != APR_SUCCESS) return rv; - - /* Retry, using a blocking read. */ - mode = APR_BLOCK_READ; - continue; - } else if (rv != APR_SUCCESS) { - /* handle errors */ - } - - /* Next time, try a non-blocking read first. */ - mode = APR_NONBLOCK_READ; - ... -}
+
+apr_bucket *e;
+apr_read_type_e mode = APR_NONBLOCK_READ;
+
+while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {
+
+ apr_status_t rv;
+
+ rv = apr_bucket_read(e, &data, &length, mode);
+ if (rv == APR_EAGAIN && mode == APR_NONBLOCK_READ) {
+
+ /* Pass down a brigade containing a flush bucket: */
+ APR_BRIGADE_INSERT_TAIL(tmpbb, apr_bucket_flush_create(...));
+ rv = ap_pass_brigade(f->next, tmpbb);
+ apr_brigade_cleanup(tmpbb);
+ if (rv != APR_SUCCESS) return rv;
+
+ /* Retry, using a blocking read. */
+ mode = APR_BLOCK_READ;
+ continue;
+
+ } else if (rv != APR_SUCCESS) {
+
+ /* handle errors */
+
+ }
+
+ /* Next time, try a non-blocking read first. */
+ mode = APR_NONBLOCK_READ;
+ ...
+
+}
+
This directive adds a member to a load balancing group. It must be used
- within a <Proxy balancer://...>
container directive, and can take any
- of the parameters available to
+ within a <Proxy balancer://...>
container
+ directive, and can take any of the parameters available to
ProxyPass
directives.
One additional parameter is available only to BalancerMember
directives:
loadfactor. This is the member load factor - a number between 1
diff --git a/docs/manual/mod/mod_proxy.xml.ja b/docs/manual/mod/mod_proxy.xml.ja
index bf67fa0960..e42f062dcf 100644
--- a/docs/manual/mod/mod_proxy.xml.ja
+++ b/docs/manual/mod/mod_proxy.xml.ja
@@ -1,7 +1,7 @@
-
+