From 27abaa238ff2b9d71a7d4f6aee0b6cd6fc615ed0 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 14 Jan 2013 11:39:54 +0100 Subject: Undo slave-master handshake when SLAVEOF sets a new slave. Issue #828 shows how Redis was not correctly undoing a non-blocking connection attempt with the previous master when the master was set to a new address using the SLAVEOF command. This was also a result of lack of refactoring, so now there is a function to cancel the non blocking handshake with the master. The new function is now used when SLAVEOF NO ONE is called or when SLAVEOF is used to set the master to a different address. --- src/replication.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/replication.c b/src/replication.c index 162aa20eb..20b6e8555 100644 --- a/src/replication.c +++ b/src/replication.c @@ -695,6 +695,27 @@ void undoConnectWithMaster(void) { server.repl_state = REDIS_REPL_CONNECT; } +/* This function aborts a non blocking replication attempt if there is one + * in progress, by canceling the non-blocking connect attempt or + * the initial bulk transfer. + * + * If there was a replication handshake in progress 1 is returned and + * the replication state (server.repl_state) set to REDIS_REPL_CONNECT. + * + * Otherwise zero is returned and no operation is perforemd at all. */ +int cancelReplicationHandshake(void) { + if (server.repl_state == REDIS_REPL_TRANSFER) { + replicationAbortSyncTransfer(); + } else if (server.repl_state == REDIS_REPL_CONNECTING || + server.repl_state == REDIS_REPL_RECEIVE_PONG) + { + undoConnectWithMaster(); + } else { + return 0; + } + return 1; +} + void slaveofCommand(redisClient *c) { if (!strcasecmp(c->argv[1]->ptr,"no") && !strcasecmp(c->argv[2]->ptr,"one")) { @@ -702,11 +723,7 @@ void slaveofCommand(redisClient *c) { sdsfree(server.masterhost); server.masterhost = NULL; if (server.master) freeClient(server.master); - if (server.repl_state == REDIS_REPL_TRANSFER) - replicationAbortSyncTransfer(); - else if (server.repl_state == REDIS_REPL_CONNECTING || - server.repl_state == REDIS_REPL_RECEIVE_PONG) - undoConnectWithMaster(); + cancelReplicationHandshake(); server.repl_state = REDIS_REPL_NONE; redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); } @@ -730,8 +747,7 @@ void slaveofCommand(redisClient *c) { server.masterport = port; if (server.master) freeClient(server.master); disconnectSlaves(); /* Force our slaves to resync with us as well. */ - if (server.repl_state == REDIS_REPL_TRANSFER) - replicationAbortSyncTransfer(); + cancelReplicationHandshake(); server.repl_state = REDIS_REPL_CONNECT; redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", server.masterhost, server.masterport); -- cgit v1.2.1 From c5f23ca79bf203c021fdd32d531487d9d15ab3b8 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 11 Jan 2013 18:43:28 +0100 Subject: CLIENT GETNAME and CLIENT SETNAME introduced. Sometimes it is much simpler to debug complex Redis installations if it is possible to assign clients a name that is displayed in the CLIENT LIST output. This is the case, for example, for "leaked" connections. The ability to provide a name to the client makes it quite trivial to understand what is the part of the code implementing the client not releasing the resources appropriately. Behavior: CLIENT SETNAME: set a name for the client, or remove the current name if an empty name is set. CLIENT GETNAME: get the current name, or a nil. CLIENT LIST: now displays the client name if any. Thanks to Mark Gravell for pushing this idea forward. --- src/aof.c | 1 + src/networking.c | 41 +++++++++++++++++++++++++++++++++++++++-- src/redis.h | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/aof.c b/src/aof.c index 6289e4dd5..fe5c64972 100644 --- a/src/aof.c +++ b/src/aof.c @@ -442,6 +442,7 @@ struct redisClient *createFakeClient(void) { selectDb(c,0); c->fd = -1; + c->name = NULL; c->querybuf = sdsempty(); c->querybuf_peak = 0; c->argc = 0; diff --git a/src/networking.c b/src/networking.c index c23939c5c..d935eaa82 100644 --- a/src/networking.c +++ b/src/networking.c @@ -70,6 +70,7 @@ redisClient *createClient(int fd) { selectDb(c,0); c->fd = fd; + c->name = NULL; c->bufpos = 0; c->querybuf = sdsempty(); c->querybuf_peak = 0; @@ -668,6 +669,7 @@ void freeClient(redisClient *c) { } /* Release memory */ + if (c->name) decrRefCount(c->name); zfree(c->argv); freeClientMultiState(c); zfree(c); @@ -1123,9 +1125,11 @@ sds getClientInfoString(redisClient *client) { if (emask & AE_WRITABLE) *p++ = 'w'; *p = '\0'; return sdscatprintf(sdsempty(), - "addr=%s:%d fd=%d age=%ld idle=%ld flags=%s db=%d sub=%d psub=%d multi=%d qbuf=%lu qbuf-free=%lu obl=%lu oll=%lu omem=%lu events=%s cmd=%s", + "addr=%s:%d fd=%d name=%s age=%ld idle=%ld flags=%s db=%d sub=%d psub=%d multi=%d qbuf=%lu qbuf-free=%lu obl=%lu oll=%lu omem=%lu events=%s cmd=%s", (client->flags & REDIS_UNIX_SOCKET) ? server.unixsocket : ip, - port,client->fd, + port, + client->fd, + client->name ? (char*)client->name->ptr : "", (long)(server.unixtime - client->ctime), (long)(server.unixtime - client->lastinteraction), flags, @@ -1190,6 +1194,39 @@ void clientCommand(redisClient *c) { } } addReplyError(c,"No such client"); + } else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { + int j, len = sdslen(c->argv[2]->ptr); + char *p = c->argv[2]->ptr; + + /* Setting the client name to an empty string actually removes + * the current name. */ + if (len == 0) { + if (c->name) decrRefCount(c->name); + c->name = NULL; + addReply(c,shared.ok); + return; + } + + /* Otherwise check if the charset is ok. We need to do this otherwise + * CLIENT LIST format will break. You should always be able to + * split by space to get the different fields. */ + for (j = 0; j < len; j++) { + if (p[j] < '!' || p[j] > '~') { /* ASCI is assumed. */ + addReplyError(c, + "Client names cannot contain spaces, " + "newlines or special characters."); + return; + } + } + if (c->name) decrRefCount(c->name); + c->name = c->argv[2]; + incrRefCount(c->name); + addReply(c,shared.ok); + } else if (!strcasecmp(c->argv[1]->ptr,"getname") && c->argc == 2) { + if (c->name) + addReplyBulk(c,c->name); + else + addReply(c,shared.nullbulk); } else { addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port)"); } diff --git a/src/redis.h b/src/redis.h index 071cb534e..1133fed5b 100644 --- a/src/redis.h +++ b/src/redis.h @@ -380,6 +380,7 @@ typedef struct redisClient { int fd; redisDb *db; int dictid; + robj *name; /* As set by CLIENT SETNAME */ sds querybuf; size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size */ int argc; -- cgit v1.2.1 From 1b2ac3b206e97e265c89351e095e7fabe674a506 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 11 Jan 2013 18:50:40 +0100 Subject: Typo fixed, ASCI -> ASCII. --- src/networking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/networking.c b/src/networking.c index d935eaa82..3448ea8de 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1211,7 +1211,7 @@ void clientCommand(redisClient *c) { * CLIENT LIST format will break. You should always be able to * split by space to get the different fields. */ for (j = 0; j < len; j++) { - if (p[j] < '!' || p[j] > '~') { /* ASCI is assumed. */ + if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */ addReplyError(c, "Client names cannot contain spaces, " "newlines or special characters."); -- cgit v1.2.1 From f9c1263f312064d283f222c738d63aec8eb32783 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 14 Jan 2013 10:19:20 +0100 Subject: Tests for CLIENT GETNAME/SETNAME. --- tests/unit/introspection.tcl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl index 9db0395a2..a6c2130f5 100644 --- a/tests/unit/introspection.tcl +++ b/tests/unit/introspection.tcl @@ -19,4 +19,37 @@ start_server {tags {"introspection"}} { assert_match {*eval*} [$rd read] assert_match {*lua*"set"*"foo"*"bar"*} [$rd read] } + + test {CLIENT GETNAME should return NIL if name is not assigned} { + r client getname + } {} + + test {CLIENT LIST shows empty fields for unassigned names} { + r client list + } {*name= *} + + test {CLIENT SETNAME does not accept spaces} { + catch {r client setname "foo bar"} e + set e + } {ERR*} + + test {CLIENT SETNAME can assign a name to this connection} { + assert_equal [r client setname myname] {OK} + r client list + } {*name=myname*} + + test {CLIENT SETNAME can change the name of an existing connection} { + assert_equal [r client setname someothername] {OK} + r client list + } {*name=someothername*} + + test {After CLIENT SETNAME, connection can still be closed} { + set rd [redis_deferring_client] + $rd client setname foobar + assert_equal [$rd read] "OK" + assert_match {*foobar*} [r client list] + $rd close + # Now the client should no longer be listed + string match {*foobar*} [r client list] + } {0} } -- cgit v1.2.1 From 52f6a1dc16eedfb23611c1a4b1013b935e5c7be0 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 16 Jan 2013 19:42:40 +0100 Subject: redis-cli: save an RDB dump from remote server to local file. --- src/redis-cli.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 3969fbab5..c3938636b 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "hiredis.h" #include "sds.h" @@ -73,6 +74,8 @@ static struct config { int cluster_reissue_command; int slave_mode; int pipe_mode; + int getrdb_mode; + char *rdb_filename; int bigkeys; int stdinarg; /* get last arg from stdin. (-x option) */ char *auth; @@ -660,6 +663,9 @@ static int parseOptions(int argc, char **argv) { config.latency_mode = 1; } else if (!strcmp(argv[i],"--slave")) { config.slave_mode = 1; + } else if (!strcmp(argv[i],"--rdb") && !lastarg) { + config.getrdb_mode = 1; + config.rdb_filename = argv[++i]; } else if (!strcmp(argv[i],"--pipe")) { config.pipe_mode = 1; } else if (!strcmp(argv[i],"--bigkeys")) { @@ -720,6 +726,7 @@ static void usage() { " --raw Use raw formatting for replies (default when STDOUT is not a tty)\n" " --latency Enter a special mode continuously sampling latency\n" " --slave Simulate a slave showing commands received from the master\n" +" --rdb Transfer an RDB dump from remote server to local file.\n" " --pipe Transfer raw Redis protocol from stdin to server\n" " --bigkeys Sample Redis keys looking for big keys\n" " --eval Send an EVAL command using the Lua script at \n" @@ -927,15 +934,15 @@ static void latencyMode(void) { } } -static void slaveMode(void) { +/* Sends SYNC and reads the number of bytes in the payload. Used both by + * slaveMode() and getRDB(). */ +unsigned long long sendSync(int fd) { /* To start we need to send the SYNC command and return the payload. * The hiredis client lib does not understand this part of the protocol * and we don't want to mess with its buffers, so everything is performed * using direct low-level I/O. */ - int fd = context->fd; - char buf[1024], *p; + char buf[4096], *p; ssize_t nread; - unsigned long long payload; /* Send the SYNC command. */ if (write(fd,"SYNC\r\n",6) != 6) { @@ -955,12 +962,25 @@ static void slaveMode(void) { p++; } *p = '\0'; - payload = strtoull(buf+1,NULL,10); - fprintf(stderr,"SYNC with master, discarding %lld bytes of bulk tranfer...\n", - payload); + if (buf[0] == '-') { + printf("SYNC with master failed: %s\n", buf); + exit(1); + } + return strtoull(buf+1,NULL,10); +} + +static void slaveMode(void) { + int fd = context->fd; + unsigned long long payload = sendSync(fd); + char buf[1024]; + + fprintf(stderr,"SYNC with master, discarding %llu " + "bytes of bulk tranfer...\n", payload); /* Discard the payload. */ while(payload) { + ssize_t nread; + nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload); if (nread <= 0) { fprintf(stderr,"Error reading RDB payload while SYNCing\n"); @@ -970,11 +990,56 @@ static void slaveMode(void) { } fprintf(stderr,"SYNC done. Logging commands from master.\n"); - /* Now we can use the hiredis to read the incoming protocol. */ + /* Now we can use hiredis to read the incoming protocol. */ config.output = OUTPUT_CSV; while (cliReadReply(0) == REDIS_OK); } +/* This function implements --rdb, so it uses the replication protocol in order + * to fetch the RDB file from a remote server. */ +static void getRDB(void) { + int s = context->fd; + int fd; + unsigned long long payload = sendSync(s); + char buf[4096]; + + fprintf(stderr,"SYNC sent to master, writing %llu bytes to '%s'\n", + payload, config.rdb_filename); + + /* Write to file. */ + if (!strcmp(config.rdb_filename,"-")) { + fd = STDOUT_FILENO; + } else { + fd = open(config.rdb_filename, O_CREAT|O_WRONLY, 0644); + if (fd == -1) { + fprintf(stderr, "Error opening '%s': %s\n", config.rdb_filename, + strerror(errno)); + exit(1); + } + } + + while(payload) { + ssize_t nread, nwritten; + + nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload); + if (nread <= 0) { + fprintf(stderr,"I/O Error reading RDB payload from socket\n"); + exit(1); + } + nwritten = write(fd, buf, nread); + if (nwritten != nread) { + fprintf(stderr,"Error writing data to file: %s\n", + strerror(errno)); + exit(1); + } + payload -= nread; + } + close(s); /* Close the file descriptor ASAP as fsync() may take time. */ + fsync(fd); + fprintf(stderr,"Transfer finished with success.\n"); + exit(0); +} + static void pipeMode(void) { int fd = context->fd; long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0; @@ -1203,6 +1268,8 @@ int main(int argc, char **argv) { config.latency_mode = 0; config.cluster_mode = 0; config.slave_mode = 0; + config.getrdb_mode = 0; + config.rdb_filename = NULL; config.pipe_mode = 0; config.bigkeys = 0; config.stdinarg = 0; @@ -1231,6 +1298,12 @@ int main(int argc, char **argv) { slaveMode(); } + /* Get RDB mode. */ + if (config.getrdb_mode) { + cliConnect(0); + getRDB(); + } + /* Pipe mode */ if (config.pipe_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); -- cgit v1.2.1 From 21159d53f58b01dfcd5e2451b617da0f3645aedb Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 16 Jan 2013 19:54:56 +0100 Subject: Redis 2.6.9 --- 00-RELEASENOTES | 14 ++++++++++++++ src/version.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/00-RELEASENOTES b/00-RELEASENOTES index 5471baa3f..2c5010660 100644 --- a/00-RELEASENOTES +++ b/00-RELEASENOTES @@ -14,6 +14,20 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade! CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP. -------------------------------------------------------------------------------- +--[ Redis 2.6.9 ] + +UPGRADE URGENCY: MODERATE if you use replication. + +* [BUGFIX] Changing master at runtime (SLAVEOF command) in presence of + network problems, or in very rapid succession, could result + in non-critical problems (GitHub Issue #828). +* [IMPROVED] CLINGET GETNAME and SETNAME to set and query connection names + reported by CLIENT LIST. Very useful for debugging of + problems. +* [IMPROVED] redis-cli is now able to transfer an RDB file from a remote + server to a local file using the --rdb command + line option. + --[ Redis 2.6.8 ] UPGRADE URGENCY: MODERATE if you use Lua scripting. Otherwise LOW. diff --git a/src/version.h b/src/version.h index c0881950f..293bd1bfb 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define REDIS_VERSION "2.6.8" +#define REDIS_VERSION "2.6.9" -- cgit v1.2.1 From 0f4dbd9a11f34306638c86f55fbb2f9ba6db8f54 Mon Sep 17 00:00:00 2001 From: Nathan Parry Date: Thu, 17 Jan 2013 23:55:43 -0500 Subject: redis-cli --rdb fails if server sends a ping Redis pings slaves in "pre-synchronization stage" with newlines. (See https://github.com/antirez/redis/blob/2.6.9/src/replication.c#L814) However, redis-cli does not expect this - it sees the newline as the end of the bulk length line, and ends up returning 0 as bulk the length. This manifests as the following when running redis-cli: $ ./src/redis-cli --rdb some_file SYNC sent to master, writing 0 bytes to 'some_file' Transfer finished with success. With this commit, we just ignore leading newlines while reading the bulk length line. To reproduce the problem, load enough data into Redis so that the preparation of the RDB snapshot takes long enough for a ping to occur while redis-cli is waiting for the data. --- src/redis-cli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index c3938636b..0bc61bb25 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -958,8 +958,8 @@ unsigned long long sendSync(int fd) { fprintf(stderr,"Error reading bulk length while SYNCing\n"); exit(1); } - if (*p == '\n') break; - p++; + if (*p == '\n' && p != buf) break; + if (*p != '\n') p++; } *p = '\0'; if (buf[0] == '-') { -- cgit v1.2.1 From a732d86fe032607e17d318436bee99d82f2aae8a Mon Sep 17 00:00:00 2001 From: bitterb Date: Sat, 19 Jan 2013 14:11:33 +0900 Subject: Fix an error reply for CLIENT command --- src/networking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/networking.c b/src/networking.c index 3448ea8de..d1a8d3b3f 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1228,7 +1228,7 @@ void clientCommand(redisClient *c) { else addReply(c,shared.nullbulk); } else { - addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port)"); + addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port | GETNAME | SETNAME connection-name)"); } } -- cgit v1.2.1 From 5e2aa2cafb29d9e174c8e625ef9ff9983d5802b7 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Fri, 18 Jan 2013 10:13:10 +0100 Subject: Always exit if connection fails. This avoids unnecessary core dumps. Fixes antirez/redis#894 --- src/redis-cli.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 0bc61bb25..a789ab13d 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1288,19 +1288,19 @@ int main(int argc, char **argv) { /* Latency mode */ if (config.latency_mode) { - cliConnect(0); + if (cliConnect(0) == REDIS_ERR) exit(1); latencyMode(); } /* Slave mode */ if (config.slave_mode) { - cliConnect(0); + if (cliConnect(0) == REDIS_ERR) exit(1); slaveMode(); } /* Get RDB mode. */ if (config.getrdb_mode) { - cliConnect(0); + if (cliConnect(0) == REDIS_ERR) exit(1); getRDB(); } @@ -1312,7 +1312,7 @@ int main(int argc, char **argv) { /* Find big keys */ if (config.bigkeys) { - cliConnect(0); + if (cliConnect(0) == REDIS_ERR) exit(1); findBigKeys(); } -- cgit v1.2.1 From c2b43eac4f35fa1137a5539387c389a43e62725f Mon Sep 17 00:00:00 2001 From: charsyam Date: Wed, 16 Jan 2013 17:20:54 -0800 Subject: redis-cli prompt bug fix --- src/redis-cli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/redis-cli.c b/src/redis-cli.c index a789ab13d..1fb076fa5 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -801,6 +801,7 @@ static void repl() { sdsfree(config.hostip); config.hostip = sdsnew(argv[1]); config.hostport = atoi(argv[2]); + cliRefreshPrompt(); cliConnect(1); } else if (argc == 1 && !strcasecmp(argv[0],"clear")) { linenoiseClearScreen(); -- cgit v1.2.1 From 560e049947779a7cae29c7bd924bd86834275022 Mon Sep 17 00:00:00 2001 From: guiquanz Date: Thu, 17 Jan 2013 01:00:20 +0800 Subject: Fixed many typos. --- redis.conf | 2 +- sentinel.conf | 2 +- src/adlist.c | 6 +++--- src/ae.c | 6 +++--- src/ae_evport.c | 12 ++++++------ src/anet.c | 4 ++-- src/aof.c | 2 +- src/bio.c | 2 +- src/bitops.c | 4 ++-- src/config.c | 6 +++--- src/db.c | 6 +++--- src/debug.c | 4 ++-- src/dict.c | 2 +- src/lzfP.h | 8 ++++---- src/mkreleasehdr.sh | 2 +- src/multi.c | 4 ++-- src/networking.c | 8 ++++---- src/object.c | 2 +- src/pubsub.c | 2 +- src/rdb.c | 10 +++++----- src/rdb.h | 2 +- src/redis-check-dump.c | 4 ++-- src/redis-cli.c | 6 +++--- src/redis.c | 28 ++++++++++++++-------------- src/redis.h | 22 +++++++++++----------- src/release.c | 4 ++-- src/replication.c | 10 +++++----- src/scripting.c | 12 ++++++------ src/sds.c | 4 ++-- src/sentinel.c | 20 ++++++++++---------- src/sha1.c | 36 ++++++++++++++++++------------------ src/sort.c | 6 +++--- src/t_list.c | 10 +++++----- src/t_set.c | 4 ++-- src/t_string.c | 4 ++-- src/t_zset.c | 4 ++-- src/zmalloc.c | 2 +- tests/unit/scripting.tcl | 2 +- 38 files changed, 137 insertions(+), 137 deletions(-) diff --git a/redis.conf b/redis.conf index 97aea334b..399f957fc 100644 --- a/redis.conf +++ b/redis.conf @@ -246,7 +246,7 @@ slave-priority 100 # Set the max number of connected clients at the same time. By default # this limit is set to 10000 clients, however if the Redis server is not -# able ot configure the process file limit to allow for the specified limit +# able to configure the process file limit to allow for the specified limit # the max number of allowed clients is set to the current file limit # minus 32 (as Redis reserves a few file descriptors for internal uses). # diff --git a/sentinel.conf b/sentinel.conf index 94169ee8f..ac687b535 100644 --- a/sentinel.conf +++ b/sentinel.conf @@ -71,7 +71,7 @@ sentinel parallel-syncs mymaster 1 # Default is 15 minutes. sentinel failover-timeout mymaster 900000 -# SCRIPTS EXECTION +# SCRIPTS EXECUTION # # sentinel notification-script and sentinel reconfig-script are used in order # to configure scripts that are called to notify the system administrator diff --git a/src/adlist.c b/src/adlist.c index e48957e3a..f075e1bda 100644 --- a/src/adlist.c +++ b/src/adlist.c @@ -97,7 +97,7 @@ list *listAddNodeHead(list *list, void *value) return list; } -/* Add a new node to the list, to tail, contaning the specified 'value' +/* Add a new node to the list, to tail, containing the specified 'value' * pointer as value. * * On error, NULL is returned and no operation is performed (i.e. the @@ -308,7 +308,7 @@ listNode *listSearchKey(list *list, void *key) /* Return the element at the specified zero-based index * where 0 is the head, 1 is the element next to head * and so on. Negative integers are used in order to count - * from the tail, -1 is the last element, -2 the penultimante + * from the tail, -1 is the last element, -2 the penultimate * and so on. If the index is out of range NULL is returned. */ listNode *listIndex(list *list, long index) { listNode *n; @@ -330,7 +330,7 @@ void listRotate(list *list) { if (listLength(list) <= 1) return; - /* Detatch current tail */ + /* Detach current tail */ list->tail = tail->prev; list->tail->next = NULL; /* Move it as head */ diff --git a/src/ae.c b/src/ae.c index 90be4e28f..6ca9a5153 100644 --- a/src/ae.c +++ b/src/ae.c @@ -309,7 +309,7 @@ static int processTimeEvents(aeEventLoop *eventLoop) { /* Process every pending time event, then every pending file event * (that may be registered by time event callbacks just processed). * Without special flags the function sleeps until some file event - * fires, or when the next time event occurrs (if any). + * fires, or when the next time event occurs (if any). * * If flags is 0, the function does nothing and returns. * if flags has AE_ALL_EVENTS set, all the kind of events are processed. @@ -356,7 +356,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags) if (tvp->tv_usec < 0) tvp->tv_usec = 0; } else { /* If we have to check for events but need to return - * ASAP because of AE_DONT_WAIT we need to se the timeout + * ASAP because of AE_DONT_WAIT we need to set the timeout * to zero */ if (flags & AE_DONT_WAIT) { tv.tv_sec = tv.tv_usec = 0; @@ -395,7 +395,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags) return processed; /* return the number of processed file/time events */ } -/* Wait for millseconds until the given file descriptor becomes +/* Wait for milliseconds until the given file descriptor becomes * writable/readable/exception */ int aeWait(int fd, int mask, long long milliseconds) { struct pollfd pfd; diff --git a/src/ae_evport.c b/src/ae_evport.c index 0196dccf4..94413c132 100644 --- a/src/ae_evport.c +++ b/src/ae_evport.c @@ -50,15 +50,15 @@ static int evport_debug = 0; * aeApiPoll, the corresponding file descriptors become dissociated from the * port. This is necessary because poll events are level-triggered, so if the * fd didn't become dissociated, it would immediately fire another event since - * the underlying state hasn't changed yet. We must reassociate the file + * the underlying state hasn't changed yet. We must re-associate the file * descriptor, but only after we know that our caller has actually read from it. * The ae API does not tell us exactly when that happens, but we do know that * it must happen by the time aeApiPoll is called again. Our solution is to - * keep track of the last fds returned by aeApiPoll and reassociate them next + * keep track of the last fds returned by aeApiPoll and re-associate them next * time aeApiPoll is invoked. * * To summarize, in this module, each fd association is EITHER (a) represented - * only via the in-kernel assocation OR (b) represented by pending_fds and + * only via the in-kernel association OR (b) represented by pending_fds and * pending_masks. (b) is only true for the last fds we returned from aeApiPoll, * and only until we enter aeApiPoll again (at which point we restore the * in-kernel association). @@ -164,7 +164,7 @@ static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { * This fd was recently returned from aeApiPoll. It should be safe to * assume that the consumer has processed that poll event, but we play * it safer by simply updating pending_mask. The fd will be - * reassociated as usual when aeApiPoll is called again. + * re-associated as usual when aeApiPoll is called again. */ if (evport_debug) fprintf(stderr, "aeApiAddEvent: adding to pending fd %d\n", fd); @@ -228,7 +228,7 @@ static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) { * ENOMEM is a potentially transient condition, but the kernel won't * generally return it unless things are really bad. EAGAIN indicates * we've reached an resource limit, for which it doesn't make sense to - * retry (counterintuitively). All other errors indicate a bug. In any + * retry (counter-intuitively). All other errors indicate a bug. In any * of these cases, the best we can do is to abort. */ abort(); /* will not return */ @@ -243,7 +243,7 @@ static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) { port_event_t event[MAX_EVENT_BATCHSZ]; /* - * If we've returned fd events before, we must reassociate them with the + * If we've returned fd events before, we must re-associate them with the * port now, before calling port_get(). See the block comment at the top of * this file for an explanation of why. */ diff --git a/src/anet.c b/src/anet.c index ae8e9a658..4da3e28db 100644 --- a/src/anet.c +++ b/src/anet.c @@ -61,7 +61,7 @@ int anetNonBlock(char *err, int fd) { int flags; - /* Set the socket nonblocking. + /* Set the socket non-blocking. * Note that fcntl(2) for F_GETFL and F_SETFL can't be * interrupted by a signal. */ if ((flags = fcntl(fd, F_GETFL)) == -1) { @@ -132,7 +132,7 @@ static int anetCreateSocket(char *err, int domain) { return ANET_ERR; } - /* Make sure connection-intensive things like the redis benckmark + /* Make sure connection-intensive things like the redis benchmark * will be able to close/open sockets a zillion of times */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); diff --git a/src/aof.c b/src/aof.c index fe5c64972..7e1512ebd 100644 --- a/src/aof.c +++ b/src/aof.c @@ -385,7 +385,7 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a sds buf = sdsempty(); robj *tmpargv[3]; - /* The DB this command was targetting is not the same as the last command + /* The DB this command was targeting is not the same as the last command * we appendend. To issue a SELECT command is needed. */ if (dictid != server.aof_selected_db) { char seldb[64]; diff --git a/src/bio.c b/src/bio.c index f3ddd6725..744c4c937 100644 --- a/src/bio.c +++ b/src/bio.c @@ -73,7 +73,7 @@ static list *bio_jobs[REDIS_BIO_NUM_OPS]; static unsigned long long bio_pending[REDIS_BIO_NUM_OPS]; /* This structure represents a background Job. It is only used locally to this - * file as the API deos not expose the internals at all. */ + * file as the API does not expose the internals at all. */ struct bio_job { time_t time; /* Time at which the job was created. */ /* Job specific arguments pointers. If we need to pass more than three diff --git a/src/bitops.c b/src/bitops.c index 3ef0a8f3d..75f3317a9 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -34,7 +34,7 @@ * Helpers and low level bit functions. * -------------------------------------------------------------------------- */ -/* This helper function used by GETBIT / SETBIT parses the bit offset arguemnt +/* This helper function used by GETBIT / SETBIT parses the bit offset argument * making sure an error is returned if it is negative or if it overflows * Redis 512 MB limit for the string value. */ static int getBitOffsetFromArgument(redisClient *c, robj *o, size_t *offset) { @@ -189,7 +189,7 @@ void bitopCommand(redisClient *c) { char *opname = c->argv[1]->ptr; robj *o, *targetkey = c->argv[2]; long op, j, numkeys; - robj **objects; /* Array of soruce objects. */ + robj **objects; /* Array of source objects. */ unsigned char **src; /* Array of source strings pointers. */ long *len, maxlen = 0; /* Array of length of src strings, and max len. */ long minlen = 0; /* Min len among the input keys. */ diff --git a/src/config.c b/src/config.c index 7e8f8a2ba..be2dbce19 100644 --- a/src/config.c +++ b/src/config.c @@ -329,7 +329,7 @@ void loadServerConfigFromString(char *config) { goto loaderr; } - /* If the target command name is the emtpy string we just + /* If the target command name is the empty string we just * remove it from the command table. */ retval = dictDelete(server.commands, argv[1]); redisAssert(retval == DICT_OK); @@ -367,7 +367,7 @@ void loadServerConfigFromString(char *config) { soft = memtoll(argv[3],NULL); soft_seconds = atoi(argv[4]); if (soft_seconds < 0) { - err = "Negative number of seconds in soft limt is invalid"; + err = "Negative number of seconds in soft limit is invalid"; goto loaderr; } server.client_obuf_limits[class].hard_limit_bytes = hard; @@ -412,7 +412,7 @@ loaderr: * in the 'options' string to the config file before loading. * * Both filename and options can be NULL, in such a case are considered - * emtpy. This way loadServerConfig can be used to just load a file or + * empty. This way loadServerConfig can be used to just load a file or * just load a string. */ void loadServerConfig(char *filename, char *options) { sds config = sdsempty(); diff --git a/src/db.c b/src/db.c index 59479574a..338566b36 100644 --- a/src/db.c +++ b/src/db.c @@ -44,7 +44,7 @@ robj *lookupKey(redisDb *db, robj *key) { if (de) { robj *val = dictGetVal(de); - /* Update the access time for the aging algorithm. + /* Update the access time for the ageing algorithm. * Don't do it if we have a saving child, as this will trigger * a copy on write madness. */ if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) @@ -85,7 +85,7 @@ robj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply) { } /* Add the key to the DB. It's up to the caller to increment the reference - * counte of the value if needed. + * counter of the value if needed. * * The program is aborted if the key already exists. */ void dbAdd(redisDb *db, robj *key, robj *val) { @@ -538,7 +538,7 @@ int expireIfNeeded(redisDb *db, robj *key) { * for *AT variants of the command, or the current time for relative expires). * * unit is either UNIT_SECONDS or UNIT_MILLISECONDS, and is only used for - * the argv[2] parameter. The basetime is always specified in milliesconds. */ + * the argv[2] parameter. The basetime is always specified in milliseconds. */ void expireGenericCommand(redisClient *c, long long basetime, int unit) { dictEntry *de; robj *key = c->argv[1], *param = c->argv[2]; diff --git a/src/debug.c b/src/debug.c index 9af6a6cc1..45364a292 100644 --- a/src/debug.c +++ b/src/debug.c @@ -42,7 +42,7 @@ /* ================================= Debugging ============================== */ /* Compute the sha1 of string at 's' with 'len' bytes long. - * The SHA1 is then xored againt the string pointed by digest. + * The SHA1 is then xored against the string pointed by digest. * Since xor is commutative, this operation is used in order to * "add" digests relative to unordered elements. * @@ -67,7 +67,7 @@ void xorObjectDigest(unsigned char *digest, robj *o) { } /* This function instead of just computing the SHA1 and xoring it - * against diget, also perform the digest of "digest" itself and + * against digest, also perform the digest of "digest" itself and * replace the old value with the new one. * * So the final digest will be: diff --git a/src/dict.c b/src/dict.c index 1e7d7609d..4bb60e0af 100644 --- a/src/dict.c +++ b/src/dict.c @@ -610,7 +610,7 @@ static int _dictExpandIfNeeded(dict *d) /* Incremental rehashing already in progress. Return. */ if (dictIsRehashing(d)) return DICT_OK; - /* If the hash table is empty expand it to the intial size. */ + /* If the hash table is empty expand it to the initial size. */ if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE); /* If we reached the 1:1 ratio, and we are allowed to resize the hash diff --git a/src/lzfP.h b/src/lzfP.h index d533f1829..10d804e04 100644 --- a/src/lzfP.h +++ b/src/lzfP.h @@ -93,7 +93,7 @@ /* * Avoid assigning values to errno variable? for some embedding purposes - * (linux kernel for example), this is neccessary. NOTE: this breaks + * (linux kernel for example), this is necessary. NOTE: this breaks * the documentation in lzf.h. */ #ifndef AVOID_ERRNO @@ -101,7 +101,7 @@ #endif /* - * Wether to pass the LZF_STATE variable as argument, or allocate it + * Whether to pass the LZF_STATE variable as argument, or allocate it * on the stack. For small-stack environments, define this to 1. * NOTE: this breaks the prototype in lzf.h. */ @@ -110,11 +110,11 @@ #endif /* - * Wether to add extra checks for input validity in lzf_decompress + * Whether to add extra checks for input validity in lzf_decompress * and return EINVAL if the input stream has been corrupted. This * only shields against overflowing the input buffer and will not * detect most corrupted streams. - * This check is not normally noticable on modern hardware + * This check is not normally noticeable on modern hardware * (<1% slowdown), but might slow down older cpus considerably. */ #ifndef CHECK_INPUT diff --git a/src/mkreleasehdr.sh b/src/mkreleasehdr.sh index 30984160e..dbf948c8a 100755 --- a/src/mkreleasehdr.sh +++ b/src/mkreleasehdr.sh @@ -3,7 +3,7 @@ GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n GIT_DIRTY=`git diff 2> /dev/null | wc -l` test -f release.h || touch release.h (cat release.h | grep SHA1 | grep $GIT_SHA1) && \ -(cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already uptodate +(cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already up-to-date echo "#define REDIS_GIT_SHA1 \"$GIT_SHA1\"" > release.h echo "#define REDIS_GIT_DIRTY \"$GIT_DIRTY\"" >> release.h touch release.c # Force recompile of release.c diff --git a/src/multi.c b/src/multi.c index 064a40944..dfac15c34 100644 --- a/src/multi.c +++ b/src/multi.c @@ -102,7 +102,7 @@ void discardCommand(redisClient *c) { } /* Send a MULTI command to all the slaves and AOF file. Check the execCommand - * implememntation for more information. */ + * implementation for more information. */ void execCommandReplicateMulti(redisClient *c) { robj *multistring = createStringObject("MULTI",5); @@ -223,7 +223,7 @@ void watchForKey(redisClient *c, robj *key) { incrRefCount(key); } listAddNodeTail(clients,c); - /* Add the new key to the lits of keys watched by this client */ + /* Add the new key to the list of keys watched by this client */ wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; diff --git a/src/networking.c b/src/networking.c index d1a8d3b3f..f48d27c07 100644 --- a/src/networking.c +++ b/src/networking.c @@ -378,7 +378,7 @@ void *addDeferredMultiBulkLength(redisClient *c) { return listLast(c->reply); } -/* Populate the length object and try glueing it to the next chunk. */ +/* Populate the length object and try gluing it to the next chunk. */ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { listNode *ln = (listNode*)node; robj *len, *next; @@ -404,7 +404,7 @@ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { asyncCloseClientOnOutputBufferLimitReached(c); } -/* Add a duble as a bulk reply */ +/* Add a double as a bulk reply */ void addReplyDouble(redisClient *c, double d) { char dbuf[128], sbuf[128]; int dlen, slen; @@ -526,7 +526,7 @@ static void acceptCommonHandler(int fd, int flags) { } /* If maxclient directive is set and this is one client more... close the * connection. Note that we create the client instead to check before - * for this condition, since now the socket is already set in nonblocking + * for this condition, since now the socket is already set in non-blocking * mode and we can send an error for free using the Kernel I/O */ if (listLength(server.clients) > server.maxclients) { char *err = "-ERR max number of clients reached\r\n"; @@ -941,7 +941,7 @@ int processMultibulkBuffer(redisClient *c) { /* Not enough data (+2 == trailing \r\n) */ break; } else { - /* Optimization: if the buffer contanins JUST our bulk element + /* Optimization: if the buffer containns JUST our bulk element * instead of creating a new object by *copying* the sds we * just use the current sds string. */ if (pos == 0 && diff --git a/src/object.c b/src/object.c index c2b89709d..00cf023b0 100644 --- a/src/object.c +++ b/src/object.c @@ -72,7 +72,7 @@ robj *createStringObjectFromLongDouble(long double value) { int len; /* We use 17 digits precision since with 128 bit floats that precision - * after rouding is able to represent most small decimal numbers in a way + * after rounding is able to represent most small decimal numbers in a way * that is "non surprising" for the user (that is, most small decimal * numbers will be represented in a way that when converted back into * a string are exactly the same as what the user typed.) */ diff --git a/src/pubsub.c b/src/pubsub.c index 8cd17df4f..973692948 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -117,7 +117,7 @@ int pubsubUnsubscribeChannel(redisClient *c, robj *channel, int notify) { return retval; } -/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the clinet was already subscribed to that pattern. */ +/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. */ int pubsubSubscribePattern(redisClient *c, robj *pattern) { int retval = 0; diff --git a/src/rdb.c b/src/rdb.c index 3d5ac2043..17f2ef840 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -265,7 +265,7 @@ err: return NULL; } -/* Save a string objet as [len][data] on disk. If the object is a string +/* Save a string object as [len][data] on disk. If the object is a string * representation of an integer value we try to save it in a special form */ int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) { int enclen; @@ -321,7 +321,7 @@ int rdbSaveLongLongAsStringObject(rio *rdb, long long value) { /* Like rdbSaveStringObjectRaw() but handle encoded objects */ int rdbSaveStringObject(rio *rdb, robj *obj) { /* Avoid to decode the object, then encode it again, if the - * object is alrady integer encoded. */ + * object is already integer encoded. */ if (obj->encoding == REDIS_ENCODING_INT) { return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr); } else { @@ -367,7 +367,7 @@ robj *rdbLoadEncodedStringObject(rio *rdb) { } /* Save a double value. Doubles are saved as strings prefixed by an unsigned - * 8 bit integer specifing the length of the representation. + * 8 bit integer specifying the length of the representation. * This 8 bit integer has special values in order to specify the following * conditions: * 253: not a number @@ -606,7 +606,7 @@ off_t rdbSavedObjectLen(robj *o) { /* Save a key-value pair, with expire time, type, key, value. * On error -1 is returned. - * On success if the key was actaully saved 1 is returned, otherwise 0 + * On success if the key was actually saved 1 is returned, otherwise 0 * is returned (the key was already expired). */ int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now) @@ -1109,7 +1109,7 @@ int rdbLoad(char *filename) { /* We read the time so we need to read the object type again. */ if ((type = rdbLoadType(&rdb)) == -1) goto eoferr; /* the EXPIRETIME opcode specifies time in seconds, so convert - * into milliesconds. */ + * into milliseconds. */ expiretime *= 1000; } else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS) { /* Milliseconds precision expire times introduced with RDB diff --git a/src/rdb.h b/src/rdb.h index d0f2aad86..54ee4e514 100644 --- a/src/rdb.h +++ b/src/rdb.h @@ -51,7 +51,7 @@ * number specify the kind of object that follows. * See the REDIS_RDB_ENC_* defines. * - * Lenghts up to 63 are stored using a single byte, most DB keys, and may + * Lengths up to 63 are stored using a single byte, most DB keys, and may * values, will fit inside. */ #define REDIS_RDB_6BITLEN 0 #define REDIS_RDB_14BITLEN 1 diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index 7efecb1a3..85ab9b96c 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -78,7 +78,7 @@ * number specify the kind of object that follows. * See the REDIS_RDB_ENC_* defines. * - * Lenghts up to 63 are stored using a single byte, most DB keys, and may + * Lengths up to 63 are stored using a single byte, most DB keys, and may * values, will fit inside. */ #define REDIS_RDB_6BITLEN 0 #define REDIS_RDB_14BITLEN 1 @@ -132,7 +132,7 @@ typedef struct { char success; } entry; -/* Global vars that are actally used as constants. The following double +/* Global vars that are actually used as constants. The following double * values are used for double on-disk serialization, and are initialized * at runtime to avoid strange compiler optimizations. */ static double R_Zero, R_PosInf, R_NegInf, R_Nan; diff --git a/src/redis-cli.c b/src/redis-cli.c index 1fb076fa5..318f1822a 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -308,7 +308,7 @@ static int cliSelect() { return REDIS_ERR; } -/* Connect to the client. If force is not zero the connection is performed +/* Connect to the server. If force is not zero the connection is performed * even if there is already a connected socket. */ static int cliConnect(int force) { if (context == NULL || force) { @@ -976,7 +976,7 @@ static void slaveMode(void) { char buf[1024]; fprintf(stderr,"SYNC with master, discarding %llu " - "bytes of bulk tranfer...\n", payload); + "bytes of bulk transfer...\n", payload); /* Discard the payload. */ while(payload) { @@ -1141,7 +1141,7 @@ static void pipeMode(void) { int j; eof = 1; - /* Everything transfered, so we queue a special + /* Everything transferred, so we queue a special * ECHO command that we can match in the replies * to make sure everything was read from the server. */ for (j = 0; j < 20; j++) diff --git a/src/redis.c b/src/redis.c index 23083fbff..c2f40f7de 100644 --- a/src/redis.c +++ b/src/redis.c @@ -99,7 +99,7 @@ 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, regardless 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 @@ -288,7 +288,7 @@ void redisLogRaw(int level, const char *msg) { if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg); } -/* Like redisLogRaw() but with printf-alike support. This is the funciton that +/* Like redisLogRaw() but with printf-alike support. This is the function that * is used across the code. The raw version is only used in order to dump * the INFO output on crash. */ void redisLog(int level, const char *fmt, ...) { @@ -363,7 +363,7 @@ void exitFromChild(int retcode) { /*====================== Hash table type implementation ==================== */ -/* This is an hash table type that uses the SDS dynamic strings libary as +/* This is an hash table type that uses the SDS dynamic strings library as * keys and radis objects as values (objects can hold SDS strings, * lists, sets). */ @@ -537,7 +537,7 @@ dictType commandTableDictType = { NULL /* val destructor */ }; -/* Hash type hash table (note that small hashes are represented with zimpaps) */ +/* Hash type hash table (note that small hashes are represented with zipmaps) */ dictType hashDictType = { dictEncObjHash, /* hash function */ NULL, /* key dup */ @@ -738,7 +738,7 @@ int clientsCronHandleTimeout(redisClient *c) { /* The client query buffer is an sds.c string that can end with a lot of * free space not used, this function reclaims space if needed. * - * The funciton always returns 0 as it never terminates the client. */ + * The function always returns 0 as it never terminates the client. */ int clientsCronResizeQueryBuffer(redisClient *c) { size_t querybuf_size = sdsAllocSize(c->querybuf); time_t idletime = server.unixtime - c->lastinteraction; @@ -796,11 +796,11 @@ void clientsCron(void) { * * - Active expired keys collection (it is also performed in a lazy way on * lookup). - * - Software watchdong. + * - Software watchdog. * - Update some statistic. * - Incremental rehashing of the DBs hash tables. * - Triggering BGSAVE / AOF rewrite, and handling of terminated children. - * - Clients timeout of differnet kinds. + * - Clients timeout of different kinds. * - Replication reconnection. * - Many more... * @@ -829,7 +829,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { /* We have just 22 bits per object for LRU information. * So we use an (eventually wrapping) LRU clock with 10 seconds resolution. - * 2^22 bits with 10 seconds resoluton is more or less 1.5 years. + * 2^22 bits with 10 seconds resolution is more or less 1.5 years. * * Note that even if this will wrap after 1.5 years it's not a problem, * everything will still work but just some object will appear younger @@ -867,7 +867,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { } } - /* We don't want to resize the hash tables while a bacground saving + /* We don't want to resize the hash tables while a background saving * is in progress: the saving child is created using fork() that is * implemented with a copy-on-write semantic in most modern systems, so * if we resize the HT while there is the saving child at work actually @@ -1178,7 +1178,7 @@ void initServerConfig() { R_NegInf = -1.0/R_Zero; R_Nan = R_Zero/R_Zero; - /* Command table -- we intiialize it here as it is part of the + /* Command table -- we initiialize it here as it is part of the * initial configuration, since command names may be changed via * redis.conf using the rename-command directive. */ server.commands = dictCreate(&commandTableDictType,NULL); @@ -1488,7 +1488,7 @@ void call(redisClient *c, int flags) { long long dirty, start = ustime(), duration; /* Sent the command to clients in MONITOR mode, only if the commands are - * not geneated from reading an AOF. */ + * not generated from reading an AOF. */ if (listLength(server.monitors) && !server.loading && !(c->cmd->flags & REDIS_CMD_SKIP_MONITOR)) @@ -1550,8 +1550,8 @@ void call(redisClient *c, int flags) { * server for a bulk read from the client. * * If 1 is returned the client is still alive and valid and - * and other operations can be performed by the caller. Otherwise - * if 0 is returned the client was destroied (i.e. after QUIT). */ + * other operations can be performed by the caller. Otherwise + * if 0 is returned the client was destroyed (i.e. after QUIT). */ int processCommand(redisClient *c) { /* The QUIT command is handled separately. Normal command procs will * go through checking for replication and QUIT will cause trouble @@ -1804,7 +1804,7 @@ void echoCommand(redisClient *c) { void timeCommand(redisClient *c) { struct timeval tv; - /* gettimeofday() can only fail if &tv is a bad addresss so we + /* gettimeofday() can only fail if &tv is a bad address so we * don't check for errors. */ gettimeofday(&tv,NULL); addReplyMultiBulkLen(c,2); diff --git a/src/redis.h b/src/redis.h index 1133fed5b..682829b7b 100644 --- a/src/redis.h +++ b/src/redis.h @@ -142,12 +142,12 @@ * * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte * 01|000000 00000000 => 01, the len is 14 byes, 6 bits + 8 bits of next byte - * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow + * 10|000000 [32 bit integer] => if it's 10, a full 32 bit len will follow * 11|000000 this means: specially encoded object will follow. The six bits * number specify the kind of object that follows. * See the REDIS_RDB_ENC_* defines. * - * Lenghts up to 63 are stored using a single byte, most DB keys, and may + * Lengths up to 63 are stored using a single byte, most DB keys, and may * values, will fit inside. */ #define REDIS_RDB_6BITLEN 0 #define REDIS_RDB_14BITLEN 1 @@ -317,7 +317,7 @@ typedef struct redisObject { void *ptr; } robj; -/* Macro used to initalize a Redis object allocated on the stack. +/* Macro used to initialize a Redis object allocated on the stack. * Note that this macro is taken near the structure definition to make sure * we'll update it when the structure is changed, to avoid bugs like * bug #85 introduced exactly in this way. */ @@ -374,7 +374,7 @@ typedef struct readyList { robj *key; } readyList; -/* With multiplexing we need to take per-clinet state. +/* With multiplexing we need to take per-client state. * Clients are taken in a liked list. */ typedef struct redisClient { int fd; @@ -536,7 +536,7 @@ struct redisServer { long long stat_keyspace_hits; /* Number of successful lookups of keys */ long long stat_keyspace_misses; /* Number of failed lookups of keys */ size_t stat_peak_memory; /* Max used memory record */ - long long stat_fork_time; /* Time needed to perform latets fork() */ + long long stat_fork_time; /* Time needed to perform latest fork() */ long long stat_rejected_conn; /* Clients rejected because of maxclients */ list *slowlog; /* SLOWLOG list of commands */ long long slowlog_entry_id; /* SLOWLOG current entry ID */ @@ -585,7 +585,7 @@ struct redisServer { char *rdb_filename; /* Name of RDB file */ int rdb_compression; /* Use compression in RDB? */ int rdb_checksum; /* Use RDB checksum? */ - time_t lastsave; /* Unix time of last save succeeede */ + time_t lastsave; /* Unix time of last successful save */ time_t rdb_save_time_last; /* Time used by last RDB save run. */ time_t rdb_save_time_start; /* Current RDB save start time. */ int lastbgsave_status; /* REDIS_OK or REDIS_ERR */ @@ -620,7 +620,7 @@ struct redisServer { /* Limits */ unsigned int maxclients; /* Max number of simultaneous clients */ unsigned long long maxmemory; /* Max number of memory bytes to use */ - int maxmemory_policy; /* Policy for key evition */ + int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Pricision of random sampling */ /* Blocked clients */ unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */ @@ -657,7 +657,7 @@ struct redisServer { int lua_timedout; /* True if we reached the time limit for script execution. */ int lua_kill; /* Kill the script if true. */ - /* Assert & bug reportign */ + /* Assert & bug reporting */ char *assert_failed; char *assert_file; int assert_line; @@ -676,13 +676,13 @@ struct redisCommand { char *name; redisCommandProc *proc; int arity; - char *sflags; /* Flags as string represenation, one char per flag. */ + char *sflags; /* Flags as string representation, one char per flag. */ int flags; /* The actual flags, obtained from the 'sflags' field. */ /* Use a function to determine keys arguments in a command line. */ redisGetKeysProc *getkeys_proc; /* What keys should be loaded in background when calling this command? */ int firstkey; /* The first argument that's a key (0 = no keys) */ - int lastkey; /* THe last argument that's a key */ + int lastkey; /* The last argument that's a key */ int keystep; /* The step between first and last key */ long long microseconds, calls; }; @@ -729,7 +729,7 @@ typedef struct { dictIterator *di; } setTypeIterator; -/* Structure to hold hash iteration abstration. Note that iteration over +/* Structure to hold hash iteration abstraction. Note that iteration over * hashes involves both fields and values. Because it is possible that * not both are required, store pointers in the iterator to avoid * unnecessary memory allocation for fields/values. */ diff --git a/src/release.c b/src/release.c index 46761448c..296db67b3 100644 --- a/src/release.c +++ b/src/release.c @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* Every time the Redis Git SHA1 or Dirty status changes only this file - * small file is recompiled, as we access this information in all the other +/* Every time the Redis Git SHA1 or Dirty status changes only this small + * file is recompiled, as we access this information in all the other * files using this functions. */ #include "release.h" diff --git a/src/replication.c b/src/replication.c index 20b6e8555..dc90c8d0e 100644 --- a/src/replication.c +++ b/src/replication.c @@ -52,7 +52,7 @@ void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) { if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) continue; /* Feed slaves that are waiting for the initial SYNC (so these commands - * are queued in the output buffer until the intial SYNC completes), + * are queued in the output buffer until the initial SYNC completes), * or are already in sync with the master. */ if (slave->slaveseldb != dictid) { robj *selectcmd; @@ -115,7 +115,7 @@ void replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj ** } void syncCommand(redisClient *c) { - /* ignore SYNC if aleady slave or in monitor mode */ + /* ignore SYNC if already slave or in monitor mode */ if (c->flags & REDIS_SLAVE) return; /* Refuse SYNC requests if we are a slave but the link with our master @@ -229,7 +229,7 @@ void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) { if (slave->repldboff == 0) { /* Write the bulk write count before to transfer the DB. In theory here * we don't know how much room there is in the output buffer of the - * socket, but in pratice SO_SNDLOWAT (the minimum count for output + * socket, but in practice SO_SNDLOWAT (the minimum count for output * operations) will never be smaller than the few bytes we need. */ sds bulkcount; @@ -272,7 +272,7 @@ void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) { } } -/* This function is called at the end of every backgrond saving. +/* This function is called at the end of every background saving. * The argument bgsaveerr is REDIS_OK if the background saving succeeded * otherwise REDIS_ERR is passed to the function. * @@ -451,7 +451,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { stopAppendOnly(); while (retry-- && startAppendOnly() == REDIS_ERR) { - redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchrnization! Trying it again in one second."); + redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchronization! Trying it again in one second."); sleep(1); } if (!retry) { diff --git a/src/scripting.c b/src/scripting.c index 46301eb11..6661f3748 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -48,7 +48,7 @@ void sha1hex(char *digest, char *script, size_t len); /* Take a Redis reply in the Redis protocol format and convert it into a * Lua type. Thanks to this function, and the introduction of not connected - * clients, it is trvial to implement the redis() lua function. + * clients, it is trivial to implement the redis() lua function. * * Basically we take the arguments, execute the Redis command in the context * of a non connected client, then take the generated reply and convert it @@ -58,7 +58,7 @@ void sha1hex(char *digest, char *script, size_t len); * * Note: in this function we do not do any sanity check as the reply is * generated by Redis directly. This allows us to go faster. - * The reply string can be altered during the parsing as it is discared + * The reply string can be altered during the parsing as it is discarded * after the conversion is completed. * * Errors are returned as a table with a single 'err' field set to the @@ -597,7 +597,7 @@ void scriptingInit(void) { lua_setglobal(lua,"math"); - /* Add a helper funciton that we use to sort the multi bulk output of non + /* Add a helper function that we use to sort the multi bulk output of non * deterministic commands, when containing 'false' elements. */ { char *compare_func = "function __redis__compare_helper(a,b)\n" @@ -638,7 +638,7 @@ void scriptingReset(void) { scriptingInit(); } -/* Perform the SHA1 of the input string. We use this both for hasing script +/* Perform the SHA1 of the input string. We use this both for hashing script * bodies in order to obtain the Lua function name, and in the implementation * of redis.sha1(). * @@ -677,7 +677,7 @@ void luaReplyToRedisReply(redisClient *c, lua_State *lua) { case LUA_TTABLE: /* We need to check if it is an array, an error, or a status reply. * Error are returned as a single element table with 'err' field. - * Status replies are returned as single elment table with 'ok' field */ + * Status replies are returned as single element table with 'ok' field */ lua_pushstring(lua,"err"); lua_gettable(lua,-2); t = lua_type(lua,-1); @@ -834,7 +834,7 @@ void evalGenericCommand(redisClient *c, int evalsha) { if (lua_isnil(lua,1)) { lua_pop(lua,1); /* remove the nil from the stack */ /* Function not defined... let's define it if we have the - * body of the funciton. If this is an EVALSHA call we can just + * body of the function. If this is an EVALSHA call we can just * return an error. */ if (evalsha) { addReply(c, shared.noscripterr); diff --git a/src/sds.c b/src/sds.c index e8491acfa..85858a4f0 100644 --- a/src/sds.c +++ b/src/sds.c @@ -141,7 +141,7 @@ size_t sdsAllocSize(sds s) { * right-trim the string. * * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the - * following schema to cat bytes coming from the kerenl to the end of an + * following schema to cat bytes coming from the kernel to the end of an * sds string new things without copying into an intermediate buffer: * * oldlen = sdslen(s); @@ -596,7 +596,7 @@ void sdssplitargs_free(sds *argv, int argc) { } /* Modify the string substituting all the occurrences of the set of - * characters specifed in the 'from' string to the corresponding character + * characters specified in the 'from' string to the corresponding character * in the 'to' array. * * For instance: sdsmapchars(mystring, "ho", "01", 2) diff --git a/src/sentinel.c b/src/sentinel.c index d8a960713..8009e5ed9 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -969,9 +969,9 @@ const char *sentinelRedisInstanceTypeStr(sentinelRedisInstance *ri) { * a master's Sentinels dictionary, we want to be very sure about not * having duplicated instances for any reason. This is so important because * we use those other sentinels in order to run our quorum protocol to - * understand if it's time to proceeed with the fail over. + * understand if it's time to proceed with the fail over. * - * Making sure no duplication is possible we greately improve the robustness + * Making sure no duplication is possible we greatly improve the robustness * of the quorum (otherwise we may end counting the same instance multiple * times for some reason). * @@ -1238,7 +1238,7 @@ void sentinelKillLink(sentinelRedisInstance *ri, redisAsyncContext *c) { * cleanup needed. * * Note: we don't free the hiredis context as hiredis will do it for us - * for async conenctions. */ + * for async connections. */ void sentinelDisconnectInstanceFromContext(const redisAsyncContext *c) { sentinelRedisInstance *ri = c->data; int pubsub; @@ -1647,7 +1647,7 @@ void sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privd /* Update the last activity in the pubsub channel. Note that since we * receive our messages as well this timestamp can be used to detect - * if the link is probably diconnected even if it seems otherwise. */ + * if the link is probably disconnected even if it seems otherwise. */ ri->pc_last_activity = mstime(); /* Sanity check in the reply we expect, so that the code that follows @@ -1939,7 +1939,7 @@ void addReplySentinelRedisInstance(redisClient *c, sentinelRedisInstance *ri) { setDeferredMultiBulkLength(c,mbl,fields*2); } -/* Output a number of instances contanined inside a dictionary as +/* Output a number of instances contained inside a dictionary as * Redis protocol. */ void addReplyDictOfRedisInstances(redisClient *c, dict *instances) { dictIterator *di; @@ -2535,7 +2535,7 @@ void sentinelStartFailoverIfNeeded(sentinelRedisInstance *master) { * 3) info_refresh more recent than SENTINEL_INFO_VALIDITY_TIME. * 4) master_link_down_time no more than: * (now - master->s_down_since_time) + (master->down_after_period * 10). - * 5) Slave priority can't be zero, otherwise the slave is discareded. + * 5) Slave priority can't be zero, otherwise the slave is discarded. * * Among all the slaves matching the above conditions we select the slave * with lower slave_priority. If priority is the same we select the slave @@ -2611,10 +2611,10 @@ void sentinelFailoverWaitStart(sentinelRedisInstance *ri) { /* If we in "wait start" but the master is no longer in ODOWN nor in * SDOWN condition we abort the failover. This is important as it * prevents a useless failover in a a notable case of netsplit, where - * the senitnels are split from the redis instances. In this case + * the sentinels are split from the redis instances. In this case * the failover will not start while there is the split because no * good slave can be reached. However when the split is resolved, we - * can go to waitstart if the slave is back rechable a few milliseconds + * can go to waitstart if the slave is back reachable a few milliseconds * before the master is. In that case when the master is back online * we cancel the failover. */ if ((ri->flags & (SRI_S_DOWN|SRI_O_DOWN|SRI_FORCE_FAILOVER)) == 0) { @@ -3026,13 +3026,13 @@ void sentinelHandleDictOfRedisInstances(dict *instances) { * following conditions happen: * * 1) The Sentiel process for some time is blocked, for every kind of - * random reason: the load is huge, the computer was freezed for some time + * random reason: the load is huge, the computer was frozen for some time * in I/O or alike, the process was stopped by a signal. Everything. * 2) The system clock was altered significantly. * * Under both this conditions we'll see everything as timed out and failing * without good reasons. Instead we enter the TILT mode and wait - * for SENTIENL_TILT_PERIOD to elapse before starting to act again. + * for SENTINEL_TILT_PERIOD to elapse before starting to act again. * * During TILT time we still collect information, we just do not act. */ void sentinelCheckTiltCondition(void) { diff --git a/src/sha1.c b/src/sha1.c index 26a5565ee..59e6f461d 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -57,13 +57,13 @@ A million repetitions of "a" void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]) { -u_int32_t a, b, c, d, e; -typedef union { - unsigned char c[64]; - u_int32_t l[16]; -} CHAR64LONG16; + u_int32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + u_int32_t l[16]; + } CHAR64LONG16; #ifdef SHA1HANDSOFF -CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ memcpy(block, buffer, 64); #else /* The following had better never be used because it causes the @@ -71,7 +71,7 @@ CHAR64LONG16 block[1]; /* use array to appear as a pointer */ * And the result is written through. I threw a "const" in, hoping * this will cause a diagnostic. */ -CHAR64LONG16* block = (const CHAR64LONG16*)buffer; + CHAR64LONG16* block = (const CHAR64LONG16*)buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; @@ -132,12 +132,11 @@ void SHA1Init(SHA1_CTX* context) void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len) { -u_int32_t i; -u_int32_t j; + u_int32_t i, j; j = context->count[0]; if ((context->count[0] += len << 3) < j) - context->count[1]++; + context->count[1]++; context->count[1] += (len>>29); j = (j >> 3) & 63; if ((j + len) > 63) { @@ -157,9 +156,9 @@ u_int32_t j; void SHA1Final(unsigned char digest[20], SHA1_CTX* context) { -unsigned i; -unsigned char finalcount[8]; -unsigned char c; + unsigned i; + unsigned char finalcount[8]; + unsigned char c; #if 0 /* untested "improvement" by DHR */ /* Convert context->count to a sequence of bytes @@ -170,12 +169,12 @@ unsigned char c; unsigned char *fcp = &finalcount[8]; for (i = 0; i < 2; i++) - { - u_int32_t t = context->count[i]; - int j; + { + u_int32_t t = context->count[i]; + int j; - for (j = 0; j < 4; t >>= 8, j++) - *--fcp = (unsigned char) t + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t; } #else for (i = 0; i < 8; i++) { @@ -226,3 +225,4 @@ main(int argc, char **argv) } #endif + diff --git a/src/sort.c b/src/sort.c index 39505b136..cd54072f3 100644 --- a/src/sort.c +++ b/src/sort.c @@ -45,7 +45,7 @@ redisSortOperation *createSortOperation(int type, robj *pattern) { /* Return the value associated to the key with a name obtained using * the following rules: * - * 1) The first occurence of '*' in 'pattern' is substituted with 'subst'. + * 1) The first occurrence of '*' in 'pattern' is substituted with 'subst'. * * 2) If 'pattern' matches the "->" string, everything on the left of * the arrow is treated as the name of an hash field, and the part on the @@ -147,7 +147,7 @@ int sortCompare(const void *s1, const void *s2) { cmp = -1; } else { /* Objects have the same score, but we don't want the comparison - * to be undefined, so we compare objects lexicographycally. + * to be undefined, so we compare objects lexicographically. * This way the result of SORT is deterministic. */ cmp = compareStringObjects(so1->obj,so2->obj); } @@ -205,7 +205,7 @@ void sortCommand(redisClient *c) { /* Now we need to protect sortval incrementing its count, in the future * SORT may have options able to overwrite/delete keys during the sorting - * and the sorted key itself may get destroied */ + * and the sorted key itself may get destroyed */ if (sortval) incrRefCount(sortval); else diff --git a/src/t_list.c b/src/t_list.c index 50db6c536..16b5e1be5 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -45,10 +45,10 @@ void listTypeTryConversion(robj *subject, robj *value) { listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST); } -/* The function pushes an elmenet to the specified list object 'subject', +/* The function pushes an element to the specified list object 'subject', * at head or tail position as specified by 'where'. * - * There is no need for the caller to incremnet the refcount of 'value' as + * There is no need for the caller to increment the refcount of 'value' as * the function takes care of it if needed. */ void listTypePush(robj *subject, robj *value, int where) { /* Check if we need to convert the ziplist */ @@ -825,7 +825,7 @@ void unblockClientWaitingData(redisClient *c) { /* If the specified key has clients blocked waiting for list pushes, this * function will put the key reference into the server.ready_keys list. * Note that db->ready_keys is an hash table that allows us to avoid putting - * the same key agains and again in the list in case of multiple pushes + * the same key again and again in the list in case of multiple pushes * made by a script or in the context of MULTI/EXEC. * * The list will be finally processed by handleClientsBlockedOnLists() */ @@ -858,7 +858,7 @@ void signalListAsReady(redisClient *c, robj *key) { * * 1) Provide the client with the 'value' element. * 2) If the dstkey is not NULL (we are serving a BRPOPLPUSH) also push the - * 'value' element on the destionation list (the LPUSH side of the command). + * 'value' element on the destination list (the LPUSH side of the command). * 3) Propagate the resulting BRPOP, BLPOP and additional LPUSH if any into * the AOF and replication channel. * @@ -868,7 +868,7 @@ void signalListAsReady(redisClient *c, robj *key) { * * The function returns REDIS_OK if we are able to serve the client, otherwise * REDIS_ERR is returned to signal the caller that the list POP operation - * should be undoed as the client was not served: This only happens for + * should be undone as the client was not served: This only happens for * BRPOPLPUSH that fails to push the value to the destination key as it is * of the wrong type. */ int serveClientBlockedOnList(redisClient *receiver, robj *key, robj *dstkey, redisDb *db, robj *value, int where) diff --git a/src/t_set.c b/src/t_set.c index 46a0c6ee5..3064807d1 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -188,7 +188,7 @@ robj *setTypeNextObject(setTypeIterator *si) { * The caller provides both pointers to be populated with the right * object. The return value of the function is the object->encoding * field of the object and is used by the caller to check if the - * int64_t pointer or the redis object pointere was populated. + * int64_t pointer or the redis object pointer was populated. * * When an object is returned (the set was a real set) the ref count * of the object is not incremented so this function can be considered @@ -598,7 +598,7 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum, sets[j] = setobj; } /* Sort sets from the smallest to largest, this will improve our - * algorithm's performace */ + * algorithm's performance */ qsort(sets,setnum,sizeof(robj*),qsortCompareSetsByCardinality); /* The first thing we should output is the total number of elements... diff --git a/src/t_string.c b/src/t_string.c index 00510c710..8ba915a58 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -43,7 +43,7 @@ static int checkStringLength(redisClient *c, long long size) { } void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire, int unit) { - long long milliseconds = 0; /* initialized to avoid an harmness warning */ + long long milliseconds = 0; /* initialized to avoid any harmness warning */ if (expire) { if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != REDIS_OK) @@ -340,7 +340,7 @@ void incrbyfloatCommand(redisClient *c) { addReplyBulk(c,new); /* Always replicate INCRBYFLOAT as a SET command with the final value - * in order to make sure that differences in float pricision or formatting + * in order to make sure that differences in float prrcision or formatting * will not create differences in replicas or after an AOF restart. */ aux = createStringObject("SET",3); rewriteClientCommandArgument(c,0,aux); diff --git a/src/t_zset.c b/src/t_zset.c index f5cdec3e4..0d92f681f 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -125,7 +125,7 @@ zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) { } /* we assume the key is not already inside, since we allow duplicated * scores, and the re-insertion of score and redis object should never - * happpen since the caller of zslInsert() should test in the hash table + * happen since the caller of zslInsert() should test in the hash table * if the element is already inside or not. */ level = zslRandomLevel(); if (level > zsl->level) { @@ -285,7 +285,7 @@ zskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec range) { } /* Delete all the elements with score between min and max from the skiplist. - * Min and mx are inclusive, so a score >= min || score <= max is deleted. + * Min and max are inclusive, so a score >= min || score <= max is deleted. * Note that this function takes the reference to the hash table view of the * sorted set, in order to remove the elements from the hash table too. */ unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec range, dict *dict) { diff --git a/src/zmalloc.c b/src/zmalloc.c index 1f8c7f08e..71e9e0820 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -250,7 +250,7 @@ void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) { * * For this kind of "fast RSS reporting" usages use instead the * function RedisEstimateRSS() that is a much faster (and less precise) - * version of the funciton. */ + * version of the function. */ #if defined(HAVE_PROCFS) #include diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 3dbfc902b..e42f87725 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -34,7 +34,7 @@ start_server {tags {"scripting"}} { r eval {return {1,2,3,'ciao',{1,2}}} 0 } {1 2 3 ciao {1 2}} - test {EVAL - Are the KEYS and ARGS arrays populated correctly?} { + test {EVAL - Are the KEYS and ARGV arrays populated correctly?} { r eval {return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}} 2 a b c d } {a b c d} -- cgit v1.2.1 From dbde1d85ea63009f12ec164653eb994d07827276 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 19 Jan 2013 12:52:05 +0100 Subject: Slowlog: don't log EXEC but just the executed commands. The Redis Slow Log always used to log the slow commands executed inside a MULTI/EXEC block. However also EXEC was logged at the end, which is perfectly useless. Now EXEC is no longer logged and a test was added to test this behavior. This fixes issue #759. --- src/redis.c | 2 +- tests/unit/slowlog.tcl | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/redis.c b/src/redis.c index c2f40f7de..15ef74379 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1510,7 +1510,7 @@ void call(redisClient *c, int flags) { /* Log the command into the Slow log if needed, and populate the * per-command statistics that we show in INFO commandstats. */ - if (flags & REDIS_CALL_SLOWLOG) + if (flags & REDIS_CALL_SLOWLOG && c->cmd->proc != execCommand) slowlogPushEntryIfNeeded(c->argv,c->argc,duration); if (flags & REDIS_CALL_STATS) { c->cmd->microseconds += duration; diff --git a/tests/unit/slowlog.tcl b/tests/unit/slowlog.tcl index 2216e925a..b25b91e2c 100644 --- a/tests/unit/slowlog.tcl +++ b/tests/unit/slowlog.tcl @@ -55,4 +55,16 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { set e [lindex [r slowlog get] 0] lindex $e 3 } {sadd set foo {AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (1 more bytes)}} + + test {SLOWLOG - EXEC is not logged, just executed commands} { + r config set slowlog-log-slower-than 100000 + r slowlog reset + assert_equal [r slowlog len] 0 + r multi + r debug sleep 0.2 + r exec + assert_equal [r slowlog len] 1 + set e [lindex [r slowlog get] 0] + assert_equal [lindex $e 3] {debug sleep 0.2} + } } -- cgit v1.2.1 From 9e5b70162c97ef794c9173e6cc3dd9e68117a9ea Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 19 Jan 2013 13:19:41 +0100 Subject: Clear server.shutdown_asap on failed shutdown. When a SIGTERM is received Redis schedules a shutdown. However if it fails to perform the shutdown it must be clear the shutdown_asap flag otehrwise it will try again and again possibly making the server unusable. --- src/redis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/redis.c b/src/redis.c index 15ef74379..fa86f50d3 100644 --- a/src/redis.c +++ b/src/redis.c @@ -850,6 +850,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { if (server.shutdown_asap) { if (prepareForShutdown(0) == REDIS_OK) exit(0); redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information"); + server.shutdown_asap = 0; } /* Show some info about non-empty databases */ -- cgit v1.2.1 From da540228d83c088b6c31de1f0d88a742a3aee870 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 14 Jan 2013 10:29:14 +0100 Subject: Whitelist SIGUSR1 to avoid auto-triggering errors. This commit fixes issue #875 that was caused by the following events: 1) There is an active child doing BGSAVE. 2) flushall is called (or any other condition that makes Redis killing the saving child process). 3) An error is sensed by Redis as the child exited with an error (killed by a singal), that stops accepting write commands until a BGSAVE happens to be executed with success. Whitelisting SIGUSR1 and making sure Redis always uses this signal in order to kill its own children fixes the issue. --- src/aof.c | 2 +- src/db.c | 2 +- src/rdb.c | 5 ++++- src/redis.c | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/aof.c b/src/aof.c index 7e1512ebd..8dc1dd188 100644 --- a/src/aof.c +++ b/src/aof.c @@ -177,7 +177,7 @@ void stopAppendOnly(void) { redisLog(REDIS_NOTICE,"Killing running AOF rewrite child: %ld", (long) server.aof_child_pid); - if (kill(server.aof_child_pid,SIGKILL) != -1) + if (kill(server.aof_child_pid,SIGUSR1) != -1) wait3(&statloc,0,NULL); /* reset the buffer accumulating changes while the child saves */ aofRewriteBufferReset(); diff --git a/src/db.c b/src/db.c index 338566b36..e67661f12 100644 --- a/src/db.c +++ b/src/db.c @@ -219,7 +219,7 @@ void flushallCommand(redisClient *c) { server.dirty += emptyDb(); addReply(c,shared.ok); if (server.rdb_child_pid != -1) { - kill(server.rdb_child_pid,SIGKILL); + kill(server.rdb_child_pid,SIGUSR1); rdbRemoveTempFile(server.rdb_child_pid); } if (server.saveparamslen > 0) { diff --git a/src/rdb.c b/src/rdb.c index 17f2ef840..a5e4c47af 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1194,7 +1194,10 @@ void backgroundSaveDoneHandler(int exitcode, int bysignal) { redisLog(REDIS_WARNING, "Background saving terminated by signal %d", bysignal); rdbRemoveTempFile(server.rdb_child_pid); - server.lastbgsave_status = REDIS_ERR; + /* SIGUSR1 is whitelisted, so we have a way to kill a child without + * tirggering an error conditon. */ + if (bysignal != SIGUSR1) + server.lastbgsave_status = REDIS_ERR; } server.rdb_child_pid = -1; server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start; diff --git a/src/redis.c b/src/redis.c index fa86f50d3..5af5200e8 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1694,7 +1694,7 @@ int prepareForShutdown(int flags) { overwrite the synchronous saving did by SHUTDOWN. */ if (server.rdb_child_pid != -1) { redisLog(REDIS_WARNING,"There is a child saving an .rdb. Killing it!"); - kill(server.rdb_child_pid,SIGKILL); + kill(server.rdb_child_pid,SIGUSR1); rdbRemoveTempFile(server.rdb_child_pid); } if (server.aof_state != REDIS_AOF_OFF) { @@ -1703,7 +1703,7 @@ int prepareForShutdown(int flags) { if (server.aof_child_pid != -1) { redisLog(REDIS_WARNING, "There is a child rewriting the AOF. Killing it!"); - kill(server.aof_child_pid,SIGKILL); + kill(server.aof_child_pid,SIGUSR1); } /* Append only file: fsync() the AOF and exit */ redisLog(REDIS_NOTICE,"Calling fsync() on the AOF file."); -- cgit v1.2.1 From a154908a8f74bba56c1b307df2cffec1c5f97ae3 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 19 Jan 2013 13:46:14 +0100 Subject: Additionally two typos fixed thanks to @jodal --- src/networking.c | 2 +- src/t_string.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/networking.c b/src/networking.c index f48d27c07..6e5d32489 100644 --- a/src/networking.c +++ b/src/networking.c @@ -941,7 +941,7 @@ int processMultibulkBuffer(redisClient *c) { /* Not enough data (+2 == trailing \r\n) */ break; } else { - /* Optimization: if the buffer containns JUST our bulk element + /* Optimization: if the buffer contains JUST our bulk element * instead of creating a new object by *copying* the sds we * just use the current sds string. */ if (pos == 0 && diff --git a/src/t_string.c b/src/t_string.c index 8ba915a58..0a7f22583 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -340,7 +340,7 @@ void incrbyfloatCommand(redisClient *c) { addReplyBulk(c,new); /* Always replicate INCRBYFLOAT as a SET command with the final value - * in order to make sure that differences in float prrcision or formatting + * in order to make sure that differences in float precision or formatting * will not create differences in replicas or after an AOF restart. */ aux = createStringObject("SET",3); rewriteClientCommandArgument(c,0,aux); -- cgit v1.2.1 From 580f65a50b6b2aa7fce0b415b71ff3219b2f9fa5 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 21 Jan 2013 12:06:54 +0100 Subject: Not every __sun has backtrace(). I don't know how to test for Open Solaris that has support for backtrace() so for now removing the #ifdef that breaks compilation under other Solaris flavors. --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h b/src/config.h index b5c8284a0..c1fcaf6d4 100644 --- a/src/config.h +++ b/src/config.h @@ -54,7 +54,7 @@ #endif /* Test for backtrace() */ -#if defined(__APPLE__) || defined(__linux__) || defined(__sun) +#if defined(__APPLE__) || defined(__linux__) #define HAVE_BACKTRACE 1 #endif -- cgit v1.2.1 From 1b0f244509a2530d4057b237e264cd20c1b04fa6 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 21 Jan 2013 12:34:22 +0100 Subject: Fixed a bug in memtest progress bar, that had no actual effects. This closes issue #859, thanks to @erbenmo. --- src/memtest.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/memtest.c b/src/memtest.c index 56162ff4f..a0b99f98b 100644 --- a/src/memtest.c +++ b/src/memtest.c @@ -78,10 +78,8 @@ void memtest_progress_end(void) { void memtest_progress_step(size_t curr, size_t size, char c) { size_t chars = ((unsigned long long)curr*progress_full)/size, j; - for (j = 0; j < chars-progress_printed; j++) { - printf("%c",c); - progress_printed++; - } + for (j = 0; j < chars-progress_printed; j++) printf("%c",c); + progress_printed = chars; fflush(stdout); } -- cgit v1.2.1 From 742e580f407cc6d922e2da54a50eb23dd017d5c4 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 21 Jan 2013 18:50:16 +0100 Subject: UNSUBSCRIBE and PUNSUBSCRIBE: always provide a reply. UNSUBSCRIBE and PUNSUBSCRIBE commands are designed to mass-unsubscribe the client respectively all the channels and patters if called without arguments. However when these functions are called without arguments, but there are no channels or patters we are subscribed to, the old behavior was to don't reply at all. This behavior is broken, as every command should always reply. Also it is possible that we are no longer subscribed to a channels but we are subscribed to patters or the other way around, and the client should be notified with the correct number of subscriptions. Also it is not pretty that sometimes we did not receive a reply at all in a redis-cli session from these commands, blocking redis-cli trying to read the reply. This fixes issue #714. --- src/pubsub.c | 16 ++++++++++++++++ tests/unit/pubsub.tcl | 12 +++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/pubsub.c b/src/pubsub.c index 973692948..3e58e3857 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -179,6 +179,14 @@ int pubsubUnsubscribeAllChannels(redisClient *c, int notify) { count += pubsubUnsubscribeChannel(c,channel,notify); } + /* We were subscribed to nothing? Still reply to the client. */ + if (notify && count == 0) { + addReply(c,shared.mbulkhdr[3]); + addReply(c,shared.unsubscribebulk); + addReply(c,shared.nullbulk); + addReplyLongLong(c,dictSize(c->pubsub_channels)+ + listLength(c->pubsub_patterns)); + } dictReleaseIterator(di); return count; } @@ -196,6 +204,14 @@ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify) { count += pubsubUnsubscribePattern(c,pattern,notify); } + if (notify && count == 0) { + /* We were subscribed to nothing? Still reply to the client. */ + addReply(c,shared.mbulkhdr[3]); + addReply(c,shared.punsubscribebulk); + addReply(c,shared.nullbulk); + addReplyLongLong(c,dictSize(c->pubsub_channels)+ + listLength(c->pubsub_patterns)); + } return count; } diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl index c8b547b4f..769151600 100644 --- a/tests/unit/pubsub.tcl +++ b/tests/unit/pubsub.tcl @@ -192,4 +192,14 @@ start_server {tags {"pubsub"}} { # clean up clients $rd1 close } -} \ No newline at end of file + + test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply." { + # Make sure we are not subscribed to any channel at all. + r punsubscribe + r unsubscribe + # Now check if the commands still reply correctly. + set reply1 [r punsubscribe] + set reply2 [r unsubscribe] + concat $reply1 $reply2 + } {punsubscribe {} 0 unsubscribe {} 0} +} -- cgit v1.2.1 From bfad381f57bdacb9b11b8d4e7741a4fcb7911133 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 21 Jan 2013 19:15:51 +0100 Subject: redis-cli --bigkeys output is now simpler to understand. --- src/redis-cli.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 318f1822a..c182ac17d 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1183,6 +1183,7 @@ static void findBigKeys(void) { unsigned long long samples = 0; redisReply *reply1, *reply2, *reply3 = NULL; char *sizecmd, *typename[] = {"string","list","set","hash","zset"}; + char *typeunit[] = {"bytes","items","members","fields","members"}; int type; printf("\n# Press ctrl+c when you have had enough of it... :)\n"); @@ -1234,9 +1235,10 @@ static void findBigKeys(void) { reply3 = redisCommand(context,"%s %s", sizecmd, reply1->str); if (reply3 && reply3->type == REDIS_REPLY_INTEGER) { if (biggest[type] < reply3->integer) { - printf("[%6s] %s | biggest so far with size %llu\n", + printf("Biggest %-6s found so far '%s' with %llu %s.\n", typename[type], reply1->str, - (unsigned long long) reply3->integer); + (unsigned long long) reply3->integer, + typeunit[type]); biggest[type] = reply3->integer; } } -- cgit v1.2.1 From c17a7f6fbc82dc6ab34a788f65adc16e84b5777c Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 23 Jan 2013 10:48:59 +0100 Subject: Lua struct library updated to version 0.2. There was a bug in the previous version of this library that caused a crash under the circumstances described in issue #901. The newer version of the library appears to be fixed (I tested it manually with valgrind and everything seems fine now). For more information about this library please visit this web site: http://www.inf.puc-rio.br/~roberto/struct/ --- deps/lua/src/lua_struct.c | 171 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 52 deletions(-) diff --git a/deps/lua/src/lua_struct.c b/deps/lua/src/lua_struct.c index 6807c8387..ec78bcbc0 100644 --- a/deps/lua/src/lua_struct.c +++ b/deps/lua/src/lua_struct.c @@ -1,18 +1,7 @@ - -#include -#include -#include -#include - - -#include "lua.h" -#include "lauxlib.h" - - /* ** {====================================================== ** Library for packing/unpacking structures. -** $Id: struct.c,v 1.2 2008/04/18 20:06:01 roberto Exp $ +** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $ ** See Copyright Notice at the end of this file ** ======================================================= */ @@ -25,6 +14,7 @@ ** b/B - signed/unsigned byte ** h/H - signed/unsigned short ** l/L - signed/unsigned long +** T - size_t ** i/In - signed/unsigned integer with size `n' (default is size of int) ** cn - sequence of `n' chars (from/to a string); when packing, n==0 means the whole string; when unpacking, n==0 means use the previous @@ -36,6 +26,38 @@ */ +#include +#include +#include +#include +#include + + +#include "lua.h" +#include "lauxlib.h" + + +#if (LUA_VERSION_NUM >= 502) + +#define luaL_register(L,n,f) luaL_newlib(L,f) + +#endif + + +/* basic integer type */ +#if !defined(STRUCT_INT) +#define STRUCT_INT long +#endif + +typedef STRUCT_INT Inttype; + +/* corresponding unsigned version */ +typedef unsigned STRUCT_INT Uinttype; + + +/* maximum size (in bytes) for integral types */ +#define MAXINTSIZE 32 + /* is 'x' a power of 2? */ #define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0) @@ -67,11 +89,11 @@ typedef struct Header { } Header; -static size_t getnum (const char **fmt, size_t df) { +static int getnum (const char **fmt, int df) { if (!isdigit(**fmt)) /* no number? */ return df; /* return default value */ else { - size_t a = 0; + int a = 0; do { a = a*10 + *((*fmt)++) - '0'; } while (isdigit(**fmt)); @@ -89,33 +111,40 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) { case 'B': case 'b': return sizeof(char); case 'H': case 'h': return sizeof(short); case 'L': case 'l': return sizeof(long); + case 'T': return sizeof(size_t); case 'f': return sizeof(float); case 'd': return sizeof(double); case 'x': return 1; case 'c': return getnum(fmt, 1); - case 's': case ' ': case '<': case '>': case '!': return 0; case 'i': case 'I': { int sz = getnum(fmt, sizeof(int)); - if (!isp2(sz)) - luaL_error(L, "integral size %d is not a power of 2", sz); + if (sz > MAXINTSIZE) + luaL_error(L, "integral size %d is larger than limit of %d", + sz, MAXINTSIZE); return sz; } - default: { - const char *msg = lua_pushfstring(L, "invalid format option [%c]", opt); - return luaL_argerror(L, 1, msg); - } + default: return 0; /* other cases do not need alignment */ } } +/* +** return number of bytes needed to align an element of size 'size' +** at current position 'len' +*/ static int gettoalign (size_t len, Header *h, int opt, size_t size) { if (size == 0 || opt == 'c') return 0; - if (size > (size_t)h->align) size = h->align; /* respect max. alignment */ - return (size - (len & (size - 1))) & (size - 1); + if (size > (size_t)h->align) + size = h->align; /* respect max. alignment */ + return (size - (len & (size - 1))) & (size - 1); } -static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) { +/* +** options to control endianess and alignment +*/ +static void controloptions (lua_State *L, int opt, const char **fmt, + Header *h) { switch (opt) { case ' ': return; /* ignore white spaces */ case '>': h->endian = BIG; return; @@ -127,7 +156,10 @@ static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) { h->align = a; return; } - default: assert(0); + default: { + const char *msg = lua_pushfstring(L, "invalid format option '%c'", opt); + luaL_argerror(L, 1, msg); + } } } @@ -135,21 +167,27 @@ static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) { static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian, int size) { lua_Number n = luaL_checknumber(L, arg); - unsigned long value; - if (n < (lua_Number)LONG_MAX) - value = (long)n; + Uinttype value; + char buff[MAXINTSIZE]; + if (n < 0) + value = (Uinttype)(Inttype)n; else - value = (unsigned long)n; + value = (Uinttype)n; if (endian == LITTLE) { int i; - for (i = 0; i < size; i++) - luaL_addchar(b, (value >> 8*i) & 0xff); + for (i = 0; i < size; i++) { + buff[i] = (value & 0xff); + value >>= 8; + } } else { int i; - for (i = size - 1; i >= 0; i--) - luaL_addchar(b, (value >> 8*i) & 0xff); + for (i = size - 1; i >= 0; i--) { + buff[i] = (value & 0xff); + value >>= 8; + } } + luaL_addlstring(b, buff, size); } @@ -179,15 +217,15 @@ static int b_pack (lua_State *L) { size_t size = optsize(L, opt, &fmt); int toalign = gettoalign(totalsize, &h, opt, size); totalsize += toalign; - while (toalign-- > 0) luaL_putchar(&b, '\0'); + while (toalign-- > 0) luaL_addchar(&b, '\0'); switch (opt) { case 'b': case 'B': case 'h': case 'H': - case 'l': case 'L': case 'i': case 'I': { /* integer types */ + case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ putinteger(L, &b, arg++, h.endian, size); break; } case 'x': { - luaL_putchar(&b, '\0'); + luaL_addchar(&b, '\0'); break; } case 'f': { @@ -209,12 +247,12 @@ static int b_pack (lua_State *L) { luaL_argcheck(L, l >= (size_t)size, arg, "string too short"); luaL_addlstring(&b, s, size); if (opt == 's') { - luaL_putchar(&b, '\0'); /* add zero at the end */ + luaL_addchar(&b, '\0'); /* add zero at the end */ size++; } break; } - default: commoncases(L, opt, &fmt, &h); + default: controloptions(L, opt, &fmt, &h); } totalsize += size; } @@ -225,24 +263,27 @@ static int b_pack (lua_State *L) { static lua_Number getinteger (const char *buff, int endian, int issigned, int size) { - unsigned long l = 0; + Uinttype l = 0; + int i; if (endian == BIG) { - int i; - for (i = 0; i < size; i++) - l |= (unsigned long)(unsigned char)buff[size - i - 1] << (i*8); + for (i = 0; i < size; i++) { + l <<= 8; + l |= (Uinttype)(unsigned char)buff[i]; + } } else { - int i; - for (i = 0; i < size; i++) - l |= (unsigned long)(unsigned char)buff[i] << (i*8); + for (i = size - 1; i >= 0; i--) { + l <<= 8; + l |= (Uinttype)(unsigned char)buff[i]; + } } if (!issigned) return (lua_Number)l; else { /* signed format */ - unsigned long mask = ~(0UL) << (size*8 - 1); + Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1); if (l & mask) /* negative value? */ l |= mask; /* signal extension */ - return (lua_Number)(long)l; + return (lua_Number)(Inttype)l; } } @@ -260,9 +301,10 @@ static int b_unpack (lua_State *L) { size_t size = optsize(L, opt, &fmt); pos += gettoalign(pos, &h, opt, size); luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); + luaL_checkstack(L, 1, "too many results"); switch (opt) { case 'b': case 'B': case 'h': case 'H': - case 'l': case 'L': case 'i': case 'I': { /* integer types */ + case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ int issigned = islower(opt); lua_Number res = getinteger(data+pos, h.endian, issigned, size); lua_pushnumber(L, res); @@ -304,7 +346,7 @@ static int b_unpack (lua_State *L) { lua_pushlstring(L, data+pos, size - 1); break; } - default: commoncases(L, opt, &fmt, &h); + default: controloptions(L, opt, &fmt, &h); } pos += size; } @@ -312,26 +354,50 @@ static int b_unpack (lua_State *L) { return lua_gettop(L) - 2; } + +static int b_size (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); + size_t pos = 0; + defaultoptions(&h); + while (*fmt) { + int opt = *fmt++; + size_t size = optsize(L, opt, &fmt); + pos += gettoalign(pos, &h, opt, size); + if (opt == 's') + luaL_argerror(L, 1, "option 's' has no fixed size"); + else if (opt == 'c' && size == 0) + luaL_argerror(L, 1, "option 'c0' has no fixed size"); + if (!isalnum(opt)) + controloptions(L, opt, &fmt, &h); + pos += size; + } + lua_pushinteger(L, pos); + return 1; +} + /* }====================================================== */ -static const struct luaL_reg thislib[] = { +static const struct luaL_Reg thislib[] = { {"pack", b_pack}, {"unpack", b_unpack}, + {"size", b_size}, {NULL, NULL} }; +LUALIB_API int luaopen_struct (lua_State *L); + LUALIB_API int luaopen_struct (lua_State *L) { luaL_register(L, "struct", thislib); return 1; } - /****************************************************************************** -* Copyright (C) 2010 Lua.org, PUC-Rio. All rights reserved. +* Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -352,3 +418,4 @@ LUALIB_API int luaopen_struct (lua_State *L) { * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ + -- cgit v1.2.1