* POSSIBILITY OF SUCH DAMAGE.
*/
-#define REDIS_VERSION "1.1.90"
+#define REDIS_VERSION "1.1.93"
#include "fmacros.h"
#include "config.h"
char *appendfilename;
char *requirepass;
int shareobjects;
+ int rdbcompression;
/* Replication related */
int isslave;
char *masterauth;
close(fd);
goto cleanup;
}
- redisLog(REDIS_WARNING,"Parent diff flushed into the new append log file with success");
+ redisLog(REDIS_NOTICE,"Parent diff flushed into the new append log file with success (%lu bytes)",sdslen(server.bgrewritebuf));
/* Now our work is to rename the temp file into the stable file. And
* switch the file descriptor used by the server for append only. */
if (rename(tmpfile,server.appendfilename) == -1) {
server.appendfilename = "appendonly.aof";
server.requirepass = NULL;
server.shareobjects = 0;
+ server.rdbcompression = 1;
server.sharingpoolsize = 1024;
server.maxclients = 0;
server.maxmemory = 0;
if ((server.shareobjects = yesnotoi(argv[1])) == -1) {
err = "argument must be 'yes' or 'no'"; goto loaderr;
}
+ } else if (!strcasecmp(argv[0],"rdbcompression") && argc == 2) {
+ if ((server.rdbcompression = yesnotoi(argv[1])) == -1) {
+ err = "argument must be 'yes' or 'no'"; goto loaderr;
+ }
} else if (!strcasecmp(argv[0],"shareobjectspoolsize") && argc == 2) {
server.sharingpoolsize = atoi(argv[1]);
if (server.sharingpoolsize < 1) {
return 1;
} else if ((cmd->arity > 0 && cmd->arity != c->argc) ||
(c->argc < -cmd->arity)) {
- addReplySds(c,sdsnew("-ERR wrong number of arguments\r\n"));
+ addReplySds(c,
+ sdscatprintf(sdsempty(),
+ "-ERR wrong number of arguments for '%s' command\r\n",
+ cmd->name));
resetClient(c);
return 1;
} else if (server.maxmemory && cmd->flags & REDIS_CMD_DENYOOM && zmalloc_used_memory() > server.maxmemory) {
lenobj = createObject(REDIS_STRING,
sdscatprintf(sdsempty(),"%lu\r\n",
- stringObjectLen(argv[j])));
+ (unsigned long) stringObjectLen(argv[j])));
lenobj->refcount = 0;
outv[outc++] = lenobj;
}
sdsupdatelen(query);
/* Now we can split the query in arguments */
- if (sdslen(query) == 0) {
- /* Ignore empty query */
- sdsfree(query);
- return;
- }
argv = sdssplitlen(query,sdslen(query)," ",1,&argc);
sdsfree(query);
}
}
zfree(argv);
- /* Execute the command. If the client is still valid
- * after processCommand() return and there is something
- * on the query buffer try to process the next command. */
- if (c->argc && processCommand(c) && sdslen(c->querybuf)) goto again;
+ if (c->argc) {
+ /* Execute the command. If the client is still valid
+ * after processCommand() return and there is something
+ * on the query buffer try to process the next command. */
+ if (processCommand(c) && sdslen(c->querybuf)) goto again;
+ } else {
+ /* Nothing to process, argc == 0. Just process the query
+ * buffer if it's not empty or return to the caller */
+ if (sdslen(c->querybuf)) goto again;
+ }
return;
} else if (sdslen(c->querybuf) >= REDIS_REQUEST_MAX_SIZE) {
redisLog(REDIS_DEBUG, "Client protocol error");
snprintf(buf,sizeof(buf),"%.17g",d);
addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n%s\r\n",
- strlen(buf),buf));
+ (unsigned long) strlen(buf),buf));
}
static void addReplyBulkLen(redisClient *c, robj *obj) {
} else {
long n = (long)obj->ptr;
+ /* Compute how many bytes will take this integer as a radix 10 string */
len = 1;
if (n < 0) {
len++;
len++;
}
}
- addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",len));
+ addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",(unsigned long)len));
}
static void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
/* Try LZF compression - under 20 bytes it's unable to compress even
* aaaaaaaaaaaaaaaaaa so skip it */
- if (len > 20) {
+ if (server.rdbcompression && len > 20) {
int retval;
retval = rdbSaveLzfStringObject(fp,obj);
case 253: *val = R_Nan; return 0;
default:
if (fread(buf,len,1,fp) == 0) return -1;
+ buf[len] = '\0';
sscanf(buf, "%lg", val);
return 0;
}
static void setGenericCommand(redisClient *c, int nx) {
int retval;
- deleteIfVolatile(c->db,c->argv[1]);
+ if (nx) deleteIfVolatile(c->db,c->argv[1]);
retval = dictAdd(c->db->dict,c->argv[1],c->argv[2]);
if (retval == DICT_ERR) {
if (!nx) {
int j, busykeys = 0;
if ((c->argc % 2) == 0) {
- addReplySds(c,sdsnew("-ERR wrong number of arguments\r\n"));
+ addReplySds(c,sdsnew("-ERR wrong number of arguments for MSET\r\n"));
return;
}
/* Handle the NX flag. The MSETNX semantic is to return zero and don't
return;
}
if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
- addReply(c,shared.ok);
+ char *status = "+Background saving started\r\n";
+ addReplySds(c,sdsnew(status));
} else {
addReply(c,shared.err);
}
kill(server.bgsavechildpid,SIGKILL);
rdbRemoveTempFile(server.bgsavechildpid);
}
- /* SYNC SAVE */
- if (rdbSave(server.dbfilename) == REDIS_OK) {
- if (server.daemonize)
- unlink(server.pidfile);
- redisLog(REDIS_WARNING,"%zu bytes used at exit",zmalloc_used_memory());
- redisLog(REDIS_WARNING,"Server exit now, bye bye...");
- exit(1);
+ if (server.appendonly) {
+ /* Append only file: fsync() the AOF and exit */
+ fsync(server.appendfd);
+ exit(0);
} else {
- /* Ooops.. error saving! The best we can do is to continue operating.
- * Note that if there was a background saving process, in the next
- * cron() Redis will be notified that the background saving aborted,
- * handling special stuff like slaves pending for synchronization... */
- redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit");
- addReplySds(c,sdsnew("-ERR can't quit, problems saving the DB\r\n"));
+ /* Snapshotting. Perform a SYNC SAVE and exit */
+ if (rdbSave(server.dbfilename) == REDIS_OK) {
+ if (server.daemonize)
+ unlink(server.pidfile);
+ redisLog(REDIS_WARNING,"%zu bytes used at exit",zmalloc_used_memory());
+ redisLog(REDIS_WARNING,"Server exit now, bye bye...");
+ exit(0);
+ } else {
+ /* Ooops.. error saving! The best we can do is to continue operating.
+ * Note that if there was a background saving process, in the next
+ * cron() Redis will be notified that the background saving aborted,
+ * handling special stuff like slaves pending for synchronization... */
+ redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit");
+ addReplySds(c,sdsnew("-ERR can't quit, problems saving the DB\r\n"));
+ }
}
}
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
- addReply(c,shared.nokeyerr);
+ addReply(c,shared.ok);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
if (!setobj) {
zfree(dv);
if (dstkey) {
- deleteKey(c->db,dstkey);
- addReply(c,shared.ok);
+ if (deleteKey(c->db,dstkey))
+ server.dirty++;
+ addReply(c,shared.czero);
} else {
addReply(c,shared.nullmultibulk);
}
int offset = 0, limit = -1;
if (c->argc != 4 && c->argc != 7) {
- addReplySds(c,sdsnew("-ERR wrong number of arguments\r\n"));
+ addReplySds(c,
+ sdsnew("-ERR wrong number of arguments for ZRANGEBYSCORE\r\n"));
return;
} else if (c->argc == 7 && strcasecmp(c->argv[4]->ptr,"limit")) {
addReply(c,shared.syntaxerr);
"changes_since_last_save:%lld\r\n"
"bgsave_in_progress:%d\r\n"
"last_save_time:%ld\r\n"
+ "bgrewriteaof_in_progress:%d\r\n"
"total_connections_received:%lld\r\n"
"total_commands_processed:%lld\r\n"
"role:%s\r\n"
server.dirty,
server.bgsavechildpid != -1,
server.lastsave,
+ server.bgrewritechildpid != -1,
server.stat_numconnections,
server.stat_numcommands,
server.masterhost == NULL ? "master" : "slave"
static void infoCommand(redisClient *c) {
sds info = genRedisInfoString();
- addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",sdslen(info)));
+ addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",
+ (unsigned long)sdslen(info)));
addReplySds(c,info);
addReply(c,shared.crlf);
}
}
server.master = createClient(fd);
server.master->flags |= REDIS_MASTER;
+ server.master->authenticated = 1;
server.replstate = REDIS_REPL_CONNECTED;
return REDIS_OK;
}
snprintf(seldb,sizeof(seldb),"%d",dictid);
buf = sdscatprintf(buf,"*2\r\n$6\r\nSELECT\r\n$%lu\r\n%s\r\n",
- strlen(seldb),seldb);
+ (unsigned long)strlen(seldb),seldb);
server.appendseldb = dictid;
}
robj *o = argv[j];
o = getDecodedObject(o);
- buf = sdscatprintf(buf,"$%lu\r\n",sdslen(o->ptr));
+ buf = sdscatprintf(buf,"$%lu\r\n",(unsigned long)sdslen(o->ptr));
buf = sdscatlen(buf,o->ptr,sdslen(o->ptr));
buf = sdscatlen(buf,"\r\n",2);
decrRefCount(o);
obj = getDecodedObject(obj);
snprintf(buf,sizeof(buf),"$%ld\r\n",(long)sdslen(obj->ptr));
if (fwrite(buf,strlen(buf),1,fp) == 0) goto err;
- if (fwrite(obj->ptr,sdslen(obj->ptr),1,fp) == 0) goto err;
+ if (sdslen(obj->ptr) && fwrite(obj->ptr,sdslen(obj->ptr),1,fp) == 0)
+ goto err;
if (fwrite("\r\n",2,1,fp) == 0) goto err;
decrRefCount(obj);
return 1;
}
/* Save the expire time */
if (expiretime != -1) {
- char cmd[]="*3\r\n$6\r\nEXPIRE\r\n";
+ char cmd[]="*3\r\n$8\r\nEXPIREAT\r\n";
/* If this key is already expired skip it */
if (expiretime < now) continue;
if (fwrite(cmd,sizeof(cmd)-1,1,fp) == 0) goto werr;
werr:
fclose(fp);
unlink(tmpfile);
- redisLog(REDIS_WARNING,"Write error writing append only fileon disk: %s", strerror(errno));
+ redisLog(REDIS_WARNING,"Write error writing append only file on disk: %s", strerror(errno));
if (di) dictReleaseIterator(di);
return REDIS_ERR;
}
return;
}
if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
- addReply(c,shared.ok);
+ char *status = "+Background append only file rewriting started\r\n";
+ addReplySds(c,sdsnew(status));
} else {
addReply(c,shared.err);
}
}
redisLog(REDIS_WARNING,"DB reloaded by DEBUG RELOAD");
addReply(c,shared.ok);
+ } else if (!strcasecmp(c->argv[1]->ptr,"loadaof")) {
+ emptyDb();
+ if (loadAppendOnlyFile(server.appendfilename) != REDIS_OK) {
+ addReply(c,shared.err);
+ return;
+ }
+ redisLog(REDIS_WARNING,"Append Only File loaded by DEBUG LOADAOF");
+ addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"object") && c->argc == 3) {
dictEntry *de = dictFind(c->db->dict,c->argv[2]);
robj *key, *val;