]> git.saurik.com Git - redis.git/commitdiff
Merge remote branch 'pietern/intset-split'
authorantirez <antirez@gmail.com>
Thu, 26 Aug 2010 10:04:24 +0000 (12:04 +0200)
committerantirez <antirez@gmail.com>
Thu, 26 Aug 2010 10:04:24 +0000 (12:04 +0200)
1  2 
src/object.c
src/redis.c
src/redis.h

diff --combined src/object.c
index 429ac0ecc6cd7eea9cabd7b987701dd9153278a0,b16123eba641ba3307fbaacb9320cf8a80f3026b..dae7f97b21924fdda844e4e07a1b276cba0d7350
@@@ -74,7 -74,16 +74,16 @@@ robj *createZiplistObject(void) 
  
  robj *createSetObject(void) {
      dict *d = dictCreate(&setDictType,NULL);
-     return createObject(REDIS_SET,d);
+     robj *o = createObject(REDIS_SET,d);
+     o->encoding = REDIS_ENCODING_HT;
+     return o;
+ }
+ robj *createIntsetObject(void) {
+     intset *is = intsetNew();
+     robj *o = createObject(REDIS_SET,is);
+     o->encoding = REDIS_ENCODING_INTSET;
+     return o;
  }
  
  robj *createHashObject(void) {
@@@ -115,7 -124,16 +124,16 @@@ void freeListObject(robj *o) 
  }
  
  void freeSetObject(robj *o) {
-     dictRelease((dict*) o->ptr);
+     switch (o->encoding) {
+     case REDIS_ENCODING_HT:
+         dictRelease((dict*) o->ptr);
+         break;
+     case REDIS_ENCODING_INTSET:
+         zfree(o->ptr);
+         break;
+     default:
+         redisPanic("Unknown set encoding type");
+     }
  }
  
  void freeZsetObject(robj *o) {
@@@ -357,9 -375,8 +375,10 @@@ int getLongLongFromObject(robj *o, lon
          redisAssert(o->type == REDIS_STRING);
          if (o->encoding == REDIS_ENCODING_RAW) {
              value = strtoll(o->ptr, &eptr, 10);
+             if (errno == ERANGE) return REDIS_ERR;
              if (eptr[0] != '\0') return REDIS_ERR;
 +            if (errno == ERANGE && (value == LLONG_MIN || value == LLONG_MAX))
 +                return REDIS_ERR;
          } else if (o->encoding == REDIS_ENCODING_INT) {
              value = (long)o->ptr;
          } else {
          }
      }
  
-     *target = value;
+     if (target) *target = value;
      return REDIS_OK;
  }
  
@@@ -377,7 -394,7 +396,7 @@@ int getLongLongFromObjectOrReply(redisC
          if (msg != NULL) {
              addReplySds(c, sdscatprintf(sdsempty(), "-ERR %s\r\n", msg));
          } else {
 -            addReplySds(c, sdsnew("-ERR value is not an integer\r\n"));
 +            addReplySds(c, sdsnew("-ERR value is not an integer or out of range\r\n"));
          }
          return REDIS_ERR;
      }
@@@ -411,6 -428,7 +430,7 @@@ char *strEncoding(int encoding) 
      case REDIS_ENCODING_ZIPMAP: return "zipmap";
      case REDIS_ENCODING_LINKEDLIST: return "linkedlist";
      case REDIS_ENCODING_ZIPLIST: return "ziplist";
+     case REDIS_ENCODING_INTSET: return "intset";
      default: return "unknown";
      }
  }
diff --combined src/redis.c
index 0ee7a20ba6bbf9ec1e563b5dc729aaf2f6291424,7b2ed42e670c4733b55e0698582186a3c044bf3a..9fbd52f2e19ca1b557fc74912449df67a1ffcf7a
@@@ -743,6 -743,7 +743,7 @@@ void initServerConfig() 
      server.hash_max_zipmap_value = REDIS_HASH_MAX_ZIPMAP_VALUE;
      server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;
      server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;
+     server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;
      server.shutdown_asap = 0;
  
      resetServerSaveParams();
@@@ -912,14 -913,9 +913,14 @@@ int processCommand(redisClient *c) 
                  resetClient(c);
                  return 1;
              } else {
 -                int bulklen = atoi(((char*)c->argv[0]->ptr)+1);
 +                char *eptr;
 +                long bulklen = strtol(((char*)c->argv[0]->ptr)+1,&eptr,10);
 +                int perr = eptr[0] != '\0';
 +
                  decrRefCount(c->argv[0]);
 -                if (bulklen < 0 || bulklen > 1024*1024*1024) {
 +                if (perr || bulklen == LONG_MIN || bulklen == LONG_MAX ||
 +                    bulklen < 0 || bulklen > 1024*1024*1024)
 +                {
                      c->argc--;
                      addReplySds(c,sdsnew("-ERR invalid bulk write count\r\n"));
                      resetClient(c);
          return 1;
      } else if (cmd->flags & REDIS_CMD_BULK && c->bulklen == -1) {
          /* This is a bulk command, we have to read the last argument yet. */
 -        int bulklen = atoi(c->argv[c->argc-1]->ptr);
 +        char *eptr;
 +        long bulklen = strtol(c->argv[c->argc-1]->ptr,&eptr,10);
 +        int perr = eptr[0] != '\0';
  
          decrRefCount(c->argv[c->argc-1]);
 -        if (bulklen < 0 || bulklen > 1024*1024*1024) {
 +        if (perr || bulklen == LONG_MAX || bulklen == LONG_MIN ||
 +            bulklen < 0 || bulklen > 1024*1024*1024)
 +        {
              c->argc--;
              addReplySds(c,sdsnew("-ERR invalid bulk write count\r\n"));
              resetClient(c);
@@@ -1085,7 -1077,11 +1086,7 @@@ int prepareForShutdown() 
          if (server.vm_enabled) unlink(server.vm_swap_file);
      } else {
          /* Snapshotting. Perform a SYNC SAVE and exit */
 -        if (rdbSave(server.dbfilename) == REDIS_OK) {
 -            if (server.daemonize)
 -                unlink(server.pidfile);
 -            redisLog(REDIS_WARNING,"%zu bytes used at exit",zmalloc_used_memory());
 -        } else {
 +        if (rdbSave(server.dbfilename) != REDIS_OK) {
              /* Ooops.. error saving! The best we can do is to continue
               * operating. Note that if there was a background saving process,
               * in the next cron() Redis will be notified that the background
              return REDIS_ERR;
          }
      }
 +    if (server.daemonize) unlink(server.pidfile);
      redisLog(REDIS_WARNING,"Server exit now, bye bye...");
      return REDIS_OK;
  }
@@@ -1368,17 -1363,9 +1369,17 @@@ void linuxOvercommitMemoryWarning(void
  }
  #endif /* __linux__ */
  
 +void createPidFile(void) {
 +    /* Try to write the pid file in a best-effort way. */
 +    FILE *fp = fopen(server.pidfile,"w");
 +    if (fp) {
 +        fprintf(fp,"%d\n",getpid());
 +        fclose(fp);
 +    }
 +}
 +
  void daemonize(void) {
      int fd;
 -    FILE *fp;
  
      if (fork() != 0) exit(0); /* parent exits */
      setsid(); /* create a new session */
          dup2(fd, STDERR_FILENO);
          if (fd > STDERR_FILENO) close(fd);
      }
 -    /* Try to write the pid file */
 -    fp = fopen(server.pidfile,"w");
 -    if (fp) {
 -        fprintf(fp,"%d\n",getpid());
 -        fclose(fp);
 -    }
  }
  
  void version() {
@@@ -1424,7 -1417,6 +1425,7 @@@ int main(int argc, char **argv) 
      }
      if (server.daemonize) daemonize();
      initServer();
 +    if (server.daemonize) createPidFile();
      redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
  #ifdef __linux__
      linuxOvercommitMemoryWarning();
@@@ -1501,7 -1493,6 +1502,7 @@@ void segvHandler(int sig, siginfo_t *in
          redisLog(REDIS_WARNING,"%s", messages[i]);
  
      /* free(messages); Don't call free() with possibly corrupted memory. */
 +    if (server.daemonize) unlink(server.pidfile);
      _exit(0);
  }
  
diff --combined src/redis.h
index c35fe53a2caffe39479ba17db2edd28a20fea0b8,0b78320c117db7ad0d304afcfb075ff26b650a86..6156a6ca74187dbb1ee9460f4cf941594e0c48f9
@@@ -26,6 -26,7 +26,7 @@@
  #include "anet.h"   /* Networking the easy way */
  #include "zipmap.h" /* Compact string -> string data structure */
  #include "ziplist.h" /* Compact list data structure */
+ #include "intset.h" /* Compact integer set structure */
  #include "version.h"
  
  /* Error codes */
@@@ -82,6 -83,7 +83,7 @@@
  #define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
  #define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
  #define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
+ #define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
  
  /* Object types only used for dumping to disk */
  #define REDIS_EXPIRETIME 253
  #define REDIS_HASH_MAX_ZIPMAP_VALUE 512
  #define REDIS_LIST_MAX_ZIPLIST_ENTRIES 1024
  #define REDIS_LIST_MAX_ZIPLIST_VALUE 32
+ #define REDIS_SET_MAX_INTSET_ENTRIES 4096
  
  /* Sets operations codes */
  #define REDIS_OP_UNION 0
@@@ -283,7 -286,7 +286,7 @@@ typedef struct redisClient 
      sds querybuf;
      robj **argv, **mbargv;
      int argc, mbargc;
 -    int bulklen;            /* bulk read len. -1 if not in bulk read mode */
 +    long bulklen;            /* bulk read len. -1 if not in bulk read mode */
      int multibulk;          /* multi bulk command format active */
      list *reply;
      int sentlen;
@@@ -398,6 -401,7 +401,7 @@@ struct redisServer 
      size_t hash_max_zipmap_value;
      size_t list_max_ziplist_entries;
      size_t list_max_ziplist_value;
+     size_t set_max_intset_entries;
      /* Virtual memory state */
      FILE *vm_fp;
      int vm_fd;
@@@ -535,6 -539,14 +539,14 @@@ typedef struct 
      listNode *ln;       /* Entry in linked list */
  } listTypeEntry;
  
+ /* Structure to hold set iteration abstraction. */
+ typedef struct {
+     robj *subject;
+     int encoding;
+     int ii; /* intset iterator */
+     dictIterator *di;
+ } setTypeIterator;
  /* Structure to hold hash iteration abstration. 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
@@@ -633,6 -645,7 +645,7 @@@ robj *createStringObjectFromLongLong(lo
  robj *createListObject(void);
  robj *createZiplistObject(void);
  robj *createSetObject(void);
+ robj *createIntsetObject(void);
  robj *createHashObject(void);
  robj *createZsetObject(void);
  int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg);
@@@ -716,6 -729,18 +729,18 @@@ int dontWaitForSwappedKey(redisClient *
  void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key);
  vmpointer *vmSwapObjectBlocking(robj *val);
  
+ /* Set data type */
+ robj *setTypeCreate(robj *value);
+ int setTypeAdd(robj *subject, robj *value);
+ int setTypeRemove(robj *subject, robj *value);
+ int setTypeIsMember(robj *subject, robj *value);
+ setTypeIterator *setTypeInitIterator(robj *subject);
+ void setTypeReleaseIterator(setTypeIterator *si);
+ robj *setTypeNext(setTypeIterator *si);
+ robj *setTypeRandomElement(robj *subject);
+ unsigned long setTypeSize(robj *subject);
+ void setTypeConvert(robj *subject, int enc);
  /* Hash data type */
  void convertToRealHash(robj *o);
  void hashTypeTryConversion(robj *subject, robj **argv, int start, int end);