apr_status_t serf_pump__write()

in src/pump.c [279:364]


apr_status_t serf_pump__write(serf_pump_t *pump,
                              bool fetch_new)
{
    apr_status_t status = APR_SUCCESS;
    apr_status_t read_status = APR_SUCCESS;

    pump->hit_eof = FALSE;

    while (status == APR_SUCCESS) {

        /* First try to write out what is already stored in the
           connection vecs. */
        while (pump->vec_len && !status) {
            status = socket_writev(pump);

            /* If the write would have blocked, then we're done.
             * Don't try to write anything else to the socket.
             */
            if (APR_STATUS_IS_EPIPE(status)
                || APR_STATUS_IS_ECONNRESET(status)
                || APR_STATUS_IS_ECONNABORTED(status))
              return no_more_writes(pump);
        }

        if (status || !fetch_new) {

            /* If we couldn't write everything that we tried,
               make sure that we will receive a write event next time */
            if (APR_STATUS_IS_EAGAIN(status)
                && !pump->io->dirty_conn
                && !(pump->io->reqevents & APR_POLLOUT))
            {
                serf_io__set_pollset_dirty(pump->io);
            }
            return status;
        }
        else if (read_status || pump->vec_len || pump->hit_eof)
            return read_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 ... */
        pump->hit_eof = false;
        read_status = serf_bucket_read_iovec(pump->ostream_head,
                                             SERF_READ_ALL_AVAIL,
                                             COUNT_OF(pump->vec),
                                             pump->vec,
                                             &pump->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) */

            serf__log(LOGLVL_INFO, LOGCOMP_CONN, __FILE__, pump->config,
                      "Output stream requested temporary write delay "
                      "on 0x%p\n", pump->io->u.v);

            pump->stop_writing = true;
            serf_io__set_pollset_dirty(pump->io);

            read_status = APR_EAGAIN;
        }
        else if (APR_STATUS_IS_EAGAIN(read_status)) {

            /* We read some stuff, but did we read everything ? */
            if (pump->hit_eof)
                read_status = APR_SUCCESS;
        }
        else if (SERF_BUCKET_READ_ERROR(read_status)) {

            /* Something bad happened. Propagate any errors. */
            return read_status;
        }
    }

    return status;
}