dec = createStringObject(buf,strlen(buf));
return dec;
} else {
- redisAssert(1 != 1);
+ redisPanic("Unknown encoding type");
}
}
}
}
-static int getDoubleFromObject(redisClient *c, robj *o, double *value) {
- double parsedValue;
- char *eptr = NULL;
+static int getDoubleFromObject(robj *o, double *target) {
+ double value;
+ char *eptr;
- if (o && o->type != REDIS_STRING) {
- addReplySds(c,sdsnew("-ERR value is not a double\r\n"));
- return REDIS_ERR;
+ if (o == NULL) {
+ value = 0;
+ } else {
+ redisAssert(o->type == REDIS_STRING);
+ if (o->encoding == REDIS_ENCODING_RAW) {
+ value = strtod(o->ptr, &eptr);
+ if (eptr[0] != '\0') return REDIS_ERR;
+ } else if (o->encoding == REDIS_ENCODING_INT) {
+ value = (long)o->ptr;
+ } else {
+ redisAssert(1 != 1);
+ }
}
- if (o == NULL)
- parsedValue = 0;
- else if (o->encoding == REDIS_ENCODING_RAW)
- parsedValue = strtod(o->ptr, &eptr);
- else if (o->encoding == REDIS_ENCODING_INT)
- parsedValue = (long)o->ptr;
- else
- redisAssert(1 != 1);
+ *target = value;
+ return REDIS_OK;
+}
- if (eptr != NULL && *eptr != '\0') {
- addReplySds(c,sdsnew("-ERR value is not a double\r\n"));
+static int getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const char *msg) {
+ double value;
+ if (getDoubleFromObject(o, &value) != REDIS_OK) {
+ if (msg != NULL) {
+ addReplySds(c, sdscatprintf(sdsempty(), "-ERR %s\r\n", msg));
+ } else {
+ addReplySds(c, sdsnew("-ERR value is not a double\r\n"));
+ }
return REDIS_ERR;
}
- *value = parsedValue;
-
+ *target = value;
return REDIS_OK;
}
-static int getLongLongFromObject(redisClient *c, robj *o, long long *value) {
- long long parsedValue;
- char *eptr = NULL;
+static int getLongLongFromObject(robj *o, long long *target) {
+ long long value;
+ char *eptr;
- if (o && o->type != REDIS_STRING) {
- addReplySds(c,sdsnew("-ERR value is not an integer\r\n"));
- return REDIS_ERR;
+ if (o == NULL) {
+ value = 0;
+ } else {
+ redisAssert(o->type == REDIS_STRING);
+ if (o->encoding == REDIS_ENCODING_RAW) {
+ value = strtoll(o->ptr, &eptr, 10);
+ if (eptr[0] != '\0') return REDIS_ERR;
+ } else if (o->encoding == REDIS_ENCODING_INT) {
+ value = (long)o->ptr;
+ } else {
+ redisAssert(1 != 1);
+ }
}
- if (o == NULL)
- parsedValue = 0;
- else if (o->encoding == REDIS_ENCODING_RAW)
- parsedValue = strtoll(o->ptr, &eptr, 10);
- else if (o->encoding == REDIS_ENCODING_INT)
- parsedValue = (long)o->ptr;
- else
- redisAssert(1 != 1);
+ *target = value;
+ return REDIS_OK;
+}
- if (eptr != NULL && *eptr != '\0') {
- addReplySds(c,sdsnew("-ERR value is not an integer\r\n"));
+static int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg) {
+ long long value;
+ if (getLongLongFromObject(o, &value) != REDIS_OK) {
+ if (msg != NULL) {
+ addReplySds(c, sdscatprintf(sdsempty(), "-ERR %s\r\n", msg));
+ } else {
+ addReplySds(c, sdsnew("-ERR value is not an integer\r\n"));
+ }
return REDIS_ERR;
}
- *value = parsedValue;
-
+ *target = value;
return REDIS_OK;
}
-static int getLongFromObject(redisClient *c, robj *o, long *value) {
- long long actualValue;
-
- if (getLongLongFromObject(c, o, &actualValue) != REDIS_OK) return REDIS_ERR;
+static int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg) {
+ long long value;
- if (actualValue < LONG_MIN || actualValue > LONG_MAX) {
- addReplySds(c,sdsnew("-ERR value is out of range\r\n"));
+ if (getLongLongFromObjectOrReply(c, o, &value, msg) != REDIS_OK) return REDIS_ERR;
+ if (value < LONG_MIN || value > LONG_MAX) {
+ if (msg != NULL) {
+ addReplySds(c, sdscatprintf(sdsempty(), "-ERR %s\r\n", msg));
+ } else {
+ addReplySds(c, sdsnew("-ERR value is out of range\r\n"));
+ }
return REDIS_ERR;
}
- *value = actualValue;
-
+ *target = value;
return REDIS_OK;
}
o = lookupKeyWrite(c->db,c->argv[1]);
- if (getLongLongFromObject(c, o, &value) != REDIS_OK) return;
+ if (getLongLongFromObjectOrReply(c, o, &value, NULL) != REDIS_OK) return;
value += incr;
o = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%lld",value));
static void incrbyCommand(redisClient *c) {
long long incr;
- if (getLongLongFromObject(c, c->argv[2], &incr) != REDIS_OK) return;
-
+ if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
incrDecrCommand(c,incr);
}
static void decrbyCommand(redisClient *c) {
long long incr;
- if (getLongLongFromObject(c, c->argv[2], &incr) != REDIS_OK) return;
-
+ if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
incrDecrCommand(c,-incr);
}
static void zaddCommand(redisClient *c) {
double scoreval;
- if (getDoubleFromObject(c, c->argv[2], &scoreval) != REDIS_OK) return;
-
+ if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,0);
}
static void zincrbyCommand(redisClient *c) {
double scoreval;
- if (getDoubleFromObject(c, c->argv[2], &scoreval) != REDIS_OK) return;
-
+ if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1);
}
robj *zsetobj;
zset *zs;
- if ((getDoubleFromObject(c, c->argv[2], &min) != REDIS_OK) ||
- (getDoubleFromObject(c, c->argv[3], &max) != REDIS_OK)) return;
+ if ((getDoubleFromObjectOrReply(c, c->argv[2], &min, NULL) != REDIS_OK) ||
+ (getDoubleFromObjectOrReply(c, c->argv[3], &max, NULL) != REDIS_OK)) return;
if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
checkType(c,zsetobj,REDIS_ZSET)) return;
robj *zsetobj;
zset *zs;
- if ((getLongFromObject(c, c->argv[2], &start) != REDIS_OK) ||
- (getLongFromObject(c, c->argv[3], &end) != REDIS_OK)) return;
+ if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
+ (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;
if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
checkType(c,zsetobj,REDIS_ZSET)) return;
if (remaining >= (zsetnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
j++; remaining--;
for (i = 0; i < zsetnum; i++, j++, remaining--) {
- if (getDoubleFromObject(c, c->argv[j], &src[i].weight) != REDIS_OK)
+ if (getDoubleFromObjectOrReply(c, c->argv[j], &src[i].weight, NULL) != REDIS_OK)
return;
}
} else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
zskiplistNode *ln;
robj *ele;
- if ((getLongFromObject(c, c->argv[2], &start) != REDIS_OK) ||
- (getLongFromObject(c, c->argv[3], &end) != REDIS_OK)) return;
+ if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
+ (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;
if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,"withscores")) {
withscores = 1;
long long value, incr;
robj *o, *current, *new;
- if (getLongLongFromObject(c,c->argv[3],&incr) != REDIS_OK) return;
+ if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != REDIS_OK) return;
if ((o = hashLookupWriteOrCreate(c,c->argv[1])) == NULL) return;
if ((current = hashGet(o,c->argv[2])) != NULL) {
if (current->encoding == REDIS_ENCODING_RAW)
cmp = strcoll(so1->u.cmpobj->ptr,so2->u.cmpobj->ptr);
}
} else {
- /* Compare elements directly. Note that these objects already
- * need to be non-encoded (see sortCommand). */
- cmp = strcoll(so1->obj->ptr,so2->obj->ptr);
+ /* Compare elements directly. */
+ cmp = compareStringObjects(so1->obj,so2->obj);
}
}
return server.sort_desc ? -cmp : cmp;
}
if (alpha) {
- vector[j].u.cmpobj = getDecodedObject(byval);
+ if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);
} else {
if (byval->encoding == REDIS_ENCODING_RAW) {
vector[j].u.score = strtod(byval->ptr,NULL);
dictEntry *de;
time_t seconds;
- if (getLongFromObject(c, param, &seconds) != REDIS_OK) return;
+ if (getLongFromObjectOrReply(c, param, &seconds, NULL) != REDIS_OK) return;
seconds -= offset;
addReply(c,shared.ok);
}
+/* Send a MULTI command to all the slaves and AOF file. Check the execCommand
+ * implememntation for more information. */
+static void execCommandReplicateMulti(redisClient *c) {
+ struct redisCommand *cmd;
+ robj *multistring = createStringObject("MULTI",5);
+
+ cmd = lookupCommand("multi");
+ if (server.appendonly)
+ feedAppendOnlyFile(cmd,c->db->id,&multistring,1);
+ if (listLength(server.slaves))
+ replicationFeedSlaves(server.slaves,c->db->id,&multistring,1);
+ decrRefCount(multistring);
+}
+
static void execCommand(redisClient *c) {
int j;
robj **orig_argv;
return;
}
+ /* Replicate a MULTI request now that we are sure the block is executed.
+ * This way we'll deliver the MULTI/..../EXEC block as a whole and
+ * both the AOF and the replication link will have the same consistency
+ * and atomicity guarantees. */
+ execCommandReplicateMulti(c);
+
+ /* Exec all the queued commands */
orig_argv = c->argv;
orig_argc = c->argc;
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",c->mstate.count));
freeClientMultiState(c);
initClientMultiState(c);
c->flags &= (~REDIS_MULTI);
+ /* Make sure the EXEC command is always replicated / AOF, since we
+ * always send the MULTI command (we can't know beforehand if the
+ * next operations will contain at least a modification to the DB). */
+ server.dirty++;
}
/* =========================== Blocking Operations ========================= */
static void _redisPanic(char *msg, char *file, int line) {
redisLog(REDIS_WARNING,"!!! Software Failure. Press left mouse button to continue");
- redisLog(REDIS_WARNING,"Guru Mediation: %s #%s:%d",msg,file,line);
+ redisLog(REDIS_WARNING,"Guru Meditation: %s #%s:%d",msg,file,line);
#ifdef HAVE_BACKTRACE
redisLog(REDIS_WARNING,"(forcing SIGSEGV in order to print the stack trace)");
*((char*)-1) = 'x';
void linuxOvercommitMemoryWarning(void) {
if (linuxOvercommitMemoryValue() == 0) {
- redisLog(REDIS_WARNING,"WARNING overcommit_memory is set to 0! Background save may fail under low condition memory. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.");
+ redisLog(REDIS_WARNING,"WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.");
}
}
#endif /* __linux__ */