static ngx_int_t ngx_http_upstream_init_hash_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { ngx_http_upstream_hash_peer_data_t *uhpd; ngx_str_t val; if (ngx_http_script_run(r, &val, us->lengths, 0, us->values) == NULL) { return NGX_ERROR; } uhpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_hash_peer_data_t) + sizeof(uintptr_t) * ((ngx_http_upstream_hash_peers_t *)us->peer.data)->number / (8 * sizeof(uintptr_t))); if (uhpd == NULL) { return NGX_ERROR; } r->upstream->peer.data = uhpd; uhpd->peers = us->peer.data; r->upstream->peer.free = ngx_http_upstream_free_hash_peer; r->upstream->peer.get = ngx_http_upstream_get_hash_peer; r->upstream->peer.tries = us->retries + 1; #if (NGX_HTTP_SSL) r->upstream->peer.set_session = ngx_http_upstream_set_hash_peer_session; r->upstream->peer.save_session = ngx_http_upstream_save_hash_peer_session; #endif /* must be big enough for the retry keys */ if ((uhpd->current_key.data = ngx_pcalloc(r->pool, NGX_ATOMIC_T_LEN + val.len)) == NULL) { return NGX_ERROR; } ngx_memcpy(uhpd->current_key.data, val.data, val.len); uhpd->current_key.len = val.len; uhpd->original_key = val; uhpd->hash = ngx_http_upstream_hash_crc32(uhpd->current_key.data, uhpd->current_key.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream_hash: hashed \"%V\" to %ui", &uhpd->current_key, ngx_http_upstream_get_hash_peer_index(uhpd)); uhpd->try_i = 0; /* In case this one is marked down */ ngx_http_upstream_hash_next_peer(uhpd, &r->upstream->peer.tries, r->connection->log); if ((ngx_int_t)r->upstream->peer.tries == -1) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream_hash: Starting with %ui", ngx_http_upstream_get_hash_peer_index(uhpd)); return NGX_OK; }
/* retry implementation is PECL memcache compatible */ static void ngx_http_upstream_free_hash_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) { ngx_http_upstream_hash_peer_data_t *uhpd = data; ngx_uint_t current; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "upstream_hash: free upstream hash peer try %ui", pc->tries); if (state & (NGX_PEER_FAILED|NGX_PEER_NEXT) && pc->tries) { current = uhpd->hash % uhpd->peers->number; uhpd->tried[ngx_bitvector_index(current)] |= ngx_bitvector_bit(current); ngx_http_upstream_hash_next_peer(uhpd, &pc->tries, pc->log); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "upstream_hash: Using %ui because %ui failed", uhpd->hash % uhpd->peers->number, current); } else { pc->tries = 0; } }