X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/5d02b00f56fa959d3720c0590f32762a853c8928..c0875a77a14d417f76b4419127733929ace587ee:/src/redis.c diff --git a/src/redis.c b/src/redis.c index ab92cc56..dd693f6c 100644 --- a/src/redis.c +++ b/src/redis.c @@ -81,7 +81,11 @@ struct redisCommand *commandTable; * 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}, @@ -121,8 +125,8 @@ struct redisCommand redisCommandTable[] = { {"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}, @@ -163,7 +167,7 @@ struct redisCommand redisCommandTable[] = { {"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}, @@ -181,35 +185,35 @@ struct redisCommand redisCommandTable[] = { {"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}, {"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} }; @@ -818,6 +822,7 @@ void initServerConfig() { server.port = REDIS_SERVERPORT; server.bindaddr = NULL; server.unixsocket = NULL; + server.unixsocketperm = 0; server.ipfd = -1; server.sofd = -1; server.dbnum = REDIS_DEFAULT_DBNUM; @@ -931,7 +936,7 @@ void initServer() { } 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); @@ -1010,6 +1015,8 @@ void populateCommandTable(void) { 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++; @@ -1230,6 +1237,10 @@ int prepareForShutdown() { /* 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; @@ -1238,7 +1249,9 @@ int prepareForShutdown() { /*================================== 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 { @@ -1504,10 +1517,10 @@ sds genRedisInfoString(char *section) { "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 */ @@ -1789,8 +1802,13 @@ int main(int argc, char **argv) { 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);