in buckets/split_buckets.c [274:339]
static apr_uint64_t serf_split_get_remaining(serf_bucket_t *bucket)
{
split_stream_ctx_t *sctx = bucket->data;
split_context_t *ctx = sctx->ctx;
split_stream_ctx_t *head;
apr_uint64_t remaining;
if (!ctx || sctx->at_eof) {
return 0; /* at eof */
}
else if (ctx->head == sctx) {
/* We are HEAD. We hereby unlock the data to allow reading the size */
sctx->cant_read = false;
}
if (sctx->fixed_size) {
return sctx->fixed_size - sctx->read_size; /* already calculated */
}
/* Do we know the total size? */
head = ctx->head;
if (head->tail_size == SERF_LENGTH_UNKNOWN) {
if (head->cant_read) {
/* Can't obtain the size without unlocking data*/
ctx->want_size = true;
return SERF_LENGTH_UNKNOWN;
}
head->tail_size = serf_bucket_get_remaining(ctx->stream);
if (head->tail_size == SERF_LENGTH_UNKNOWN)
return SERF_LENGTH_UNKNOWN;
/* Add what we already have to avoid updating on every read */
head->tail_size += head->read_size;
}
remaining = head->tail_size;
/* And now we fix the sizes of the buckets until we get to
the one we're interested in */
while (head) {
if (!head->fixed_size) {
/* Size not decided yet. Let's make this chunk as big
as allowed */
head->fixed_size = (remaining < head->max_size)
? (apr_size_t)remaining
: head->max_size;
/* Disable dynamic sizing now */
head->min_size = head->max_size = head->fixed_size;
}
if (head == sctx) {
/* We got the information we need. Exit now to avoid
fixing the length of more buckets than needed */
return sctx->fixed_size - sctx->read_size;
}
remaining -= head->fixed_size;
head = head->next;
}
return SERF_LENGTH_UNKNOWN; /* Hit NULL before our bucket??? */
}