Annotation of embedaddon/nginx/src/http/ngx_http_upstream_round_robin.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_http.h>
! 11:
! 12:
! 13: static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
! 14: ngx_http_upstream_rr_peer_data_t *rrp);
! 15:
! 16: #if (NGX_HTTP_SSL)
! 17:
! 18: static ngx_int_t ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc,
! 19: void *data);
! 20: static void ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc,
! 21: void *data);
! 22:
! 23: #endif
! 24:
! 25:
! 26: ngx_int_t
! 27: ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
! 28: ngx_http_upstream_srv_conf_t *us)
! 29: {
! 30: ngx_url_t u;
! 31: ngx_uint_t i, j, n, w;
! 32: ngx_http_upstream_server_t *server;
! 33: ngx_http_upstream_rr_peers_t *peers, *backup;
! 34:
! 35: us->peer.init = ngx_http_upstream_init_round_robin_peer;
! 36:
! 37: if (us->servers) {
! 38: server = us->servers->elts;
! 39:
! 40: n = 0;
! 41: w = 0;
! 42:
! 43: for (i = 0; i < us->servers->nelts; i++) {
! 44: if (server[i].backup) {
! 45: continue;
! 46: }
! 47:
! 48: n += server[i].naddrs;
! 49: w += server[i].naddrs * server[i].weight;
! 50: }
! 51:
! 52: if (n == 0) {
! 53: ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
! 54: "no servers in upstream \"%V\" in %s:%ui",
! 55: &us->host, us->file_name, us->line);
! 56: return NGX_ERROR;
! 57: }
! 58:
! 59: peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
! 60: + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
! 61: if (peers == NULL) {
! 62: return NGX_ERROR;
! 63: }
! 64:
! 65: peers->single = (n == 1);
! 66: peers->number = n;
! 67: peers->weighted = (w != n);
! 68: peers->total_weight = w;
! 69: peers->name = &us->host;
! 70:
! 71: n = 0;
! 72:
! 73: for (i = 0; i < us->servers->nelts; i++) {
! 74: for (j = 0; j < server[i].naddrs; j++) {
! 75: if (server[i].backup) {
! 76: continue;
! 77: }
! 78:
! 79: peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
! 80: peers->peer[n].socklen = server[i].addrs[j].socklen;
! 81: peers->peer[n].name = server[i].addrs[j].name;
! 82: peers->peer[n].max_fails = server[i].max_fails;
! 83: peers->peer[n].fail_timeout = server[i].fail_timeout;
! 84: peers->peer[n].down = server[i].down;
! 85: peers->peer[n].weight = server[i].weight;
! 86: peers->peer[n].effective_weight = server[i].weight;
! 87: peers->peer[n].current_weight = 0;
! 88: n++;
! 89: }
! 90: }
! 91:
! 92: us->peer.data = peers;
! 93:
! 94: /* backup servers */
! 95:
! 96: n = 0;
! 97: w = 0;
! 98:
! 99: for (i = 0; i < us->servers->nelts; i++) {
! 100: if (!server[i].backup) {
! 101: continue;
! 102: }
! 103:
! 104: n += server[i].naddrs;
! 105: w += server[i].naddrs * server[i].weight;
! 106: }
! 107:
! 108: if (n == 0) {
! 109: return NGX_OK;
! 110: }
! 111:
! 112: backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
! 113: + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
! 114: if (backup == NULL) {
! 115: return NGX_ERROR;
! 116: }
! 117:
! 118: peers->single = 0;
! 119: backup->single = 0;
! 120: backup->number = n;
! 121: backup->weighted = (w != n);
! 122: backup->total_weight = w;
! 123: backup->name = &us->host;
! 124:
! 125: n = 0;
! 126:
! 127: for (i = 0; i < us->servers->nelts; i++) {
! 128: for (j = 0; j < server[i].naddrs; j++) {
! 129: if (!server[i].backup) {
! 130: continue;
! 131: }
! 132:
! 133: backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
! 134: backup->peer[n].socklen = server[i].addrs[j].socklen;
! 135: backup->peer[n].name = server[i].addrs[j].name;
! 136: backup->peer[n].weight = server[i].weight;
! 137: backup->peer[n].effective_weight = server[i].weight;
! 138: backup->peer[n].current_weight = 0;
! 139: backup->peer[n].max_fails = server[i].max_fails;
! 140: backup->peer[n].fail_timeout = server[i].fail_timeout;
! 141: backup->peer[n].down = server[i].down;
! 142: n++;
! 143: }
! 144: }
! 145:
! 146: peers->next = backup;
! 147:
! 148: return NGX_OK;
! 149: }
! 150:
! 151:
! 152: /* an upstream implicitly defined by proxy_pass, etc. */
! 153:
! 154: if (us->port == 0) {
! 155: ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
! 156: "no port in upstream \"%V\" in %s:%ui",
! 157: &us->host, us->file_name, us->line);
! 158: return NGX_ERROR;
! 159: }
! 160:
! 161: ngx_memzero(&u, sizeof(ngx_url_t));
! 162:
! 163: u.host = us->host;
! 164: u.port = us->port;
! 165:
! 166: if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
! 167: if (u.err) {
! 168: ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
! 169: "%s in upstream \"%V\" in %s:%ui",
! 170: u.err, &us->host, us->file_name, us->line);
! 171: }
! 172:
! 173: return NGX_ERROR;
! 174: }
! 175:
! 176: n = u.naddrs;
! 177:
! 178: peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
! 179: + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
! 180: if (peers == NULL) {
! 181: return NGX_ERROR;
! 182: }
! 183:
! 184: peers->single = (n == 1);
! 185: peers->number = n;
! 186: peers->weighted = 0;
! 187: peers->total_weight = n;
! 188: peers->name = &us->host;
! 189:
! 190: for (i = 0; i < u.naddrs; i++) {
! 191: peers->peer[i].sockaddr = u.addrs[i].sockaddr;
! 192: peers->peer[i].socklen = u.addrs[i].socklen;
! 193: peers->peer[i].name = u.addrs[i].name;
! 194: peers->peer[i].weight = 1;
! 195: peers->peer[i].effective_weight = 1;
! 196: peers->peer[i].current_weight = 0;
! 197: peers->peer[i].max_fails = 1;
! 198: peers->peer[i].fail_timeout = 10;
! 199: }
! 200:
! 201: us->peer.data = peers;
! 202:
! 203: /* implicitly defined upstream has no backup servers */
! 204:
! 205: return NGX_OK;
! 206: }
! 207:
! 208:
! 209: ngx_int_t
! 210: ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
! 211: ngx_http_upstream_srv_conf_t *us)
! 212: {
! 213: ngx_uint_t n;
! 214: ngx_http_upstream_rr_peer_data_t *rrp;
! 215:
! 216: rrp = r->upstream->peer.data;
! 217:
! 218: if (rrp == NULL) {
! 219: rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
! 220: if (rrp == NULL) {
! 221: return NGX_ERROR;
! 222: }
! 223:
! 224: r->upstream->peer.data = rrp;
! 225: }
! 226:
! 227: rrp->peers = us->peer.data;
! 228: rrp->current = 0;
! 229:
! 230: n = rrp->peers->number;
! 231:
! 232: if (rrp->peers->next && rrp->peers->next->number > n) {
! 233: n = rrp->peers->next->number;
! 234: }
! 235:
! 236: if (n <= 8 * sizeof(uintptr_t)) {
! 237: rrp->tried = &rrp->data;
! 238: rrp->data = 0;
! 239:
! 240: } else {
! 241: n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
! 242:
! 243: rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
! 244: if (rrp->tried == NULL) {
! 245: return NGX_ERROR;
! 246: }
! 247: }
! 248:
! 249: r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
! 250: r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
! 251: r->upstream->peer.tries = rrp->peers->number;
! 252: #if (NGX_HTTP_SSL)
! 253: r->upstream->peer.set_session =
! 254: ngx_http_upstream_set_round_robin_peer_session;
! 255: r->upstream->peer.save_session =
! 256: ngx_http_upstream_save_round_robin_peer_session;
! 257: #endif
! 258:
! 259: return NGX_OK;
! 260: }
! 261:
! 262:
! 263: ngx_int_t
! 264: ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
! 265: ngx_http_upstream_resolved_t *ur)
! 266: {
! 267: u_char *p;
! 268: size_t len;
! 269: ngx_uint_t i, n;
! 270: struct sockaddr_in *sin;
! 271: ngx_http_upstream_rr_peers_t *peers;
! 272: ngx_http_upstream_rr_peer_data_t *rrp;
! 273:
! 274: rrp = r->upstream->peer.data;
! 275:
! 276: if (rrp == NULL) {
! 277: rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
! 278: if (rrp == NULL) {
! 279: return NGX_ERROR;
! 280: }
! 281:
! 282: r->upstream->peer.data = rrp;
! 283: }
! 284:
! 285: peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t)
! 286: + sizeof(ngx_http_upstream_rr_peer_t) * (ur->naddrs - 1));
! 287: if (peers == NULL) {
! 288: return NGX_ERROR;
! 289: }
! 290:
! 291: peers->single = (ur->naddrs == 1);
! 292: peers->number = ur->naddrs;
! 293: peers->name = &ur->host;
! 294:
! 295: if (ur->sockaddr) {
! 296: peers->peer[0].sockaddr = ur->sockaddr;
! 297: peers->peer[0].socklen = ur->socklen;
! 298: peers->peer[0].name = ur->host;
! 299: peers->peer[0].weight = 1;
! 300: peers->peer[0].effective_weight = 1;
! 301: peers->peer[0].current_weight = 0;
! 302: peers->peer[0].max_fails = 1;
! 303: peers->peer[0].fail_timeout = 10;
! 304:
! 305: } else {
! 306:
! 307: for (i = 0; i < ur->naddrs; i++) {
! 308:
! 309: len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
! 310:
! 311: p = ngx_pnalloc(r->pool, len);
! 312: if (p == NULL) {
! 313: return NGX_ERROR;
! 314: }
! 315:
! 316: len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
! 317: len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
! 318:
! 319: sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
! 320: if (sin == NULL) {
! 321: return NGX_ERROR;
! 322: }
! 323:
! 324: sin->sin_family = AF_INET;
! 325: sin->sin_port = htons(ur->port);
! 326: sin->sin_addr.s_addr = ur->addrs[i];
! 327:
! 328: peers->peer[i].sockaddr = (struct sockaddr *) sin;
! 329: peers->peer[i].socklen = sizeof(struct sockaddr_in);
! 330: peers->peer[i].name.len = len;
! 331: peers->peer[i].name.data = p;
! 332: peers->peer[i].weight = 1;
! 333: peers->peer[i].effective_weight = 1;
! 334: peers->peer[i].current_weight = 0;
! 335: peers->peer[i].max_fails = 1;
! 336: peers->peer[i].fail_timeout = 10;
! 337: }
! 338: }
! 339:
! 340: rrp->peers = peers;
! 341: rrp->current = 0;
! 342:
! 343: if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {
! 344: rrp->tried = &rrp->data;
! 345: rrp->data = 0;
! 346:
! 347: } else {
! 348: n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
! 349: / (8 * sizeof(uintptr_t));
! 350:
! 351: rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
! 352: if (rrp->tried == NULL) {
! 353: return NGX_ERROR;
! 354: }
! 355: }
! 356:
! 357: r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
! 358: r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
! 359: r->upstream->peer.tries = rrp->peers->number;
! 360: #if (NGX_HTTP_SSL)
! 361: r->upstream->peer.set_session = ngx_http_upstream_empty_set_session;
! 362: r->upstream->peer.save_session = ngx_http_upstream_empty_save_session;
! 363: #endif
! 364:
! 365: return NGX_OK;
! 366: }
! 367:
! 368:
! 369: ngx_int_t
! 370: ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
! 371: {
! 372: ngx_http_upstream_rr_peer_data_t *rrp = data;
! 373:
! 374: ngx_int_t rc;
! 375: ngx_uint_t i, n;
! 376: ngx_http_upstream_rr_peer_t *peer;
! 377: ngx_http_upstream_rr_peers_t *peers;
! 378:
! 379: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 380: "get rr peer, try: %ui", pc->tries);
! 381:
! 382: /* ngx_lock_mutex(rrp->peers->mutex); */
! 383:
! 384: pc->cached = 0;
! 385: pc->connection = NULL;
! 386:
! 387: if (rrp->peers->single) {
! 388: peer = &rrp->peers->peer[0];
! 389:
! 390: if (peer->down) {
! 391: goto failed;
! 392: }
! 393:
! 394: } else {
! 395:
! 396: /* there are several peers */
! 397:
! 398: peer = ngx_http_upstream_get_peer(rrp);
! 399:
! 400: if (peer == NULL) {
! 401: goto failed;
! 402: }
! 403:
! 404: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 405: "get rr peer, current: %ui %i",
! 406: rrp->current, peer->current_weight);
! 407: }
! 408:
! 409: pc->sockaddr = peer->sockaddr;
! 410: pc->socklen = peer->socklen;
! 411: pc->name = &peer->name;
! 412:
! 413: /* ngx_unlock_mutex(rrp->peers->mutex); */
! 414:
! 415: if (pc->tries == 1 && rrp->peers->next) {
! 416: pc->tries += rrp->peers->next->number;
! 417: }
! 418:
! 419: return NGX_OK;
! 420:
! 421: failed:
! 422:
! 423: peers = rrp->peers;
! 424:
! 425: if (peers->next) {
! 426:
! 427: /* ngx_unlock_mutex(peers->mutex); */
! 428:
! 429: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");
! 430:
! 431: rrp->peers = peers->next;
! 432: pc->tries = rrp->peers->number;
! 433:
! 434: n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
! 435: / (8 * sizeof(uintptr_t));
! 436:
! 437: for (i = 0; i < n; i++) {
! 438: rrp->tried[i] = 0;
! 439: }
! 440:
! 441: rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);
! 442:
! 443: if (rc != NGX_BUSY) {
! 444: return rc;
! 445: }
! 446:
! 447: /* ngx_lock_mutex(peers->mutex); */
! 448: }
! 449:
! 450: /* all peers failed, mark them as live for quick recovery */
! 451:
! 452: for (i = 0; i < peers->number; i++) {
! 453: peers->peer[i].fails = 0;
! 454: }
! 455:
! 456: /* ngx_unlock_mutex(peers->mutex); */
! 457:
! 458: pc->name = peers->name;
! 459:
! 460: return NGX_BUSY;
! 461: }
! 462:
! 463:
! 464: static ngx_http_upstream_rr_peer_t *
! 465: ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
! 466: {
! 467: time_t now;
! 468: uintptr_t m;
! 469: ngx_int_t total;
! 470: ngx_uint_t i, n;
! 471: ngx_http_upstream_rr_peer_t *peer, *best;
! 472:
! 473: now = ngx_time();
! 474:
! 475: best = NULL;
! 476: total = 0;
! 477:
! 478: for (i = 0; i < rrp->peers->number; i++) {
! 479:
! 480: n = i / (8 * sizeof(uintptr_t));
! 481: m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
! 482:
! 483: if (rrp->tried[n] & m) {
! 484: continue;
! 485: }
! 486:
! 487: peer = &rrp->peers->peer[i];
! 488:
! 489: if (peer->down) {
! 490: continue;
! 491: }
! 492:
! 493: if (peer->max_fails
! 494: && peer->fails >= peer->max_fails
! 495: && now - peer->checked <= peer->fail_timeout)
! 496: {
! 497: continue;
! 498: }
! 499:
! 500: peer->current_weight += peer->effective_weight;
! 501: total += peer->effective_weight;
! 502:
! 503: if (peer->effective_weight < peer->weight) {
! 504: peer->effective_weight++;
! 505: }
! 506:
! 507: if (best == NULL || peer->current_weight > best->current_weight) {
! 508: best = peer;
! 509: }
! 510: }
! 511:
! 512: if (best == NULL) {
! 513: return NULL;
! 514: }
! 515:
! 516: i = best - &rrp->peers->peer[0];
! 517:
! 518: rrp->current = i;
! 519:
! 520: n = i / (8 * sizeof(uintptr_t));
! 521: m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
! 522:
! 523: rrp->tried[n] |= m;
! 524:
! 525: best->current_weight -= total;
! 526:
! 527: if (now - best->checked > best->fail_timeout) {
! 528: best->checked = now;
! 529: }
! 530:
! 531: return best;
! 532: }
! 533:
! 534:
! 535: void
! 536: ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
! 537: ngx_uint_t state)
! 538: {
! 539: ngx_http_upstream_rr_peer_data_t *rrp = data;
! 540:
! 541: time_t now;
! 542: ngx_http_upstream_rr_peer_t *peer;
! 543:
! 544: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 545: "free rr peer %ui %ui", pc->tries, state);
! 546:
! 547: /* TODO: NGX_PEER_KEEPALIVE */
! 548:
! 549: if (rrp->peers->single) {
! 550: pc->tries = 0;
! 551: return;
! 552: }
! 553:
! 554: peer = &rrp->peers->peer[rrp->current];
! 555:
! 556: if (state & NGX_PEER_FAILED) {
! 557: now = ngx_time();
! 558:
! 559: /* ngx_lock_mutex(rrp->peers->mutex); */
! 560:
! 561: peer->fails++;
! 562: peer->accessed = now;
! 563: peer->checked = now;
! 564:
! 565: if (peer->max_fails) {
! 566: peer->effective_weight -= peer->weight / peer->max_fails;
! 567: }
! 568:
! 569: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 570: "free rr peer failed: %ui %i",
! 571: rrp->current, peer->effective_weight);
! 572:
! 573: if (peer->effective_weight < 0) {
! 574: peer->effective_weight = 0;
! 575: }
! 576:
! 577: /* ngx_unlock_mutex(rrp->peers->mutex); */
! 578:
! 579: } else {
! 580:
! 581: /* mark peer live if check passed */
! 582:
! 583: if (peer->accessed < peer->checked) {
! 584: peer->fails = 0;
! 585: }
! 586: }
! 587:
! 588: if (pc->tries) {
! 589: pc->tries--;
! 590: }
! 591:
! 592: /* ngx_unlock_mutex(rrp->peers->mutex); */
! 593: }
! 594:
! 595:
! 596: #if (NGX_HTTP_SSL)
! 597:
! 598: ngx_int_t
! 599: ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
! 600: void *data)
! 601: {
! 602: ngx_http_upstream_rr_peer_data_t *rrp = data;
! 603:
! 604: ngx_int_t rc;
! 605: ngx_ssl_session_t *ssl_session;
! 606: ngx_http_upstream_rr_peer_t *peer;
! 607:
! 608: peer = &rrp->peers->peer[rrp->current];
! 609:
! 610: /* TODO: threads only mutex */
! 611: /* ngx_lock_mutex(rrp->peers->mutex); */
! 612:
! 613: ssl_session = peer->ssl_session;
! 614:
! 615: rc = ngx_ssl_set_session(pc->connection, ssl_session);
! 616:
! 617: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 618: "set session: %p:%d",
! 619: ssl_session, ssl_session ? ssl_session->references : 0);
! 620:
! 621: /* ngx_unlock_mutex(rrp->peers->mutex); */
! 622:
! 623: return rc;
! 624: }
! 625:
! 626:
! 627: void
! 628: ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
! 629: void *data)
! 630: {
! 631: ngx_http_upstream_rr_peer_data_t *rrp = data;
! 632:
! 633: ngx_ssl_session_t *old_ssl_session, *ssl_session;
! 634: ngx_http_upstream_rr_peer_t *peer;
! 635:
! 636: ssl_session = ngx_ssl_get_session(pc->connection);
! 637:
! 638: if (ssl_session == NULL) {
! 639: return;
! 640: }
! 641:
! 642: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 643: "save session: %p:%d", ssl_session, ssl_session->references);
! 644:
! 645: peer = &rrp->peers->peer[rrp->current];
! 646:
! 647: /* TODO: threads only mutex */
! 648: /* ngx_lock_mutex(rrp->peers->mutex); */
! 649:
! 650: old_ssl_session = peer->ssl_session;
! 651: peer->ssl_session = ssl_session;
! 652:
! 653: /* ngx_unlock_mutex(rrp->peers->mutex); */
! 654:
! 655: if (old_ssl_session) {
! 656:
! 657: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
! 658: "old session: %p:%d",
! 659: old_ssl_session, old_ssl_session->references);
! 660:
! 661: /* TODO: may block */
! 662:
! 663: ngx_ssl_free_session(old_ssl_session);
! 664: }
! 665: }
! 666:
! 667:
! 668: static ngx_int_t
! 669: ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data)
! 670: {
! 671: return NGX_OK;
! 672: }
! 673:
! 674:
! 675: static void
! 676: ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data)
! 677: {
! 678: return;
! 679: }
! 680:
! 681: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>