]> git.saurik.com Git - redis.git/commitdiff
Merge pull request #199 from jerem/patch-1
authorSalvatore Sanfilippo <antirez@gmail.com>
Tue, 22 Nov 2011 10:43:28 +0000 (02:43 -0800)
committerSalvatore Sanfilippo <antirez@gmail.com>
Tue, 22 Nov 2011 10:43:28 +0000 (02:43 -0800)
Fixed a typo in comments.

.gitignore
src/ae.c
src/ae.h
src/networking.c
src/redis.c
src/redis.h
src/sds.c
src/sds.h

index 1f480bd4d1271dd7cd7174ba1dfc8573ed312770..5f262c4617928cbc4adf7e4d01cc06ad7fa3ca8d 100644 (file)
@@ -23,3 +23,4 @@ deps/lua/src/lua
 deps/lua/src/luac
 deps/lua/src/liblua.a
 .make-*
+.prerequisites
index c7918ee1d6c52732856e3335197c0dff675f9474..0580289002dfa72db5d1d267f13f27f0f02438d9 100644 (file)
--- a/src/ae.c
+++ b/src/ae.c
@@ -118,6 +118,13 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
     aeApiDelEvent(eventLoop, fd, mask);
 }
 
+int aeGetFileEvents(aeEventLoop *eventLoop, int fd) {
+    if (fd >= AE_SETSIZE) return 0;
+    aeFileEvent *fe = &eventLoop->events[fd];
+
+    return fe->mask;
+}
+
 static void aeGetTime(long *seconds, long *milliseconds)
 {
     struct timeval tv;
index a9db18ed93356f759ceee4ecc60c5e68c655db60..9e23a6fdeea0352d996dcd0a183520c272071641 100644 (file)
--- a/src/ae.h
+++ b/src/ae.h
@@ -104,6 +104,7 @@ void aeStop(aeEventLoop *eventLoop);
 int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
         aeFileProc *proc, void *clientData);
 void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
+int aeGetFileEvents(aeEventLoop *eventLoop, int fd);
 long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
         aeTimeProc *proc, void *clientData,
         aeEventFinalizerProc *finalizerProc);
index edd7891d379dfe99328c8ad5dc74992de9ac38fc..537ebaba65a35286d6f09c4d9e515a1bf3dd8198 100644 (file)
@@ -903,6 +903,13 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
     } else {
         return;
     }
+    if (sdslen(c->querybuf) > server.client_max_querybuf_len) {
+        sds ci = getClientInfoString(c);
+        redisLog(REDIS_WARNING,"Closing client that reached max query buffer length: %s", ci);
+        sdsfree(ci);
+        freeClient(c);
+        return;
+    }
     processInputBuffer(c);
 }
 
@@ -924,6 +931,53 @@ void getClientsMaxBuffers(unsigned long *longest_output_list,
     *biggest_input_buffer = bib;
 }
 
+/* Turn a Redis client into an sds string representing its state. */
+sds getClientInfoString(redisClient *client) {
+    char ip[32], flags[16], events[3], *p;
+    int port;
+    time_t now = time(NULL);
+    int emask;
+
+    if (anetPeerToString(client->fd,ip,&port) == -1) {
+        ip[0] = '?';
+        ip[1] = '\0';
+        port = 0;
+    }
+    p = flags;
+    if (client->flags & REDIS_SLAVE) {
+        if (client->flags & REDIS_MONITOR)
+            *p++ = 'O';
+        else
+            *p++ = 'S';
+    }
+    if (client->flags & REDIS_MASTER) *p++ = 'M';
+    if (client->flags & REDIS_MULTI) *p++ = 'x';
+    if (client->flags & REDIS_BLOCKED) *p++ = 'b';
+    if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd';
+    if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c';
+    if (client->flags & REDIS_UNBLOCKED) *p++ = 'u';
+    if (p == flags) *p++ = 'N';
+    *p++ = '\0';
+
+    emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd);
+    p = events;
+    if (emask & AE_READABLE) *p++ = 'r';
+    if (emask & AE_WRITABLE) *p++ = 'w';
+    *p = '\0';
+    return sdscatprintf(sdsempty(),
+        "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d qbuf=%lu obl=%lu oll=%lu events=%s",
+        ip,port,client->fd,
+        (long)(now - client->lastinteraction),
+        flags,
+        client->db->id,
+        (int) dictSize(client->pubsub_channels),
+        (int) listLength(client->pubsub_patterns),
+        (unsigned long) sdslen(client->querybuf),
+        (unsigned long) client->bufpos,
+        (unsigned long) listLength(client->reply),
+        events);
+}
+
 void clientCommand(redisClient *c) {
     listNode *ln;
     listIter li;
@@ -931,38 +985,12 @@ void clientCommand(redisClient *c) {
 
     if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) {
         sds o = sdsempty();
-        time_t now = time(NULL);
 
         listRewind(server.clients,&li);
         while ((ln = listNext(&li)) != NULL) {
-            char ip[32], flags[16], *p;
-            int port;
-
             client = listNodeValue(ln);
-            if (anetPeerToString(client->fd,ip,&port) == -1) continue;
-            p = flags;
-            if (client->flags & REDIS_SLAVE) {
-                if (client->flags & REDIS_MONITOR)
-                    *p++ = 'O';
-                else
-                    *p++ = 'S';
-            }
-            if (client->flags & REDIS_MASTER) *p++ = 'M';
-            if (p == flags) *p++ = 'N';
-            if (client->flags & REDIS_MULTI) *p++ = 'x';
-            if (client->flags & REDIS_BLOCKED) *p++ = 'b';
-            if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd';
-            if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c';
-            if (client->flags & REDIS_UNBLOCKED) *p++ = 'u';
-            *p++ = '\0';
-            o = sdscatprintf(o,
-                "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d\n",
-                ip,port,client->fd,
-                (long)(now - client->lastinteraction),
-                flags,
-                client->db->id,
-                (int) dictSize(client->pubsub_channels),
-                (int) listLength(client->pubsub_patterns));
+            o = sdscatsds(o,getClientInfoString(client));
+            o = sdscatlen(o,"\n",1);
         }
         addReplyBulkCBuffer(c,o,sdslen(o));
         sdsfree(o);
index 91e1e10c834fb97ad7cd6e80f18880a96289ac28..7e324aa15151ef964b55d336f4062691045e24ec 100644 (file)
@@ -70,9 +70,31 @@ double R_Zero, R_PosInf, R_NegInf, R_Nan;
 struct redisServer server; /* server global state */
 struct redisCommand *commandTable;
 
-/* Our command table. Command flags are expressed using strings where every
- * character represents a flag. Later the populateCommandTable() function will
- * take care of populating the real 'flags' field using this characters.
+/* Our command table.
+ *
+ * Every entry is composed of the following fields:
+ *
+ * name: a string representing the command name.
+ * function: pointer to the C function implementing the command.
+ * arity: number of arguments, it is possible to use -N to say >= N
+ * sflags: command flags as string. See below for a table of flags.
+ * flags: flags as bitmask. Computed by Redis using the 'sflags' field.
+ * get_keys_proc: an optional function to get key arguments from a command.
+ *                This is only used when the following three fields are not
+ *                enough to specify what arguments are keys.
+ * first_key_index: first argument that is a key
+ * last_key_index: last argument that is a key
+ * key_step: step to get all the keys from first to last argument. For instance
+ *           in MSET the step is two since arguments are key,val,key,val,...
+ * microseconds: microseconds of total execution time for this command.
+ * calls: total number of calls of this command.
+ *
+ * The flags, microseconds and calls fields are computed by Redis and should
+ * always be set to zero.
+ *
+ * Command flags are expressed using strings where every character represents
+ * a flag. Later the populateCommandTable() function will take care of
+ * populating the real 'flags' field using this characters.
  *
  * This is the meaning of the flags:
  *
@@ -83,15 +105,15 @@ struct redisCommand *commandTable;
  * p: Pub/Sub related command.
  * f: force replication of this command, regarless of server.dirty.
  * s: command not allowed in scripts.
- * r: random command. Command is not deterministic, that is, the same command
+ * R: random command. Command is not deterministic, that is, the same command
  *    with the same arguments, with the same key space, may have different
  *    results. For instance SPOP and RANDOMKEY are two random commands. */
 struct redisCommand redisCommandTable[] = {
     {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
     {"set",setCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
     {"setnx",setnxCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
-    {"setex",setexCommand,4,"wm",0,noPreloadGetKeys,2,2,1,0,0},
-    {"psetex",psetexCommand,4,"wm",0,noPreloadGetKeys,2,2,1,0,0},
+    {"setex",setexCommand,4,"wm",0,noPreloadGetKeys,1,1,1,0,0},
+    {"psetex",psetexCommand,4,"wm",0,noPreloadGetKeys,1,1,1,0,0},
     {"append",appendCommand,3,"wm",0,NULL,1,1,1,0,0},
     {"strlen",strlenCommand,2,"r",0,NULL,1,1,1,0,0},
     {"del",delCommand,-2,"w",0,noPreloadGetKeys,1,-1,1,0,0},
@@ -843,6 +865,7 @@ void initServerConfig() {
     server.dbnum = REDIS_DEFAULT_DBNUM;
     server.verbosity = REDIS_VERBOSE;
     server.maxidletime = REDIS_MAXIDLETIME;
+    server.client_max_querybuf_len = REDIS_MAX_QUERYBUF_LEN;
     server.saveparams = NULL;
     server.loading = 0;
     server.logfile = NULL; /* NULL = log on standard output */
index d532e385913375e8edc497bcc73aec7a1e904fe0..40d0d39ab8239c748ecad8f8cb5223bd4af9266f 100644 (file)
@@ -40,6 +40,7 @@
 /* Static server configuration */
 #define REDIS_SERVERPORT        6379    /* TCP port */
 #define REDIS_MAXIDLETIME       0       /* default client timeout: infinite */
+#define REDIS_MAX_QUERYBUF_LEN  (1024*1024*1024) /* 1GB max query buffer. */
 #define REDIS_IOBUF_LEN         (1024*16)
 #define REDIS_LOADBUF_LEN       1024
 #define REDIS_DEFAULT_DBNUM     16
@@ -533,6 +534,7 @@ struct redisServer {
     /* Configuration */
     int verbosity;
     int maxidletime;
+    size_t client_max_querybuf_len;
     int dbnum;
     int daemonize;
     int appendonly;
@@ -765,6 +767,7 @@ void addReplyMultiBulkLen(redisClient *c, long length);
 void *dupClientReplyValue(void *o);
 void getClientsMaxBuffers(unsigned long *longest_output_list,
                           unsigned long *biggest_input_buffer);
+sds getClientInfoString(redisClient *client);
 void rewriteClientCommandVector(redisClient *c, int argc, ...);
 void rewriteClientCommandArgument(redisClient *c, int i, robj *newval);
 
index c3a0ccb978ae92b56a69a5c9d9964ba69784fc0a..b6c2aaf3ef70ae49d5b154dd64c8114167fc2416 100644 (file)
--- a/src/sds.c
+++ b/src/sds.c
@@ -196,6 +196,10 @@ sds sdscat(sds s, char *t) {
     return sdscatlen(s, t, strlen(t));
 }
 
+sds sdscatsds(sds s, sds t) {
+    return sdscatlen(s, t, sdslen(t));
+}
+
 sds sdscpylen(sds s, char *t, size_t len) {
     struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
     size_t totlen = sh->free+sh->len;
index eff1b03e800bafa1232e25e3b585c6c75070ff26..ee336d1deee9ea9124408f24564f38c4b3e5fe0b 100644 (file)
--- a/src/sds.h
+++ b/src/sds.h
@@ -62,6 +62,7 @@ size_t sdsavail(sds s);
 sds sdsgrowzero(sds s, size_t len);
 sds sdscatlen(sds s, void *t, size_t len);
 sds sdscat(sds s, char *t);
+sds sdscatsds(sds s, sds t);
 sds sdscpylen(sds s, char *t, size_t len);
 sds sdscpy(sds s, char *t);