Commit 08f55f19 authored by Brian Pane's avatar Brian Pane
Browse files

Update new conn_rec field "data_in_output_filters" in core output filter

so async MPMs can tell whether to keep polling and writing


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/async-dev@307379 13f79535-47bb-0310-9956-ffa450edef68
parent 3b438e84
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1066,6 +1066,8 @@ struct conn_rec {
    conn_state_t *cs;
    /** Is there data pending in the input filters? */ 
    int data_in_input_filters;
    /** Is there data pending in the output filters? */
    int data_in_output_filters;
};

/** 
+1 −1
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ static int ap_process_http_async_connection(conn_rec *c)
            ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
            if (r->status == HTTP_OK) {
                cs->state = CONN_STATE_HANDLER;
                ap_process_request(r);
                ap_process_async_request(r);
            }

            if (ap_extended_status)
+49 −27
Original line number Diff line number Diff line
@@ -307,6 +307,11 @@ int ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
    return APR_SUCCESS;
}

static void setaside_remaining_output(ap_filter_t *f,
                                      core_output_filter_ctx_t *ctx,
                                      apr_bucket_brigade *bb,
                                      int make_a_copy, conn_rec *c);

static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
                                             apr_bucket_brigade *bb,
                                             apr_size_t *bytes_written,
@@ -376,10 +381,14 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
        if (new_bb != NULL) {
            APR_BRIGADE_CONCAT(bb, new_bb);
        }
        c->data_in_output_filters = 0;
    }
    else if (new_bb != NULL) {
        bb = new_bb;
    }
    else {
        return;
    }

    /* Scan through the brigade and decide whether to attempt a write,
     * based on the following rules:
@@ -411,12 +420,11 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
        apr_status_t rv = send_brigade_nonblocking(net->client_socket, bb,
                                                   &(ctx->bytes_written), c);
        if (APR_STATUS_IS_EAGAIN(rv)) {
            return APR_SUCCESS;
            rv = APR_SUCCESS;
        }
        else {
        setaside_remaining_output(f, ctx, bb, 0, c);
        return rv;
    }
    }
    
    bytes_in_brigade = 0;
    non_file_bytes_in_brigade = 0;
@@ -473,24 +481,35 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
        }
    }

    if (!APR_BRIGADE_EMPTY(bb)) {
        if (new_bb == NULL) {
            /* Everything in bb must have been in ctx->buffered_bb
             * before this function was called.  Thus we can just
             * move it back, without incurring the potential copying
             * cost of a bucket setaside.
             */
            ctx->buffered_bb = bb;
    setaside_remaining_output(f, ctx, bb, 1, c);
    return APR_SUCCESS;
}
        else {

static void setaside_remaining_output(ap_filter_t *f,
                                      core_output_filter_ctx_t *ctx,
                                      apr_bucket_brigade *bb,
                                      int make_a_copy, conn_rec *c)
{
    if (bb == NULL) {
        return;
    }
    remove_empty_buckets(bb);
    if (!APR_BRIGADE_EMPTY(bb)) {
        c->data_in_output_filters = 1;
        if (make_a_copy) {
            /* XXX should this use a separate deferred write pool, like
             * the original ap_core_output_filter?
             */
            ap_save_brigade(f, &(ctx->buffered_bb), &bb, c->pool);
            apr_brigade_destroy(bb);
        }
        else {
            ctx->buffered_bb = bb;
        }
    }
    else {
        apr_brigade_destroy(bb);
    }

    return APR_SUCCESS;
}
 
#ifndef APR_MAX_IOVEC_SIZE 
@@ -533,6 +552,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
            if ((apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) &&
                (bucket->length >= AP_MIN_SENDFILE_BYTES)) {
                did_sendfile = 1;
                if (nvec > 0) {
                    (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
                    rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
                    nvec = 0;
@@ -540,11 +560,15 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
                        (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
                        return rv;
                    }
                }
                rv = sendfile_nonblocking(s, bb, bytes_written, c);
                if (nvec > 0) {
                    (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
                }
                if (rv != APR_SUCCESS) {
                    return rv;
                }
                break;
            }
        }
#endif /* APR_HAS_SENDFILE */
@@ -566,6 +590,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
                if (rv != APR_SUCCESS) {
                    return rv;
                }
                break;
            }
        }
    }
@@ -703,21 +728,18 @@ static apr_status_t sendfile_nonblocking(apr_socket_t *s,
    file_length = bucket->length;
    file_offset = bucket->start;

    while (bytes_written < file_length) {
    if (bytes_written < file_length) {
        apr_size_t n = file_length - bytes_written;
        rv = apr_socket_sendfile(s, fd, NULL, &file_offset, &n, 0);
        if (rv == APR_SUCCESS) {
            bytes_written += n;
            file_offset += n;
        }
        else {
            break;
        }
    }
    if ((logio_add_bytes_out != NULL) && (bytes_written > 0)) {
        logio_add_bytes_out(c, bytes_written);
    }
    cumulative_bytes_written += bytes_written;
    *cumulative_bytes_written += bytes_written;
    if ((bytes_written < file_length) && (bytes_written > 0)) {
        apr_bucket_split(bucket, bytes_written);
        APR_BUCKET_REMOVE(bucket);