int ringbuffer_memcpy(ringbuffer_t *dst, ringbuffer_t *src, lcb_size_t nbytes) { ringbuffer_t copy = *src; struct lcb_iovec_st iov[2]; int ii = 0; lcb_size_t towrite = nbytes; lcb_size_t toread, nb; if (nbytes > ringbuffer_get_nbytes(src)) { /* EINVAL */ return -1; } if (!ringbuffer_ensure_capacity(dst, nbytes)) { /* Failed to allocate space */ return -1; } ringbuffer_get_iov(dst, RINGBUFFER_WRITE, iov); toread = minimum(iov[ii].iov_len, nbytes); do { assert(ii < 2); nb = ringbuffer_read(©, iov[ii].iov_base, toread); toread -= nb; towrite -= nb; ++ii; } while (towrite > 0); ringbuffer_produced(dst, nbytes); return 0; }
static int do_fill_input_buffer(libcouchbase_server_t *c) { struct libcouchbase_iovec_st iov[2]; libcouchbase_ssize_t nr; if (!ringbuffer_ensure_capacity(&c->input, 8192)) { libcouchbase_error_handler(c->instance, LIBCOUCHBASE_CLIENT_ENOMEM, NULL); return -1; } ringbuffer_get_iov(&c->input, RINGBUFFER_WRITE, iov); nr = c->instance->io->recvv(c->instance->io, c->sock, iov, 2); if (nr == -1) { switch (c->instance->io->error) { case EINTR: break; case EWOULDBLOCK: return 0; default: libcouchbase_failout_server(c, LIBCOUCHBASE_NETWORK_ERROR); return -1; } } else if (nr == 0) { assert((iov[0].iov_len + iov[1].iov_len) != 0); /* TODO stash error message somewhere * "Connection closed... we should resend to other nodes or reconnect!!" */ libcouchbase_failout_server(c, LIBCOUCHBASE_NETWORK_ERROR); return -1; } else { ringbuffer_produced(&c->input, (libcouchbase_size_t)nr); } return 1; }
void lcb_sockrw_v1_onread_common(lcb_sockdata_t *sock, ringbuffer_t **dst, lcb_ssize_t nr) { struct lcb_buf_info *bi = &sock->read_buffer; lcb_assert(*dst == NULL); *dst = bi->ringbuffer; memset(bi, 0, sizeof(*bi)); sock->is_reading = 0; if (nr > 0) { ringbuffer_produced(*dst, nr); } }
lcb_sockrw_status_t lcb_sockrw_v0_read(lcb_connection_t conn, ringbuffer_t *buf) { struct lcb_iovec_st iov[2]; lcb_ssize_t nr; lcb_io_opt_t io = conn->io; if (!ringbuffer_ensure_capacity(buf, conn->settings ? conn->settings->rbufsize : LCB_DEFAULT_RBUFSIZE)) { return LCB_SOCKRW_GENERIC_ERROR; } ringbuffer_get_iov(buf, RINGBUFFER_WRITE, iov); nr = io->v.v0.recvv(io, conn->sockfd, iov, 2); if (nr == -1) { switch (io->v.v0.error) { case EINTR: break; case EWOULDBLOCK: #ifdef USE_EAGAIN case EAGAIN: #endif return LCB_SOCKRW_WOULDBLOCK; default: return LCB_SOCKRW_IO_ERROR; return -1; } } else if (nr == 0) { lcb_assert((iov[0].iov_len + iov[1].iov_len) != 0); /* TODO stash error message somewhere * "Connection closed... we should resend to other nodes or reconnect!!" */ return LCB_SOCKRW_SHUTDOWN; } else { ringbuffer_produced(buf, (lcb_size_t)nr); } return LCB_SOCKRW_READ; }