Handle OOM when doing blocking requests

This commit is contained in:
Pieter Noordhuis 2011-04-21 21:34:43 +02:00
parent e932709a66
commit 8419b060f2
2 changed files with 56 additions and 31 deletions

View File

@ -1107,31 +1107,65 @@ int redisGetReply(redisContext *c, void **reply) {
* is used, you need to call redisGetReply yourself to retrieve * is used, you need to call redisGetReply yourself to retrieve
* the reply (or replies in pub/sub). * the reply (or replies in pub/sub).
*/ */
void __redisAppendCommand(redisContext *c, char *cmd, size_t len) { int __redisAppendCommand(redisContext *c, char *cmd, size_t len) {
c->obuf = sdscatlen(c->obuf,cmd,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;
} }
void redisvAppendCommand(redisContext *c, const char *format, va_list ap) { int redisvAppendCommand(redisContext *c, const char *format, va_list ap) {
char *cmd; char *cmd;
int len; int len;
len = redisvFormatCommand(&cmd,format,ap); len = redisvFormatCommand(&cmd,format,ap);
__redisAppendCommand(c,cmd,len); if (len == -1) {
__redisSetError(c,REDIS_ERR_OOM,"Out of memory");
return REDIS_ERR;
}
if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
free(cmd);
return REDIS_ERR;
}
free(cmd); free(cmd);
return REDIS_OK;
} }
void redisAppendCommand(redisContext *c, const char *format, ...) { int redisAppendCommand(redisContext *c, const char *format, ...) {
va_list ap; va_list ap;
int ret;
va_start(ap,format); va_start(ap,format);
redisvAppendCommand(c,format,ap); ret = redisvAppendCommand(c,format,ap);
va_end(ap); va_end(ap);
return ret;
} }
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
char *cmd; char *cmd;
int len; int len;
len = redisFormatCommandArgv(&cmd,argc,argv,argvlen); len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);
__redisAppendCommand(c,cmd,len); if (len == -1) {
__redisSetError(c,REDIS_ERR_OOM,"Out of memory");
return REDIS_ERR;
}
if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
free(cmd);
return REDIS_ERR;
}
free(cmd); free(cmd);
return REDIS_OK;
} }
/* Helper function for the redisCommand* family of functions. /* Helper function for the redisCommand* family of functions.
@ -1145,26 +1179,21 @@ void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const
* otherwise. When NULL is returned in a blocking context, the error field * otherwise. When NULL is returned in a blocking context, the error field
* in the context will be set. * in the context will be set.
*/ */
static void *__redisCommand(redisContext *c, char *cmd, size_t len) { static void *__redisBlockForReply(redisContext *c) {
void *aux = NULL; void *reply;
__redisAppendCommand(c,cmd,len);
if (c->flags & REDIS_BLOCK) { if (c->flags & REDIS_BLOCK) {
if (redisGetReply(c,&aux) == REDIS_OK) if (redisGetReply(c,&reply) != REDIS_OK)
return aux; return NULL;
return NULL; return reply;
} }
return NULL; return NULL;
} }
void *redisvCommand(redisContext *c, const char *format, va_list ap) { void *redisvCommand(redisContext *c, const char *format, va_list ap) {
char *cmd; if (redisvAppendCommand(c,format,ap) != REDIS_OK)
int len; return NULL;
void *reply = NULL; return __redisBlockForReply(c);
len = redisvFormatCommand(&cmd,format,ap);
reply = __redisCommand(c,cmd,len);
free(cmd);
return reply;
} }
void *redisCommand(redisContext *c, const char *format, ...) { void *redisCommand(redisContext *c, const char *format, ...) {
@ -1177,11 +1206,7 @@ void *redisCommand(redisContext *c, const char *format, ...) {
} }
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
char *cmd; if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)
int len; return NULL;
void *reply = NULL; return __redisBlockForReply(c);
len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);
reply = __redisCommand(c,cmd,len);
free(cmd);
return reply;
} }

View File

@ -184,9 +184,9 @@ int redisGetReplyFromReader(redisContext *c, void **reply);
/* Write a command to the output buffer. Use these functions in blocking mode /* Write a command to the output buffer. Use these functions in blocking mode
* to get a pipeline of commands. */ * to get a pipeline of commands. */
void redisvAppendCommand(redisContext *c, const char *format, va_list ap); int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
void redisAppendCommand(redisContext *c, const char *format, ...); int redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
/* Issue a command to Redis. In a blocking context, it is identical to calling /* Issue a command to Redis. In a blocking context, it is identical to calling
* redisAppendCommand, followed by redisGetReply. The function will return * redisAppendCommand, followed by redisGetReply. The function will return