static rstatus_t conn_recv_queue(struct conn *conn) { struct mbuf *mbuf; size_t msize; /* current mbuf size */ ssize_t n; mbuf = STAILQ_LAST(&conn->recv_queue, mbuf, next); if (mbuf == NULL || mbuf_full(mbuf)) { mbuf = mbuf_get(); if (mbuf == NULL) { return NC_ENOMEM; } mbuf_insert(&conn->recv_queue, mbuf); } msize = mbuf_size(mbuf); ASSERT(msize > 0); n = conn_recv_buf(conn, mbuf->last, msize); if (n < 0) { if (n == NC_EAGAIN) { return NC_OK; } return NC_ERROR; } ASSERT((mbuf->last + n) <= mbuf->end); mbuf->last += n; return NC_OK; }
struct mbuf *mbuf_queue_get(struct context *ctx, struct mhdr *q) { struct mbuf *buf = NULL; if (!STAILQ_EMPTY(q)) buf = STAILQ_LAST(q, mbuf, next); if (buf == NULL || mbuf_full(buf)) { buf = mbuf_get(ctx); STAILQ_INSERT_TAIL(q, buf, next); } return buf; }
/* * Copy n bytes from memory area pos to mbuf. * * The memory areas should not overlap and the mbuf should have * enough space for n bytes. */ void mbuf_copy(struct mbuf *mbuf, uint8_t *pos, size_t n) { if (n == 0) { return; } /* mbuf has space for n bytes */ ASSERT(!mbuf_full(mbuf) && n <= mbuf_size(mbuf)); /* no overlapping copy */ ASSERT(pos < mbuf->start || pos >= mbuf->end); dn_memcpy(mbuf->last, pos, n); mbuf->last += n; }
static void direct_reply(struct context *ctx, struct conn *conn, struct msg *smsg, char *_msg) { struct mbuf *mbuf; int n; struct msg *msg = msg_get(conn, true, conn->redis); if (msg == NULL) { conn->err = errno; conn->done = 1; return; } mbuf = STAILQ_LAST(&msg->mhdr, mbuf, next); if (mbuf == NULL || mbuf_full(mbuf)) { mbuf = mbuf_get(); if (mbuf != NULL) { mbuf_insert(&msg->mhdr, mbuf); msg->pos = mbuf->pos; } } if (mbuf == NULL) { conn->err = errno; conn->done = 1; msg_put(msg); return; } smsg->peer = msg; msg->peer = smsg; msg->request = 0; n = (int)strlen(_msg); memcpy(mbuf->last, _msg, (size_t)n); mbuf->last += n; msg->mlen += (uint32_t)n; smsg->done = 1; event_add_out(ctx->evb, conn); conn->enqueue_outq(ctx, conn, smsg); }
/* * note: we should not call conn_add_out here. * because we may call append many times. */ rstatus_t conn_sendq_append(struct conn *conn, char *pos, size_t n) { struct mbuf *mbuf; size_t bytes = 0; size_t len; while (bytes < n) { mbuf = STAILQ_LAST(&conn->send_queue, mbuf, next); if ((mbuf == NULL) || mbuf_full(mbuf)) { mbuf = mbuf_get(); if (mbuf == NULL) { return NC_ENOMEM; } mbuf_insert(&conn->send_queue, mbuf); } len = MIN(mbuf_size(mbuf), n - bytes); mbuf_copy(mbuf, (uint8_t *)pos + bytes, len); bytes += len; } return NC_OK; }