summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2012-11-12 18:47:07 +0000
committerMaxim Dounin <mdounin@mdounin.ru>2012-11-12 18:47:07 +0000
commit0e6c7b0614eafd628c2abe93e5418599a025b552 (patch)
tree8a11874937ca0620b9e2e9ec037e5c9cc2f41357
parent033598bc073da23dcec5e4ea80b85cccecd8958a (diff)
downloadnginx-0e6c7b0614eafd628c2abe93e5418599a025b552.tar.gz
nginx-0e6c7b0614eafd628c2abe93e5418599a025b552.tar.bz2
Merge of r4872, r4893: resolver cached addresses random rotation.
Resolver: cached addresses are returned with random rotation now. This ensures balancing when working with dynamically resolved upstream servers with multiple addresses. Based on patch by Anton Jouline.
Diffstat (limited to '')
-rw-r--r--src/core/ngx_resolver.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 178e0831d..d59d0c471 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -88,6 +88,8 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
static void ngx_resolver_free(ngx_resolver_t *r, void *p);
static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
+static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
+ ngx_uint_t n);
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
@@ -445,8 +447,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
if (naddrs != 1) {
addr = 0;
- addrs = ngx_resolver_dup(r, rn->u.addrs,
- naddrs * sizeof(in_addr_t));
+ addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
if (addrs == NULL) {
return NGX_ERROR;
}
@@ -2135,6 +2136,32 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
}
+static in_addr_t *
+ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
+{
+ void *dst, *p;
+ ngx_uint_t j;
+
+ dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
+
+ if (dst == NULL) {
+ return dst;
+ }
+
+ j = ngx_random() % n;
+
+ if (j == 0) {
+ ngx_memcpy(dst, src, n * sizeof(in_addr_t));
+ return dst;
+ }
+
+ p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
+ ngx_memcpy(p, src, j * sizeof(in_addr_t));
+
+ return dst;
+}
+
+
char *
ngx_resolver_strerror(ngx_int_t err)
{