From: antirez Date: Thu, 26 Aug 2010 10:04:24 +0000 (+0200) Subject: Merge remote branch 'pietern/intset-split' X-Git-Url: https://git.saurik.com/redis.git/commitdiff_plain/acc75bfd4f1607625876d74d6447efaaf505db59?hp=-c Merge remote branch 'pietern/intset-split' --- acc75bfd4f1607625876d74d6447efaaf505db59 diff --combined src/object.c index 429ac0ec,b16123eb..dae7f97b --- a/src/object.c +++ b/src/object.c @@@ -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 { @@@ -367,7 -384,7 +386,7 @@@ } } - *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 0ee7a20b,7b2ed42e..9fbd52f2 --- a/src/redis.c +++ b/src/redis.c @@@ -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); @@@ -989,14 -985,10 +990,14 @@@ 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 @@@ -1095,7 -1091,6 +1096,7 @@@ 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 */ @@@ -1392,6 -1379,12 +1393,6 @@@ 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 c35fe53a,0b78320c..6156a6ca --- a/src/redis.h +++ b/src/redis.h @@@ -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 @@@ -188,6 -190,7 +190,7 @@@ #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);