X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/c7c7cfbddca1325e600e5c0fd4cfcfde38cc0758..02e600653216cebc0746bfbb86b353667a843591:/src/cluster.c diff --git a/src/cluster.c b/src/cluster.c index b3fcd1ea..783c658d 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -44,7 +44,7 @@ int clusterLoadConfig(char *filename) { return REDIS_OK; fmterr: - redisLog(REDIS_WARNING,"Unrecovarable error: corrupted cluster.conf file."); + redisLog(REDIS_WARNING,"Unrecovarable error: corrupted cluster config file."); fclose(fp); exit(1); } @@ -53,11 +53,12 @@ fmterr: * * This function writes the node config and returns 0, on error -1 * is returned. */ -int clusterSaveConfig(char *filename) { +int clusterSaveConfig(void) { sds ci = clusterGenNodesDescription(); int fd; - if ((fd = open(filename,O_WRONLY|O_CREAT,0644)) == -1) goto err; + if ((fd = open(server.cluster.configfile,O_WRONLY|O_CREAT,0644)) == -1) + goto err; if (write(fd,ci,sdslen(ci)) != (ssize_t)sdslen(ci)) goto err; close(fd); sdsfree(ci); @@ -68,7 +69,16 @@ err: return -1; } +void clusterSaveConfigOrDie(void) { + if (clusterSaveConfig() == -1) { + redisLog(REDIS_WARNING,"Fatal: can't update cluster config file."); + exit(1); + } +} + void clusterInit(void) { + int saveconf = 0; + server.cluster.myself = createClusterNode(NULL,REDIS_NODE_MYSELF); server.cluster.state = REDIS_CLUSTER_FAIL; server.cluster.nodes = dictCreate(&clusterNodesDictType,NULL); @@ -79,17 +89,15 @@ void clusterInit(void) { sizeof(server.cluster.importing_slots_from)); memset(server.cluster.slots,0, sizeof(server.cluster.slots)); - if (clusterLoadConfig("cluster.conf") == REDIS_ERR) { + if (clusterLoadConfig(server.cluster.configfile) == REDIS_ERR) { /* No configuration found. We will just use the random name provided * by the createClusterNode() function. */ redisLog(REDIS_NOTICE,"No cluster configuration found, I'm %.40s", server.cluster.myself->name); - if (clusterSaveConfig("cluster.conf") == -1) { - redisLog(REDIS_WARNING,"Fatal: can't update cluster config file."); - exit(1); - } + clusterAddNode(server.cluster.myself); + saveconf = 1; } - clusterAddNode(server.cluster.myself); + if (saveconf) clusterSaveConfigOrDie(); /* We need a listening TCP port for our cluster messaging needs */ server.cfd = anetTcpServer(server.neterr, server.port+REDIS_CLUSTER_PORT_INCR, server.bindaddr); @@ -905,6 +913,7 @@ sds clusterGenNodesDescription(void) { sds ci = sdsempty(); dictIterator *di; dictEntry *de; + int j, start; di = dictGetIterator(server.cluster.nodes); while((de = dictNext(di)) != NULL) { @@ -934,11 +943,32 @@ sds clusterGenNodesDescription(void) { ci = sdscatprintf(ci,"- "); /* Latency from the POV of this node, link status */ - ci = sdscatprintf(ci,"%ld %ld %s\n", + ci = sdscatprintf(ci,"%ld %ld %s", (long) node->ping_sent, (long) node->pong_received, node->link ? "connected" : "disconnected"); + + /* Slots served by this instance */ + start = -1; + for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { + int bit; + + if ((bit = clusterNodeGetSlotBit(node,j)) != 0) { + if (start == -1) start = j; + } + if (start != -1 && (!bit || j == REDIS_CLUSTER_SLOTS-1)) { + if (j == REDIS_CLUSTER_SLOTS-1) j++; + + if (start == j-1) { + ci = sdscatprintf(ci," %d",start); + } else { + ci = sdscatprintf(ci," %d-%d",start,j-1); + } + start = -1; + } + } } + ci = sdscatlen(ci,"\n",1); dictReleaseIterator(di); return ci; } @@ -1110,8 +1140,10 @@ void restoreCommand(redisClient *c) { /* Finally create the object from the serialized dump and * store it at the specified key. */ - o = rdbLoadObject(data[0],fp); - if (o == NULL) { + if ((data[0] > 4 && data[0] < 9) || + data[0] > 11 || + (o = rdbLoadObject(data[0],fp)) == NULL) + { addReplyError(c,"Bad data format."); fclose(fp); return; @@ -1240,6 +1272,7 @@ file_wr_err: strerror(errno)); fclose(fp); close(fd); + return; file_rd_err: redisLog(REDIS_WARNING,"Can't read from tmp file for MIGRATE: %s", @@ -1248,6 +1281,7 @@ file_rd_err: strerror(errno)); fclose(fp); close(fd); + return; socket_wr_err: redisLog(REDIS_NOTICE,"Can't write to target node for MIGRATE: %s", @@ -1256,6 +1290,7 @@ socket_wr_err: strerror(errno)); fclose(fp); close(fd); + return; socket_rd_err: redisLog(REDIS_NOTICE,"Can't read from target node for MIGRATE: %s", @@ -1264,6 +1299,81 @@ socket_rd_err: strerror(errno)); fclose(fp); close(fd); + return; +} + +/* DUMP keyname + * DUMP is actually not used by Redis Cluster but it is the obvious + * complement of RESTORE and can be useful for different applications. */ +void dumpCommand(redisClient *c) { + char buf[64]; + FILE *fp; + robj *o, *dumpobj; + sds dump = NULL; + off_t payload_len; + unsigned int type; + + /* Check if the key is here. */ + if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) { + addReply(c,shared.nullbulk); + return; + } + + /* Create temp file */ + snprintf(buf,sizeof(buf),"redis-dump-%d.tmp",getpid()); + fp = fopen(buf,"w+"); + if (!fp) { + redisLog(REDIS_WARNING,"Can't open tmp file for MIGRATE: %s", + strerror(errno)); + addReplyErrorFormat(c,"DUMP failed, tmp file creation error: %s.", + strerror(errno)); + return; + } + unlink(buf); + + /* Dump the serailized object and read it back in memory. + * We prefix it with a one byte containing the type ID. + * This is the serialization format understood by RESTORE. */ + if (rdbSaveObject(fp,o) == -1) goto file_wr_err; + payload_len = ftello(fp); + if (fseeko(fp,0,SEEK_SET) == -1) goto file_rd_err; + dump = sdsnewlen(NULL,payload_len+1); + if (payload_len && fread(dump+1,payload_len,1,fp) != 1) goto file_rd_err; + fclose(fp); + type = o->type; + if (type == REDIS_LIST && o->encoding == REDIS_ENCODING_ZIPLIST) + type = REDIS_LIST_ZIPLIST; + else if (type == REDIS_HASH && o->encoding == REDIS_ENCODING_ZIPMAP) + type = REDIS_HASH_ZIPMAP; + else if (type == REDIS_SET && o->encoding == REDIS_ENCODING_INTSET) + type = REDIS_SET_INTSET; + else + type = o->type; + dump[0] = type; + + /* Transfer to the client */ + dumpobj = createObject(REDIS_STRING,dump); + addReplyBulk(c,dumpobj); + decrRefCount(dumpobj); + return; + +file_wr_err: + redisLog(REDIS_WARNING,"Can't write on tmp file for DUMP: %s", + strerror(errno)); + addReplyErrorFormat(c,"DUMP failed, tmp file write error: %s.", + strerror(errno)); + sdsfree(dump); + fclose(fp); + return; + +file_rd_err: + redisLog(REDIS_WARNING,"Can't read from tmp file for DUMP: %s", + strerror(errno)); + addReplyErrorFormat(c,"DUMP failed, tmp file read error: %s.", + strerror(errno)); + sdsfree(dump); + fclose(fp); + return; } /* -----------------------------------------------------------------------------