int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ if (aux == NULL && c->flags & REDIS_BLOCK) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) return REDIS_ERR; } while (!wdone); /* Read until there is a reply */ do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } /* Set reply object */ if (reply != NULL) *reply = aux; return REDIS_OK; }
void RedisSelect::readData() { redisReply *reply = nullptr; if (redisGetReply(m_subscribe->getContext(), reinterpret_cast<void**>(&reply)) != REDIS_OK) throw std::runtime_error("Unable to read redis reply"); freeReplyObject(reply); m_queueLength++; reply = nullptr; int status; do { status = redisGetReplyFromReader(m_subscribe->getContext(), reinterpret_cast<void**>(&reply)); if(reply != nullptr && status == REDIS_OK) { m_queueLength++; freeReplyObject(reply); } } while(reply != nullptr && status == REDIS_OK); if (status != REDIS_OK) { throw std::runtime_error("Unable to read redis reply"); } }
int swss::NotificationConsumer::readCache() { SWSS_LOG_ENTER(); if (m_queue.size() > 0) { return Selectable::DATA; } redisReply *reply = NULL; if (redisGetReplyFromReader(m_subscribe->getContext(), (void**)&reply) != REDIS_OK) { SWSS_LOG_ERROR("failed to read redis reply on channel %s", m_channel.c_str()); return Selectable::ERROR; } else if (reply != NULL) { RedisReply r(reply); processReply(reply); return Selectable::DATA; } return Selectable::NODATA; }
static int __get_reply(redisParentContext *pc, VALUE *reply) { redisContext *c = pc->context; int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) { /* Protocol error */ return -1; } if (aux == NULL) { /* Write until the write buffer is drained */ while (!wdone) { errno = 0; if (redisBufferWrite(c, &wdone) == REDIS_ERR) { /* Socket error */ return -1; } if (errno == EAGAIN) { int writable = 0; if (__wait_writable(c->fd, pc->timeout, &writable) < 0) { rb_sys_fail(0); } if (!writable) { errno = EAGAIN; rb_sys_fail(0); } } } /* Read until there is a full reply */ while (aux == NULL) { errno = 0; if (redisBufferRead(c) == REDIS_ERR) { /* Socket error */ return -1; } if (errno == EAGAIN) { int readable = 0; if (__wait_readable(c->fd, pc->timeout, &readable) < 0) { rb_sys_fail(0); } if (!readable) { errno = EAGAIN; rb_sys_fail(0); } /* Retry */ continue; } if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) { /* Protocol error */ return -1; } } } /* Set reply object */ if (reply != NULL) { *reply = (VALUE)aux; } return 0; }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; #ifndef HIREDIS_WIN nread = read(c->fd,buf,sizeof(buf)); if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #else nread = recv(c->fd,buf,sizeof(buf),0); if (nread == -1) { errno = WSAGetLastError(); if ((errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK) && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #endif } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; } /* Write the output buffer to the socket. * * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was * succesfully written to the socket. When the buffer is empty after the * write operation, "done" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->errstr to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { int nwritten; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if (sdslen(c->obuf) > 0) { #ifndef HIREDIS_WIN nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); if (nwritten == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #else nwritten = send(c->fd,c->obuf,sdslen(c->obuf),0); if (nwritten == -1) { errno = WSAGetLastError(); if ((errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK) && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #endif } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { c->obuf = sdsrange(c->obuf,nwritten,-1); } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; } /* Internal helper function to try and get a reply from the reader, * or set an error in the context otherwise. */ int redisGetReplyFromReader(redisContext *c, void **reply) { if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } return REDIS_OK; } int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ if (aux == NULL && c->flags & REDIS_BLOCK) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) return REDIS_ERR; } while (!wdone); /* Read until there is a reply */ do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } /* Set reply object */ if (reply != NULL) *reply = aux; return REDIS_OK; } /* Helper function for the redisAppendCommand* family of functions. * * Write a formatted command to the output buffer. When this family * is used, you need to call redisGetReply yourself to retrieve * the reply (or replies in pub/sub). */ int __redisAppendCommand(redisContext *c, char *cmd, size_t len) { sds newbuf; newbuf = sdscatlen(c->obuf,cmd,len); if (newbuf == NULL) { __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); return REDIS_ERR; } c->obuf = newbuf; return REDIS_OK; }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; #ifdef WIN32 nread = recv(c->fd,buf,sizeof(buf),0); #else nread = read(c->fd,buf,sizeof(buf)); #endif if (nread == -1) { #ifdef WIN32 errno = WSAGetLastError(); if ((errno == WSAEWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == WSAEINTR)) { #else if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { #endif /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; } /* Write the output buffer to the socket. * * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was * succesfully written to the socket. When the buffer is empty after the * write operation, "done" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->errstr to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { int nwritten; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if (sdslen(c->obuf) > 0) { #ifdef WIN32 nwritten = send(c->fd,c->obuf,sdslen(c->obuf),0); #else nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); #endif if (nwritten == -1) { #ifdef WIN32 errno = WSAGetLastError(); if ((errno == WSAEWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == WSAEINTR)) { #else if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { #endif /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { c->obuf = sdsrange(c->obuf,nwritten,-1); } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; } /* Internal helper function to try and get a reply from the reader, * or set an error in the context otherwise. */ int redisGetReplyFromReader(redisContext *c, void **reply) { if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } return REDIS_OK; } int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ if (aux == NULL && c->flags & REDIS_BLOCK) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) return REDIS_ERR; } while (!wdone); /* Read until there is a reply */ do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } /* Set reply object */ if (reply != NULL) *reply = aux; return REDIS_OK; }
int redisc_exec_pipelined(redisc_server_t *rsrv) { redisc_reply_t *rpl; int i; LM_DBG("redis server: %.*s\n", rsrv->sname->len,rsrv->sname->s); /* if server is disabled do nothing unless the disable time has passed */ if (redis_check_server(rsrv)) { goto srv_disabled; } if (rsrv->piped.pending_commands == 0) { LM_WARN("call for redis_cmd without any pipelined commands\n"); return -1; } if(rsrv->ctxRedis==NULL) { LM_ERR("no redis context for server: %.*s\n", rsrv->sname->len,rsrv->sname->s); goto error_exec; } /* send the commands and retrieve the first reply */ rpl=rsrv->piped.replies[0]; if(rpl->rplRedis!=NULL) { /* clean up previous redis reply */ freeReplyObject(rpl->rplRedis); rpl->rplRedis = NULL; } redisc_create_pipelined_message(rsrv); redisGetReply(rsrv->ctxRedis, (void**) &rpl->rplRedis); if (rpl->rplRedis == NULL) { /* null reply, reconnect and try again */ if (rsrv->ctxRedis->err) { LM_ERR("Redis error: %s\n", rsrv->ctxRedis->errstr); } if (redisc_create_pipelined_message(rsrv) == 0) { redisGetReply(rsrv->ctxRedis, (void**) &rpl->rplRedis); if (rpl->rplRedis == NULL) { redis_count_err_and_disable(rsrv); LM_ERR("Unable to read reply\n"); goto error_exec; } } else { redis_count_err_and_disable(rsrv); goto error_exec; } } LM_DBG("reply is [%s]",rpl->rplRedis->str); /* replies are received just retrieve them */ for (i=1;i<rsrv->piped.pending_commands;i++) { rpl=rsrv->piped.replies[i]; if(rpl->rplRedis!=NULL) { /* clean up previous redis reply */ freeReplyObject(rpl->rplRedis); rpl->rplRedis = NULL; } if (redisGetReplyFromReader(rsrv->ctxRedis, (void**) &rpl->rplRedis) != REDIS_OK) { LM_ERR("Unable to read reply\n"); continue; } LM_DBG("reply is [%s]",rpl->rplRedis->str); } redisc_free_pipelined_cmds(rsrv); rsrv->disable.consecutive_errors = 0; return 0; error_exec: redisc_free_pipelined_cmds(rsrv); return -1; srv_disabled: redisc_free_pipelined_cmds(rsrv); return -2; }