]> git.saurik.com Git - redis.git/blobdiff - src/cluster.c
Explicitly zero zval since it is stored on the stack
[redis.git] / src / cluster.c
index b3fcd1ea17416d499ee98f7ba993bb1ad6267a18..783c658d43681d2d731e631c6f3bc7e6fa1b151a 100644 (file)
@@ -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;
 }
 
 /* -----------------------------------------------------------------------------