Process a hello message received via Pub/Sub in master or slave instance, * or sent directly to this sentinel via the (fake) PUBLISH command of Sentinel. * * If the master name specified in the message is not known, the message is * discarded. */
| 2845 | * If the master name specified in the message is not known, the message is |
| 2846 | * discarded. */ |
| 2847 | void sentinelProcessHelloMessage(char *hello, int hello_len) { |
| 2848 | /* Format is composed of 8 tokens: |
| 2849 | * 0=ip,1=port,2=runid,3=current_epoch,4=master_name, |
| 2850 | * 5=master_ip,6=master_port,7=master_config_epoch. */ |
| 2851 | int numtokens, port, removed, master_port; |
| 2852 | uint64_t current_epoch, master_config_epoch; |
| 2853 | char **token = sdssplitlen(hello, hello_len, ",", 1, &numtokens); |
| 2854 | sentinelRedisInstance *si, *master; |
| 2855 | |
| 2856 | if (numtokens == 8) { |
| 2857 | /* Obtain a reference to the master this hello message is about */ |
| 2858 | master = sentinelGetMasterByName(token[4]); |
| 2859 | if (!master) goto cleanup; /* Unknown master, skip the message. */ |
| 2860 | |
| 2861 | /* First, try to see if we already have this sentinel. */ |
| 2862 | port = atoi(token[1]); |
| 2863 | master_port = atoi(token[6]); |
| 2864 | si = getSentinelRedisInstanceByAddrAndRunID( |
| 2865 | master->sentinels,token[0],port,token[2]); |
| 2866 | current_epoch = strtoull(token[3],NULL,10); |
| 2867 | master_config_epoch = strtoull(token[7],NULL,10); |
| 2868 | |
| 2869 | if (!si) { |
| 2870 | /* If not, remove all the sentinels that have the same runid |
| 2871 | * because there was an address change, and add the same Sentinel |
| 2872 | * with the new address back. */ |
| 2873 | removed = removeMatchingSentinelFromMaster(master,token[2]); |
| 2874 | if (removed) { |
| 2875 | sentinelEvent(LL_NOTICE,"+sentinel-address-switch",master, |
| 2876 | "%@ ip %s port %d for %s", token[0],port,token[2]); |
| 2877 | } else { |
| 2878 | /* Check if there is another Sentinel with the same address this |
| 2879 | * new one is reporting. What we do if this happens is to set its |
| 2880 | * port to 0, to signal the address is invalid. We'll update it |
| 2881 | * later if we get an HELLO message. */ |
| 2882 | sentinelRedisInstance *other = |
| 2883 | getSentinelRedisInstanceByAddrAndRunID( |
| 2884 | master->sentinels, token[0],port,NULL); |
| 2885 | if (other) { |
| 2886 | sentinelEvent(LL_NOTICE,"+sentinel-invalid-addr",other,"%@"); |
| 2887 | other->addr->port = 0; /* It means: invalid address. */ |
| 2888 | sentinelUpdateSentinelAddressInAllMasters(other); |
| 2889 | } |
| 2890 | } |
| 2891 | |
| 2892 | /* Add the new sentinel. */ |
| 2893 | si = createSentinelRedisInstance(token[2],SRI_SENTINEL, |
| 2894 | token[0],port,master->quorum,master); |
| 2895 | |
| 2896 | if (si) { |
| 2897 | if (!removed) sentinelEvent(LL_NOTICE,"+sentinel",si,"%@"); |
| 2898 | /* The runid is NULL after a new instance creation and |
| 2899 | * for Sentinels we don't have a later chance to fill it, |
| 2900 | * so do it now. */ |
| 2901 | si->runid = sdsnew(token[2]); |
| 2902 | sentinelTryConnectionSharing(si); |
| 2903 | if (removed) sentinelUpdateSentinelAddressInAllMasters(si); |
| 2904 | sentinelFlushConfig(); |
no test coverage detected