apr_buckets_pool.c 4.7 KB

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