ngx_int_t
ngx_http_rds_csv_output_bufs(ngx_http_request_t *r,
    ngx_http_rds_csv_ctx_t *ctx)
{
    ngx_int_t                rc;
    ngx_chain_t             *cl;

    dd("entered output chain");

    if (ctx->seen_stream_end) {
        ctx->seen_stream_end = 0;

        if (ctx->avail_out) {
            cl = ngx_alloc_chain_link(r->pool);
            if (cl == NULL) {
                return NGX_ERROR;
            }

            cl->buf = ctx->out_buf;
            cl->next = NULL;
            *ctx->last_out = cl;
            ctx->last_out = &cl->next;

            ctx->avail_out = 0;
        }
    }

    dd_dump_chain_size();

    for ( ;; ) {
        if (ctx->out == NULL) {
            /* fprintf(stderr, "\n"); */
            return NGX_OK;
        }

        /* fprintf(stderr, "XXX Relooping..."); */

        rc = ngx_http_rds_csv_next_body_filter(r, ctx->out);

        if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
            return rc;
        }

#if defined(nginx_version) && nginx_version >= 1001004
        ngx_chain_update_chains(r->pool, &ctx->free_bufs, &ctx->busy_bufs,
                                &ctx->out, ctx->tag);
#else
        ngx_chain_update_chains(&ctx->free_bufs, &ctx->busy_bufs, &ctx->out,
                                ctx->tag);
#endif

        ctx->last_out = &ctx->out;
    }

    /* impossible to reach here */
    return NGX_ERROR;
}
ngx_int_t
ngx_http_drizzle_output_bufs(ngx_http_request_t *r,
        ngx_http_upstream_drizzle_peer_data_t *dp)
{
    ngx_http_upstream_t                    *u = r->upstream;
    ngx_int_t                               rc;
    ngx_str_t                               key, value;
    ngx_http_drizzle_loc_conf_t            *dlcf;
    ngx_chain_t                            *cl;

    dd("enter");
    dd_dump_chain_size();

    if (dp->seen_stream_end) {
        dp->seen_stream_end = 0;

        if (dp->avail_out) {
            cl = ngx_alloc_chain_link(r->pool);
            if (cl == NULL) {
                return NGX_ERROR;
            }

            cl->buf = dp->out_buf;
            cl->next = NULL;
            *dp->last_out = cl;
            dp->last_out = &cl->next;

            dp->avail_out = 0;
        }
    }

    if ( ! u->header_sent && u->out_bufs) {
        ngx_http_clear_content_length(r);

        r->headers_out.status = NGX_HTTP_OK;

        /* set the Content-Type header */

        r->headers_out.content_type.data =
            (u_char *) rds_content_type;

        r->headers_out.content_type.len =
            rds_content_type_len;

        r->headers_out.content_type_len =
            rds_content_type_len;

        r->headers_out.content_type_lowcase = NULL;

        dlcf = ngx_http_get_module_loc_conf(r, ngx_http_drizzle_module);

        if (dlcf->enable_module_header) {
            /* set the X-Resty-DBD-Module header */

            key.data = (u_char *) ngx_http_drizzle_module_header_key;
            key.len  = ngx_http_drizzle_module_header_key_len;

            value.data = (u_char *) ngx_http_drizzle_module_header_val;
            value.len = ngx_http_drizzle_module_header_val_len;

            rc = ngx_http_drizzle_set_header(r, &key, &value);

            if (rc != NGX_OK) {
                return NGX_ERROR;
            }
        }

        rc = ngx_http_send_header(r);

        if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
            return rc;
        }

        u->header_sent = 1;
    }


    for ( ;; ) {
        if (u->out_bufs == NULL) {
            return NGX_OK;
        }

#if 0
        {
            int              n;
            ngx_chain_t     *cl;

            for (n = 0, cl = u->out_bufs; cl; cl = cl->next, n++) {
            }

            fprintf(stderr, "XXX chain size: %d\n", n);
        }
#endif

        rc = ngx_http_output_filter(r, u->out_bufs);

        if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
            return rc;
        }

        ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs, &u->out_bufs, u->output.tag);

        dp->last_out = &u->out_bufs;
    }

    return NGX_ERROR;
}