| 772 | } |
| 773 | |
| 774 | bool RedisClusterChannel::FetchAndParseClusterSlots( |
| 775 | Channel* channel, |
| 776 | const std::string& endpoint, |
| 777 | std::vector<std::string>* slot_to_endpoint, |
| 778 | std::vector<std::string>* discovered_endpoints) { |
| 779 | RedisRequest request; |
| 780 | if (!request.AddCommand("cluster slots")) { |
| 781 | return false; |
| 782 | } |
| 783 | |
| 784 | RedisResponse response; |
| 785 | Controller cntl; |
| 786 | cntl.set_timeout_ms(_options.topology_refresh_timeout_ms); |
| 787 | channel->CallMethod(NULL, &cntl, &request, &response, NULL); |
| 788 | if (cntl.Failed()) { |
| 789 | return false; |
| 790 | } |
| 791 | |
| 792 | if (response.reply_size() != 1 || !response.reply(0).is_array()) { |
| 793 | return false; |
| 794 | } |
| 795 | |
| 796 | const RedisReply& root = response.reply(0); |
| 797 | const std::string fallback_host = EndpointHost(endpoint); |
| 798 | bool has_slot = false; |
| 799 | for (size_t i = 0; i < root.size(); ++i) { |
| 800 | const RedisReply& item = root[i]; |
| 801 | if (!item.is_array() || item.size() < 3) { |
| 802 | continue; |
| 803 | } |
| 804 | if (!item[0].is_integer() || !item[1].is_integer()) { |
| 805 | continue; |
| 806 | } |
| 807 | |
| 808 | int64_t start = item[0].integer(); |
| 809 | int64_t end = item[1].integer(); |
| 810 | if (start < 0 || end < start) { |
| 811 | continue; |
| 812 | } |
| 813 | |
| 814 | if (!item[2].is_array() || item[2].size() < 2 || !item[2][1].is_integer()) { |
| 815 | continue; |
| 816 | } |
| 817 | std::string host; |
| 818 | if (item[2][0].is_string()) { |
| 819 | host = item[2][0].data().as_string(); |
| 820 | } |
| 821 | if (host.empty()) { |
| 822 | host = fallback_host; |
| 823 | } |
| 824 | |
| 825 | const int64_t port = item[2][1].integer(); |
| 826 | if (port <= 0 || port > 65535) { |
| 827 | continue; |
| 828 | } |
| 829 | |
| 830 | std::ostringstream oss; |
| 831 | oss << host << ":" << port; |
nothing calls this directly
no test coverage detected