Author: rhuijben Date: Tue Oct 20 17:19:52 2015 New Revision: 1709651 URL: http://svn.apache.org/viewvc?rev=1709651&view=rev Log: Following up on r1709631 and r1709641, move the pump to the network logic from the http1-style connection writer to the serf__connection_flush() helper function.
The previous two patches in this set fixed issues that made it impossible to extract the code. * serf-dev/dev/outgoing.c (serf__connection_flush): Add pump argument. Move pump logic here. Make the SERF_ERROR_WAIT_CONN logic return APR_EAGAIN, which our callers handle by returning success, like the old stop_reading did. (write_to_connection): Extract code here. Update caller. * serf-dev/dev/serf_private.h (serf__connection_flush): Update prototype. Modified: serf/trunk/outgoing.c serf/trunk/serf_private.h Modified: serf/trunk/outgoing.c URL: http://svn.apache.org/viewvc/serf/trunk/outgoing.c?rev=1709651&r1=1709650&r2=1709651&view=diff ============================================================================== --- serf/trunk/outgoing.c (original) +++ serf/trunk/outgoing.c Tue Oct 20 17:19:52 2015 @@ -692,9 +692,60 @@ static apr_status_t socket_writev(serf_c return status; } -apr_status_t serf__connection_flush(serf_connection_t *conn) +apr_status_t serf__connection_flush(serf_connection_t *conn, + int pump) { apr_status_t status = APR_SUCCESS; + apr_status_t read_status = APR_SUCCESS; + + if (pump) { + serf_bucket_t *ostreamt, *ostreamh; + + status = prepare_conn_streams(conn, &ostreamt, &ostreamh); + if (status) { + return status; + } + + /* ### optimize at some point by using read_for_sendfile */ + /* TODO: now that read_iovec will effectively try to return as much + data as available, we probably don't want to read ALL_AVAIL, but + a lower number, like the size of one or a few TCP packets, the + available TCP buffer size ... */ + conn->hit_eof = 0; + read_status = serf_bucket_read_iovec(ostreamh, + SERF_READ_ALL_AVAIL, + IOV_MAX, + conn->vec, + &conn->vec_len); + + if (read_status == SERF_ERROR_WAIT_CONN) { + /* The bucket told us that it can't provide more data until + more data is read from the socket. This normally happens + during a SSL handshake. + + We should avoid looking for writability for a while so + that (hopefully) something will appear in the bucket so + we can actually write something. otherwise, we could + end up in a CPU spin: socket wants something, but we + don't have anything (and keep returning EAGAIN) */ + conn->stop_writing = 1; + conn->dirty_conn = 1; + conn->ctx->dirty_pollset = 1; + + read_status = APR_EAGAIN; + } + else if (APR_STATUS_IS_EAGAIN(read_status)) { + + /* We read some stuff, but did we read everything ? */ + if (conn->hit_eof) + read_status = APR_SUCCESS; + } + else if (SERF_BUCKET_READ_ERROR(read_status)) { + + /* Something bad happened. Propagate any errors. */ + return read_status; + } + } while (conn->vec_len && !status) { status = socket_writev(conn); @@ -708,7 +759,8 @@ apr_status_t serf__connection_flush(serf return no_more_writes(conn); } - return status; + + return status ? status : read_status; } /* write data out to the connection */ @@ -729,7 +781,6 @@ static apr_status_t write_to_connection( */ while (1) { serf_request_t *request; - int stop_reading = 0; apr_status_t status; apr_status_t read_status; serf_bucket_t *ostreamt; @@ -757,7 +808,7 @@ static apr_status_t write_to_connection( } /* If we have unwritten data, then write what we can. */ - status = serf__connection_flush(conn); + status = serf__connection_flush(conn, FALSE); if (APR_STATUS_IS_EAGAIN(status)) return APR_SUCCESS; else if (status) @@ -801,59 +852,15 @@ static apr_status_t write_to_connection( } } - /* ### optimize at some point by using read_for_sendfile */ - /* TODO: now that read_iovec will effectively try to return as much - data as available, we probably don't want to read ALL_AVAIL, but - a lower number, like the size of one or a few TCP packets, the - available TCP buffer size ... */ - conn->hit_eof = 0; - read_status = serf_bucket_read_iovec(ostreamh, - SERF_READ_ALL_AVAIL, - IOV_MAX, - conn->vec, - &conn->vec_len); - - if (read_status == SERF_ERROR_WAIT_CONN) { - - /* The bucket told us that it can't provide more data until - more data is read from the socket. This normally happens - during a SSL handshake. - - We should avoid looking for writability for a while so - that (hopefully) something will appear in the bucket so - we can actually write something. otherwise, we could - end up in a CPU spin: socket wants something, but we - don't have anything (and keep returning EAGAIN) */ - conn->stop_writing = 1; - conn->dirty_conn = 1; - conn->ctx->dirty_pollset = 1; - } - else if (APR_STATUS_IS_EAGAIN(read_status)) { - - /* We read some stuff, but should not try to read again. */ - - if (! conn->hit_eof) - stop_reading = 1; - } - else if (SERF_BUCKET_READ_ERROR(read_status)) { - - /* Something bad happened. Propagate any errors. */ - - return read_status; - } - /* If we got some data, then deliver it. */ /* ### what to do if we got no data?? is that a problem? */ - status = serf__connection_flush(conn); + status = serf__connection_flush(conn, TRUE); if (APR_STATUS_IS_EAGAIN(status)) return APR_SUCCESS; else if (status) return status; - if (read_status == SERF_ERROR_WAIT_CONN) { - stop_reading = 1; - } - else if (request && conn->hit_eof && conn->vec_len == 0) { + if (request && conn->hit_eof && conn->vec_len == 0) { /* If we hit the end of the request bucket and all of its data has * been written, then clear it out to signify that we're done * sending the request. On the next iteration through this loop: @@ -887,13 +894,9 @@ static apr_status_t write_to_connection( if (conn->probable_keepalive_limit && conn->completed_requests > conn->probable_keepalive_limit) { /* backoff for now. */ - stop_reading = 1; + return APR_SUCCESS; } } - - if (stop_reading) { - return APR_SUCCESS; - } } /* NOTREACHED */ } Modified: serf/trunk/serf_private.h URL: http://svn.apache.org/viewvc/serf/trunk/serf_private.h?rev=1709651&r1=1709650&r2=1709651&view=diff ============================================================================== --- serf/trunk/serf_private.h (original) +++ serf/trunk/serf_private.h Tue Oct 20 17:19:52 2015 @@ -511,7 +511,8 @@ serf_request_t *serf__ssltunnel_request_ serf_request_setup_t setup, void *setup_baton); void serf__connection_set_pipelining(serf_connection_t *conn, int enabled); -apr_status_t serf__connection_flush(serf_connection_t *conn); +apr_status_t serf__connection_flush(serf_connection_t *conn, + int pump); apr_status_t serf__provide_credentials(serf_context_t *ctx, char **username,