Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;

#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;
}
Exemplo n.º 7
0
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;
}