* m: may increase memory usage once called. Don't allow if out of memory.
* a: admin command, like SAVE or SHUTDOWN.
* p: Pub/Sub related command.
- * f: force replication of this command, regarless of server.dirty. */
+ * f: force replication of this command, regarless of server.dirty.
+ * s: command not allowed in scripts.
+ * r: random command. Command is not deterministic, that is, the same command
+ * with the same arguments, with the same key space, may have different
+ * results. For instance SPOP and RANDOMKEY are two random commands. */
struct redisCommand redisCommandTable[] = {
{"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
{"set",setCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
{"smove",smoveCommand,4,"w",0,NULL,1,2,1,0,0},
{"sismember",sismemberCommand,3,"r",0,NULL,1,1,1,0,0},
{"scard",scardCommand,2,"r",0,NULL,1,1,1,0,0},
- {"spop",spopCommand,2,"w",0,NULL,1,1,1,0,0},
- {"srandmember",srandmemberCommand,2,"r",0,NULL,1,1,1,0,0},
+ {"spop",spopCommand,2,"wRs",0,NULL,1,1,1,0,0},
+ {"srandmember",srandmemberCommand,2,"rR",0,NULL,1,1,1,0,0},
{"sinter",sinterCommand,-2,"r",0,NULL,1,-1,1,0,0},
{"sinterstore",sinterstoreCommand,-3,"wm",0,NULL,2,-1,1,0,0},
{"sunion",sunionCommand,-2,"r",0,NULL,1,-1,1,0,0},
{"getset",getsetCommand,3,"wm",0,NULL,1,1,1,0,0},
{"mset",msetCommand,-3,"wm",0,NULL,1,-1,2,0,0},
{"msetnx",msetnxCommand,-3,"wm",0,NULL,1,-1,2,0,0},
- {"randomkey",randomkeyCommand,1,"r",0,NULL,0,0,0,0,0},
+ {"randomkey",randomkeyCommand,1,"rR",0,NULL,0,0,0,0,0},
{"select",selectCommand,2,"r",0,NULL,0,0,0,0,0},
{"move",moveCommand,3,"w",0,NULL,1,1,1,0,0},
{"rename",renameCommand,3,"w",0,renameGetKeys,1,2,1,0,0},
{"shutdown",shutdownCommand,1,"ar",0,NULL,0,0,0,0,0},
{"lastsave",lastsaveCommand,1,"r",0,NULL,0,0,0,0,0},
{"type",typeCommand,2,"r",0,NULL,1,1,1,0,0},
- {"multi",multiCommand,1,"r",0,NULL,0,0,0,0,0},
- {"exec",execCommand,1,"wm",0,NULL,0,0,0,0,0},
- {"discard",discardCommand,1,"r",0,NULL,0,0,0,0,0},
- {"sync",syncCommand,1,"ar",0,NULL,0,0,0,0,0},
+ {"multi",multiCommand,1,"rs",0,NULL,0,0,0,0,0},
+ {"exec",execCommand,1,"wms",0,NULL,0,0,0,0,0},
+ {"discard",discardCommand,1,"rs",0,NULL,0,0,0,0,0},
+ {"sync",syncCommand,1,"ars",0,NULL,0,0,0,0,0},
{"flushdb",flushdbCommand,1,"w",0,NULL,0,0,0,0,0},
{"flushall",flushallCommand,1,"w",0,NULL,0,0,0,0,0},
{"sort",sortCommand,-2,"wm",0,NULL,1,1,1,0,0},
{"info",infoCommand,-1,"r",0,NULL,0,0,0,0,0},
- {"monitor",monitorCommand,1,"ar",0,NULL,0,0,0,0,0},
+ {"monitor",monitorCommand,1,"ars",0,NULL,0,0,0,0,0},
{"ttl",ttlCommand,2,"r",0,NULL,1,1,1,0,0},
{"persist",persistCommand,2,"w",0,NULL,1,1,1,0,0},
- {"slaveof",slaveofCommand,3,"aw",0,NULL,0,0,0,0,0},
+ {"slaveof",slaveofCommand,3,"aws",0,NULL,0,0,0,0,0},
{"debug",debugCommand,-2,"aw",0,NULL,0,0,0,0,0},
{"config",configCommand,-2,"ar",0,NULL,0,0,0,0,0},
- {"subscribe",subscribeCommand,-2,"rp",0,NULL,0,0,0,0,0},
- {"unsubscribe",unsubscribeCommand,-1,"rp",0,NULL,0,0,0,0,0},
- {"psubscribe",psubscribeCommand,-2,"rp",0,NULL,0,0,0,0,0},
- {"punsubscribe",punsubscribeCommand,-1,"rp",0,NULL,0,0,0,0,0},
+ {"subscribe",subscribeCommand,-2,"rps",0,NULL,0,0,0,0,0},
+ {"unsubscribe",unsubscribeCommand,-1,"rps",0,NULL,0,0,0,0,0},
+ {"psubscribe",psubscribeCommand,-2,"rps",0,NULL,0,0,0,0,0},
+ {"punsubscribe",punsubscribeCommand,-1,"rps",0,NULL,0,0,0,0,0},
{"publish",publishCommand,3,"rpf",0,NULL,0,0,0,0,0},
- {"watch",watchCommand,-2,"r",0,noPreloadGetKeys,1,-1,1,0,0},
- {"unwatch",unwatchCommand,1,"r",0,NULL,0,0,0,0,0},
+ {"watch",watchCommand,-2,"rs",0,noPreloadGetKeys,1,-1,1,0,0},
+ {"unwatch",unwatchCommand,1,"rs",0,NULL,0,0,0,0,0},
{"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
- {"restore",restoreCommand,4,"awm",0,NULL,0,0,0,0,0},
+ {"restore",restoreCommand,4,"awm",0,NULL,1,1,1,0,0},
{"migrate",migrateCommand,6,"aw",0,NULL,0,0,0,0,0},
+ {"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0},
{"dump",dumpCommand,2,"ar",0,NULL,0,0,0,0,0},
{"object",objectCommand,-2,"r",0,NULL,0,0,0,0,0},
{"client",clientCommand,-2,"ar",0,NULL,0,0,0,0,0},
- {"eval",evalCommand,-3,"wm",0,zunionInterGetKeys,0,0,0,0,0},
- {"evalsha",evalShaCommand,-3,"wm",0,zunionInterGetKeys,0,0,0,0,0},
+ {"eval",evalCommand,-3,"wms",0,zunionInterGetKeys,0,0,0,0,0},
+ {"evalsha",evalShaCommand,-3,"wms",0,zunionInterGetKeys,0,0,0,0,0},
{"slowlog",slowlogCommand,-2,"r",0,NULL,0,0,0,0,0}
};
server.port = REDIS_SERVERPORT;
server.bindaddr = NULL;
server.unixsocket = NULL;
+ server.unixsocketperm = 0;
server.ipfd = -1;
server.sofd = -1;
server.dbnum = REDIS_DEFAULT_DBNUM;
}
if (server.unixsocket != NULL) {
unlink(server.unixsocket); /* don't care if this fails */
- server.sofd = anetUnixServer(server.neterr,server.unixsocket);
+ server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);
if (server.sofd == ANET_ERR) {
redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr);
exit(1);
case 'a': c->flags |= REDIS_CMD_ADMIN; break;
case 'p': c->flags |= REDIS_CMD_PUBSUB; break;
case 'f': c->flags |= REDIS_CMD_FORCE_REPLICATION; break;
+ case 's': c->flags |= REDIS_CMD_NOSCRIPT; break;
+ case 'R': c->flags |= REDIS_CMD_RANDOM; break;
default: redisPanic("Unsupported command flag"); break;
}
f++;
/* Close the listening sockets. Apparently this allows faster restarts. */
if (server.ipfd != -1) close(server.ipfd);
if (server.sofd != -1) close(server.sofd);
+ if (server.unixsocket) {
+ redisLog(REDIS_NOTICE,"Removing the unix socket file.");
+ unlink(server.unixsocket); /* don't care if this fails */
+ }
redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");
return REDIS_OK;
/*================================== Commands =============================== */
void authCommand(redisClient *c) {
- if (!server.requirepass || !strcmp(c->argv[1]->ptr, server.requirepass)) {
+ if (!server.requirepass) {
+ addReplyError(c,"Client sent AUTH, but no password is set");
+ } else if (!strcmp(c->argv[1]->ptr, server.requirepass)) {
c->authenticated = 1;
addReply(c,shared.ok);
} else {
"used_cpu_user:%.2f\r\n"
"used_cpu_sys_children:%.2f\r\n"
"used_cpu_user_children:%.2f\r\n",
- (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,
(float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,
- (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000,
- (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000);
+ (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,
+ (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000,
+ (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000);
}
/* cmdtime */
if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
} else {
- if (rdbLoad(server.dbfilename) == REDIS_OK)
- redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",(float)(ustime()-start)/1000000);
+ if (rdbLoad(server.dbfilename) == REDIS_OK) {
+ redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",
+ (float)(ustime()-start)/1000000);
+ } else if (errno != ENOENT) {
+ redisLog(REDIS_WARNING,"Fatal error loading the DB. Exiting.");
+ exit(1);
+ }
}
if (server.ipfd > 0)
redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);