1 /* Copyright 2000-2004 The Apache Software Foundation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include "apr_buckets.h"
17 #define APR_WANT_MEMFUNC
20 static apr_status_t
pool_bucket_cleanup(void *data
)
22 apr_bucket_pool
*p
= data
;
25 * If the pool gets cleaned up, we have to copy the data out
26 * of the pool and onto the heap. But the apr_buckets out there
27 * that point to this pool bucket need to be notified such that
28 * they can morph themselves into a regular heap bucket the next
29 * time they try to read. To avoid having to manipulate
30 * reference counts and b->data pointers, the apr_bucket_pool
31 * actually _contains_ an apr_bucket_heap as its first element,
32 * so the two share their apr_bucket_refcount member, and you
33 * can typecast a pool bucket struct to make it look like a
34 * regular old heap bucket struct.
36 p
->heap
.base
= apr_bucket_alloc(p
->heap
.alloc_len
, p
->list
);
37 memcpy(p
->heap
.base
, p
->base
, p
->heap
.alloc_len
);
44 static apr_status_t
pool_bucket_read(apr_bucket
*b
, const char **str
,
45 apr_size_t
*len
, apr_read_type_e block
)
47 apr_bucket_pool
*p
= b
->data
;
48 const char *base
= p
->base
;
50 if (p
->pool
== NULL
) {
52 * pool has been cleaned up... masquerade as a heap bucket from now
53 * on. subsequent bucket operations will use the heap bucket code.
55 b
->type
= &apr_bucket_type_heap
;
58 *str
= base
+ b
->start
;
63 static void pool_bucket_destroy(void *data
)
65 apr_bucket_pool
*p
= data
;
67 /* If the pool is cleaned up before the last reference goes
68 * away, the data is really now on the heap; heap_destroy() takes
69 * over. free() in heap_destroy() thinks it's freeing
70 * an apr_bucket_heap, when in reality it's freeing the whole
71 * apr_bucket_pool for us.
74 /* the shared resource is still in the pool
75 * because the pool has not been cleaned up yet
77 if (apr_bucket_shared_destroy(p
)) {
78 apr_pool_cleanup_kill(p
->pool
, p
, pool_bucket_cleanup
);
83 /* the shared resource is no longer in the pool, it's
84 * on the heap, but this reference still thinks it's a pool
85 * bucket. we should just go ahead and pass control to
86 * heap_destroy() for it since it doesn't know any better.
88 apr_bucket_type_heap
.destroy(p
);
92 APU_DECLARE(apr_bucket
*) apr_bucket_pool_make(apr_bucket
*b
,
93 const char *buf
, apr_size_t length
, apr_pool_t
*pool
)
97 p
= apr_bucket_alloc(sizeof(*p
), b
->list
);
99 /* XXX: we lose the const qualifier here which indicates
100 * there's something screwy with the API...
102 /* XXX: why is this? buf is const, p->base is const... what's
103 * the problem? --jcw */
104 p
->base
= (char *) buf
;
108 b
= apr_bucket_shared_make(b
, p
, 0, length
);
109 b
->type
= &apr_bucket_type_pool
;
111 /* pre-initialize heap bucket member */
112 p
->heap
.alloc_len
= length
;
114 p
->heap
.free_func
= apr_bucket_free
;
116 apr_pool_cleanup_register(p
->pool
, p
, pool_bucket_cleanup
,
117 apr_pool_cleanup_null
);
121 APU_DECLARE(apr_bucket
*) apr_bucket_pool_create(const char *buf
,
124 apr_bucket_alloc_t
*list
)
126 apr_bucket
*b
= apr_bucket_alloc(sizeof(*b
), list
);
129 b
->free
= apr_bucket_free
;
131 return apr_bucket_pool_make(b
, buf
, length
, pool
);
134 APU_DECLARE_DATA
const apr_bucket_type_t apr_bucket_type_pool
= {
135 "POOL", 5, APR_BUCKET_DATA
,
138 apr_bucket_setaside_noop
, /* don't need to setaside thanks to the cleanup*/
139 apr_bucket_shared_split
,
140 apr_bucket_shared_copy