]> git.saurik.com Git - redis.git/commitdiff
Merge branch 'hincrby' of git://github.com/pietern/redis
authorantirez <antirez@gmail.com>
Fri, 26 Mar 2010 16:08:47 +0000 (17:08 +0100)
committerantirez <antirez@gmail.com>
Fri, 26 Mar 2010 16:08:47 +0000 (17:08 +0100)
1  2 
redis.c

diff --combined redis.c
index 03f90a02f36c3588868597bb4c70f44ba52e6dfd,c29cc002024935e4db2987df2f5488ee1d27ab01..f2f54316c27389456d043378b91a0f0607bbac2f
+++ b/redis.c
@@@ -86,7 -86,7 +86,7 @@@
  #define REDIS_MAXIDLETIME       (60*5)  /* default client timeout */
  #define REDIS_IOBUF_LEN         1024
  #define REDIS_LOADBUF_LEN       1024
 -#define REDIS_STATIC_ARGS       4
 +#define REDIS_STATIC_ARGS       8
  #define REDIS_DEFAULT_DBNUM     16
  #define REDIS_CONFIGLINE_MAX    1024
  #define REDIS_OBJFREELIST_MAX   1000000 /* Max number of objects to cache */
@@@ -521,7 -521,7 +521,7 @@@ typedef struct iojob 
      robj *val;  /* the value to swap for REDIS_IOREQ_*_SWAP, otherwise this
                   * field is populated by the I/O thread for REDIS_IOREQ_LOAD. */
      off_t page; /* Swap page where to read/write the object */
 -    off_t pages; /* Swap pages needed to safe object. PREPARE_SWAP return val */
 +    off_t pages; /* Swap pages needed to save object. PREPARE_SWAP return val */
      int canceled; /* True if this command was canceled by blocking side of VM */
      pthread_t thread; /* ID of the thread processing this entry */
  } iojob;
@@@ -541,7 -541,7 +541,7 @@@ static void incrRefCount(robj *o)
  static int rdbSaveBackground(char *filename);
  static robj *createStringObject(char *ptr, size_t len);
  static robj *dupStringObject(robj *o);
 -static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int dictid, robj **argv, int argc);
 +static void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc);
  static void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc);
  static int syncWithMaster(void);
  static robj *tryObjectSharing(robj *o);
@@@ -697,6 -697,7 +697,7 @@@ static void hvalsCommand(redisClient *c
  static void hgetallCommand(redisClient *c);
  static void hexistsCommand(redisClient *c);
  static void configCommand(redisClient *c);
+ static void hincrbyCommand(redisClient *c);
  
  /*================================= Globals ================================= */
  
@@@ -756,6 -757,7 +757,7 @@@ static struct redisCommand cmdTable[] 
      {"zrank",zrankCommand,3,REDIS_CMD_BULK,NULL,1,1,1},
      {"zrevrank",zrevrankCommand,3,REDIS_CMD_BULK,NULL,1,1,1},
      {"hset",hsetCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
+     {"hincrby",hincrbyCommand,4,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
      {"hget",hgetCommand,3,REDIS_CMD_BULK,NULL,1,1,1},
      {"hdel",hdelCommand,3,REDIS_CMD_BULK,NULL,1,1,1},
      {"hlen",hlenCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
@@@ -2075,9 -2077,9 +2077,9 @@@ static void call(redisClient *c, struc
      if (server.appendonly && server.dirty-dirty)
          feedAppendOnlyFile(cmd,c->db->id,c->argv,c->argc);
      if (server.dirty-dirty && listLength(server.slaves))
 -        replicationFeedSlaves(server.slaves,cmd,c->db->id,c->argv,c->argc);
 +        replicationFeedSlaves(server.slaves,c->db->id,c->argv,c->argc);
      if (listLength(server.monitors))
 -        replicationFeedSlaves(server.monitors,cmd,c->db->id,c->argv,c->argc);
 +        replicationFeedSlaves(server.monitors,c->db->id,c->argv,c->argc);
      server.stat_numcommands++;
  }
  
@@@ -2256,36 -2258,34 +2258,36 @@@ static int processCommand(redisClient *
      return 1;
  }
  
 -static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int dictid, robj **argv, int argc) {
 +static void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) {
      listNode *ln;
      listIter li;
      int outc = 0, j;
      robj **outv;
 -    /* (args*2)+1 is enough room for args, spaces, newlines */
 -    robj *static_outv[REDIS_STATIC_ARGS*2+1];
 +    /* We need 1+(ARGS*3) objects since commands are using the new protocol
 +     * and we one 1 object for the first "*<count>\r\n" multibulk count, then
 +     * for every additional object we have "$<count>\r\n" + object + "\r\n". */
 +    robj *static_outv[REDIS_STATIC_ARGS*3+1];
 +    robj *lenobj;
  
      if (argc <= REDIS_STATIC_ARGS) {
          outv = static_outv;
      } else {
 -        outv = zmalloc(sizeof(robj*)*(argc*2+1));
 +        outv = zmalloc(sizeof(robj*)*(argc*3+1));
      }
 -    
 +
 +    lenobj = createObject(REDIS_STRING,
 +            sdscatprintf(sdsempty(), "*%d\r\n", argc));
 +    lenobj->refcount = 0;
 +    outv[outc++] = lenobj;
      for (j = 0; j < argc; j++) {
 -        if (j != 0) outv[outc++] = shared.space;
 -        if ((cmd->flags & REDIS_CMD_BULK) && j == argc-1) {
 -            robj *lenobj;
 -
 -            lenobj = createObject(REDIS_STRING,
 -                sdscatprintf(sdsempty(),"%lu\r\n",
 -                    (unsigned long) stringObjectLen(argv[j])));
 -            lenobj->refcount = 0;
 -            outv[outc++] = lenobj;
 -        }
 +        lenobj = createObject(REDIS_STRING,
 +            sdscatprintf(sdsempty(),"$%lu\r\n",
 +                (unsigned long) stringObjectLen(argv[j])));
 +        lenobj->refcount = 0;
 +        outv[outc++] = lenobj;
          outv[outc++] = argv[j];
 +        outv[outc++] = shared.crlf;
      }
 -    outv[outc++] = shared.crlf;
  
      /* Increment all the refcounts at start and decrement at end in order to
       * be sure to free objects if there is no slave in a replication state
@@@ -2437,7 -2437,8 +2439,7 @@@ static void readQueryFromClient(aeEvent
      } else {
          return;
      }
 -    if (!(c->flags & REDIS_BLOCKED))
 -        processInputBuffer(c);
 +    processInputBuffer(c);
  }
  
  static int selectDb(redisClient *c, int id) {
@@@ -5955,6 -5956,80 +5957,80 @@@ static void hsetCommand(redisClient *c
      addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",update == 0));
  }
  
+ static void hincrbyCommand(redisClient *c) {
+     int update = 0;
+     long long value = 0, incr = 0;
+     robj *o = lookupKeyWrite(c->db,c->argv[1]);
+     if (o == NULL) {
+         o = createHashObject();
+         dictAdd(c->db->dict,c->argv[1],o);
+         incrRefCount(c->argv[1]);
+     } else {
+         if (o->type != REDIS_HASH) {
+             addReply(c,shared.wrongtypeerr);
+             return;
+         }
+     }
+     robj *o_incr = getDecodedObject(c->argv[3]);
+     incr = strtoll(o_incr->ptr, NULL, 10);
+     decrRefCount(o_incr);
+     if (o->encoding == REDIS_ENCODING_ZIPMAP) {
+         unsigned char *zm = o->ptr;
+         unsigned char *zval;
+         unsigned int zvlen;
+         /* Find value if already present in hash */
+         if (zipmapGet(zm,c->argv[2]->ptr,sdslen(c->argv[2]->ptr),
+             &zval,&zvlen)) {
+             /* strtoll needs the char* to have a trailing \0, but
+              * the zipmap doesn't include them. */
+             sds szval = sdsnewlen(zval, zvlen);
+             value = strtoll(szval,NULL,10);
+             sdsfree(szval);
+         }
+         value += incr;
+         sds svalue = sdscatprintf(sdsempty(),"%lld",value);
+         zm = zipmapSet(zm,c->argv[2]->ptr,sdslen(c->argv[2]->ptr),
+             (unsigned char*)svalue,sdslen(svalue),&update);
+         sdsfree(svalue);
+         o->ptr = zm;
+         /* Check if the zipmap needs to be converted
+          * if this was not an update. */
+         if (!update && zipmapLen(zm) > server.hash_max_zipmap_entries)
+             convertToRealHash(o);
+     } else {
+         robj *hval;
+         dictEntry *de;
+         /* Find value if already present in hash */
+         de = dictFind(o->ptr,c->argv[2]);
+         if (de != NULL) {
+             hval = dictGetEntryVal(de);
+             if (hval->encoding == REDIS_ENCODING_RAW)
+                 value = strtoll(hval->ptr,NULL,10);
+             else if (hval->encoding == REDIS_ENCODING_INT)
+                 value = (long)hval->ptr;
+             else
+                 redisAssert(1 != 1);
+         }
+         value += incr;
+         hval = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%lld",value));
+         tryObjectEncoding(hval);
+         if (dictReplace(o->ptr,c->argv[2],hval)) {
+             incrRefCount(c->argv[2]);
+         }
+     }
+     server.dirty++;
+     addReplyLong(c, value);
+ }
  static void hgetCommand(redisClient *c) {
      robj *o;