static ngx_int_t
ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
{
    ngx_http_upstream_hash_peer_data_t  *hp = data;
    time_t                        now;
    u_char                        buf[NGX_INT_T_LEN];
    size_t                        size;
    uint32_t                      hash;
    ngx_int_t                     w;
    uintptr_t                     m;
    ngx_uint_t                    i, n, p;
    ngx_http_upstream_rr_peer_t  *peer;
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                   "get hash peer, try: %ui", pc->tries);
    if (hp->tries > 20 || hp->rrp.peers->single) {
        return hp->get_rr_peer(pc, &hp->rrp);
    }
    now = ngx_time();
    pc->cached = 0;
    pc->connection = NULL;
    for ( ;; ) {
        ngx_crc32_init(hash);
        if (hp->rehash > 0) {
            size = ngx_sprintf(buf, "%ui", hp->rehash) - buf;
            ngx_crc32_update(&hash, buf, size);
        }
        ngx_crc32_update(&hash, hp->key.data, hp->key.len);
        ngx_crc32_final(hash);
        hash = (hash >> 16) & 0x7fff;
        hp->hash += hash;
        hp->rehash++;
        if (!hp->rrp.peers->weighted) {
            p = hp->hash % hp->rrp.peers->number;
        } else {
            w = hp->hash % hp->rrp.peers->total_weight;
            for (i = 0; i < hp->rrp.peers->number; i++) {
                w -= hp->rrp.peers->peer[i].weight;
                if (w < 0) {
                    break;
                }
            }
            p = i;
        }
        n = p / (8 * sizeof(uintptr_t));
        m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
        if (hp->rrp.tried[n] & m) {
            goto next;
        }
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                       "get hash peer, value:%uD, peer:%ui", hp->hash, p);
        peer = &hp->rrp.peers->peer[p];
        if (peer->down) {
            goto next;
        }
        if (peer->max_fails
            && peer->fails >= peer->max_fails
            && now - peer->checked <= peer->fail_timeout)
        {
            goto next;
        }
        break;
    next:
        if (++hp->tries > 20) {
            return hp->get_rr_peer(pc, &hp->rrp);
        }
    }
    hp->rrp.current = p;
    pc->sockaddr = peer->sockaddr;
    pc->socklen = peer->socklen;
    pc->name = &peer->name;
    if (now - peer->checked > peer->fail_timeout) {
        peer->checked = now;
    }
    hp->rrp.tried[n] |= m;
    return NGX_OK;
}
['static ngx_int_t\nngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)\n{\n    ngx_http_upstream_hash_peer_data_t  *hp = data;\n    time_t                        now;\n    u_char                        buf[NGX_INT_T_LEN];\n    size_t                        size;\n    uint32_t                      hash;\n    ngx_int_t                     w;\n    uintptr_t                     m;\n    ngx_uint_t                    i, n, p;\n    ngx_http_upstream_rr_peer_t  *peer;\n    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,\n                   "get hash peer, try: %ui", pc->tries);\n    if (hp->tries > 20 || hp->rrp.peers->single) {\n        return hp->get_rr_peer(pc, &hp->rrp);\n    }\n    now = ngx_time();\n    pc->cached = 0;\n    pc->connection = NULL;\n    for ( ;; ) {\n        ngx_crc32_init(hash);\n        if (hp->rehash > 0) {\n            size = ngx_sprintf(buf, "%ui", hp->rehash) - buf;\n            ngx_crc32_update(&hash, buf, size);\n        }\n        ngx_crc32_update(&hash, hp->key.data, hp->key.len);\n        ngx_crc32_final(hash);\n        hash = (hash >> 16) & 0x7fff;\n        hp->hash += hash;\n        hp->rehash++;\n        if (!hp->rrp.peers->weighted) {\n            p = hp->hash % hp->rrp.peers->number;\n        } else {\n            w = hp->hash % hp->rrp.peers->total_weight;\n            for (i = 0; i < hp->rrp.peers->number; i++) {\n                w -= hp->rrp.peers->peer[i].weight;\n                if (w < 0) {\n                    break;\n                }\n            }\n            p = i;\n        }\n        n = p / (8 * sizeof(uintptr_t));\n        m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));\n        if (hp->rrp.tried[n] & m) {\n            goto next;\n        }\n        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,\n                       "get hash peer, value:%uD, peer:%ui", hp->hash, p);\n        peer = &hp->rrp.peers->peer[p];\n        if (peer->down) {\n            goto next;\n        }\n        if (peer->max_fails\n            && peer->fails >= peer->max_fails\n            && now - peer->checked <= peer->fail_timeout)\n        {\n            goto next;\n        }\n        break;\n    next:\n        if (++hp->tries > 20) {\n            return hp->get_rr_peer(pc, &hp->rrp);\n        }\n    }\n    hp->rrp.current = p;\n    pc->sockaddr = peer->sockaddr;\n    pc->socklen = peer->socklen;\n    pc->name = &peer->name;\n    if (now - peer->checked > peer->fail_timeout) {\n        peer->checked = now;\n    }\n    hp->rrp.tried[n] |= m;\n    return NGX_OK;\n}']