Load the cluster config from 'filename'. * * If the file does not exist or is zero-length (this may happen because * when we lock the nodes.conf file, we create a zero-length one for the * sake of locking if it does not already exist), C_ERR is returned. * If the configuration was loaded from the file, C_OK is returned. */
| 99 | * sake of locking if it does not already exist), C_ERR is returned. |
| 100 | * If the configuration was loaded from the file, C_OK is returned. */ |
| 101 | int clusterLoadConfig(char *filename) { |
| 102 | FILE *fp = fopen(filename,"r"); |
| 103 | struct stat sb; |
| 104 | char *line; |
| 105 | int maxline, j; |
| 106 | |
| 107 | if (fp == NULL) { |
| 108 | if (errno == ENOENT) { |
| 109 | return C_ERR; |
| 110 | } else { |
| 111 | serverLog(LL_WARNING, |
| 112 | "Loading the cluster node config from %s: %s", |
| 113 | filename, strerror(errno)); |
| 114 | exit(1); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /* Check if the file is zero-length: if so return C_ERR to signal |
| 119 | * we have to write the config. */ |
| 120 | if (fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) { |
| 121 | fclose(fp); |
| 122 | return C_ERR; |
| 123 | } |
| 124 | |
| 125 | /* Parse the file. Note that single lines of the cluster config file can |
| 126 | * be really long as they include all the hash slots of the node. |
| 127 | * This means in the worst possible case, half of the Redis slots will be |
| 128 | * present in a single line, possibly in importing or migrating state, so |
| 129 | * together with the node ID of the sender/receiver. |
| 130 | * |
| 131 | * To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */ |
| 132 | maxline = 1024+CLUSTER_SLOTS*128; |
| 133 | line = (char*)zmalloc(maxline, MALLOC_LOCAL); |
| 134 | while(fgets(line,maxline,fp) != NULL) { |
| 135 | int argc; |
| 136 | sds *argv; |
| 137 | clusterNode *n, *master; |
| 138 | char *p, *s; |
| 139 | |
| 140 | /* Skip blank lines, they can be created either by users manually |
| 141 | * editing nodes.conf or by the config writing process if stopped |
| 142 | * before the truncate() call. */ |
| 143 | if (line[0] == '\n' || line[0] == '\0') continue; |
| 144 | |
| 145 | /* Split the line into arguments for processing. */ |
| 146 | argv = sdssplitargs(line,&argc); |
| 147 | if (argv == NULL) goto fmterr; |
| 148 | |
| 149 | /* Handle the special "vars" line. Don't pretend it is the last |
| 150 | * line even if it actually is when generated by Redis. */ |
| 151 | if (strcasecmp(argv[0],"vars") == 0) { |
| 152 | if (!(argc % 2)) goto fmterr; |
| 153 | for (j = 1; j < argc; j += 2) { |
| 154 | if (strcasecmp(argv[j],"currentEpoch") == 0) { |
| 155 | g_pserver->cluster->currentEpoch = |
| 156 | strtoull(argv[j+1],NULL,10); |
| 157 | } else if (strcasecmp(argv[j],"lastVoteEpoch") == 0) { |
| 158 | g_pserver->cluster->lastVoteEpoch = |
no test coverage detected