* Having jumped through all the hoops and decided to cache the * response, call store_body() for each brigade, handling the * case where the provider can't swallow the full brigade. In this * case, we write the brigade we were passed out downstream, and * loop around to try and cache some more until the in brigade is * completely empty. As soon as the out brigade contains eos, call * commit_
| 700 | * commit_entity() to finalise the cached element. |
| 701 | */ |
| 702 | static int cache_save_store(ap_filter_t *f, apr_bucket_brigade *in, |
| 703 | cache_server_conf *conf, cache_request_rec *cache) |
| 704 | { |
| 705 | int rv = APR_SUCCESS; |
| 706 | apr_bucket *e; |
| 707 | |
| 708 | /* pass the brigade in into the cache provider, which is then |
| 709 | * expected to move cached buckets to the out brigade, for us |
| 710 | * to pass up the filter stack. repeat until in is empty, or |
| 711 | * we fail. |
| 712 | */ |
| 713 | while (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(in)) { |
| 714 | |
| 715 | rv = cache->provider->store_body(cache->handle, f->r, in, cache->out); |
| 716 | if (rv != APR_SUCCESS) { |
| 717 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r, APLOGNO(00765) |
| 718 | "cache: Cache provider's store_body failed for URI %s", f->r->uri); |
| 719 | ap_remove_output_filter(f); |
| 720 | |
| 721 | /* give someone else the chance to cache the file */ |
| 722 | cache_remove_lock(conf, cache, f->r, NULL); |
| 723 | |
| 724 | /* give up trying to cache, just step out the way */ |
| 725 | APR_BRIGADE_PREPEND(in, cache->out); |
| 726 | return ap_pass_brigade(f->next, in); |
| 727 | |
| 728 | } |
| 729 | |
| 730 | /* does the out brigade contain eos? if so, we're done, commit! */ |
| 731 | for (e = APR_BRIGADE_FIRST(cache->out); |
| 732 | e != APR_BRIGADE_SENTINEL(cache->out); |
| 733 | e = APR_BUCKET_NEXT(e)) |
| 734 | { |
| 735 | if (APR_BUCKET_IS_EOS(e)) { |
| 736 | rv = cache->provider->commit_entity(cache->handle, f->r); |
| 737 | break; |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | /* conditionally remove the lock as soon as we see the eos bucket */ |
| 742 | cache_remove_lock(conf, cache, f->r, cache->out); |
| 743 | |
| 744 | if (APR_BRIGADE_EMPTY(cache->out)) { |
| 745 | if (APR_BRIGADE_EMPTY(in)) { |
| 746 | /* cache provider wants more data before passing the brigade |
| 747 | * upstream, oblige the provider by leaving to fetch more. |
| 748 | */ |
| 749 | break; |
| 750 | } |
| 751 | else { |
| 752 | /* oops, no data out, but not all data read in either, be |
| 753 | * safe and stand down to prevent a spin. |
| 754 | */ |
| 755 | ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, f->r, APLOGNO(00766) |
| 756 | "cache: Cache provider's store_body returned an " |
| 757 | "empty brigade, but didn't consume all of the " |
| 758 | "input brigade, standing down to prevent a spin"); |
| 759 | ap_remove_output_filter(f); |
no test coverage detected