LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_balancer.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 0 286 0.0 %
Date: 2020-03-03 04:25:50 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Yichun Zhang (agentzh)
       4             :  */
       5             : 
       6             : 
       7             : #ifndef DDEBUG
       8             : #define DDEBUG 0
       9             : #endif
      10             : #include "ddebug.h"
      11             : 
      12             : 
      13             : #include "ngx_http_lua_cache.h"
      14             : #include "ngx_http_lua_balancer.h"
      15             : #include "ngx_http_lua_util.h"
      16             : #include "ngx_http_lua_directive.h"
      17             : 
      18             : 
      19             : struct ngx_http_lua_balancer_peer_data_s {
      20             :     /* the round robin data must be first */
      21             :     ngx_http_upstream_rr_peer_data_t    rrp;
      22             : 
      23             :     ngx_http_lua_srv_conf_t            *conf;
      24             :     ngx_http_request_t                 *request;
      25             : 
      26             :     ngx_uint_t                          more_tries;
      27             :     ngx_uint_t                          total_tries;
      28             : 
      29             :     struct sockaddr                    *sockaddr;
      30             :     socklen_t                           socklen;
      31             : 
      32             :     ngx_str_t                          *host;
      33             :     in_port_t                           port;
      34             : 
      35             :     int                                 last_peer_state;
      36             : 
      37             : #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
      38             :     unsigned                            cloned_upstream_conf;  /* :1 */
      39             : #endif
      40             : };
      41             : 
      42             : 
      43             : #if (NGX_HTTP_SSL)
      44             : static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc,
      45             :     void *data);
      46             : static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc,
      47             :     void *data);
      48             : #endif
      49             : static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf,
      50             :     ngx_http_upstream_srv_conf_t *us);
      51             : static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r,
      52             :     ngx_http_upstream_srv_conf_t *us);
      53             : static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc,
      54             :     void *data);
      55             : static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L,
      56             :     ngx_http_request_t *r);
      57             : void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data,
      58             :     ngx_uint_t state);
      59             : 
      60             : 
      61             : ngx_int_t
      62           0 : ngx_http_lua_balancer_handler_file(ngx_http_request_t *r,
      63             :     ngx_http_lua_srv_conf_t *lscf, lua_State *L)
      64             : {
      65             :     ngx_int_t           rc;
      66             : 
      67           0 :     rc = ngx_http_lua_cache_loadfile(r->connection->log, L,
      68           0 :                                      lscf->balancer.src.data,
      69           0 :                                      lscf->balancer.src_key);
      70           0 :     if (rc != NGX_OK) {
      71           0 :         return rc;
      72             :     }
      73             : 
      74             :     /*  make sure we have a valid code chunk */
      75           0 :     ngx_http_lua_assert(lua_isfunction(L, -1));
      76             : 
      77           0 :     return ngx_http_lua_balancer_by_chunk(L, r);
      78             : }
      79             : 
      80             : 
      81             : ngx_int_t
      82           0 : ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r,
      83             :     ngx_http_lua_srv_conf_t *lscf, lua_State *L)
      84             : {
      85             :     ngx_int_t           rc;
      86             : 
      87           0 :     rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L,
      88           0 :                                        lscf->balancer.src.data,
      89             :                                        lscf->balancer.src.len,
      90           0 :                                        lscf->balancer.src_key,
      91             :                                        "=balancer_by_lua");
      92           0 :     if (rc != NGX_OK) {
      93           0 :         return rc;
      94             :     }
      95             : 
      96             :     /*  make sure we have a valid code chunk */
      97           0 :     ngx_http_lua_assert(lua_isfunction(L, -1));
      98             : 
      99           0 :     return ngx_http_lua_balancer_by_chunk(L, r);
     100             : }
     101             : 
     102             : 
     103             : char *
     104           0 : ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
     105             :     void *conf)
     106             : {
     107             :     char        *rv;
     108             :     ngx_conf_t   save;
     109             : 
     110           0 :     save = *cf;
     111           0 :     cf->handler = ngx_http_lua_balancer_by_lua;
     112           0 :     cf->handler_conf = conf;
     113             : 
     114           0 :     rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
     115             : 
     116           0 :     *cf = save;
     117             : 
     118           0 :     return rv;
     119             : }
     120             : 
     121             : 
     122             : char *
     123           0 : ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
     124             :     void *conf)
     125             : {
     126             :     u_char                      *p;
     127             :     u_char                      *name;
     128             :     ngx_str_t                   *value;
     129           0 :     ngx_http_lua_srv_conf_t     *lscf = conf;
     130             : 
     131             :     ngx_http_upstream_srv_conf_t      *uscf;
     132             : 
     133             :     dd("enter");
     134             : 
     135             :     /*  must specify a content handler */
     136           0 :     if (cmd->post == NULL) {
     137           0 :         return NGX_CONF_ERROR;
     138             :     }
     139             : 
     140           0 :     if (lscf->balancer.handler) {
     141           0 :         return "is duplicate";
     142             :     }
     143             : 
     144           0 :     value = cf->args->elts;
     145             : 
     146           0 :     lscf->balancer.handler = (ngx_http_lua_srv_conf_handler_pt) cmd->post;
     147             : 
     148           0 :     if (cmd->post == ngx_http_lua_balancer_handler_file) {
     149             :         /* Lua code in an external file */
     150             : 
     151           0 :         name = ngx_http_lua_rebase_path(cf->pool, value[1].data,
     152           0 :                                         value[1].len);
     153           0 :         if (name == NULL) {
     154           0 :             return NGX_CONF_ERROR;
     155             :         }
     156             : 
     157           0 :         lscf->balancer.src.data = name;
     158           0 :         lscf->balancer.src.len = ngx_strlen(name);
     159             : 
     160           0 :         p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
     161           0 :         if (p == NULL) {
     162           0 :             return NGX_CONF_ERROR;
     163             :         }
     164             : 
     165           0 :         lscf->balancer.src_key = p;
     166             : 
     167           0 :         p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
     168           0 :         p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
     169           0 :         *p = '\0';
     170             : 
     171             :     } else {
     172             :         /* inlined Lua code */
     173             : 
     174           0 :         lscf->balancer.src = value[1];
     175             : 
     176           0 :         p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
     177           0 :         if (p == NULL) {
     178           0 :             return NGX_CONF_ERROR;
     179             :         }
     180             : 
     181           0 :         lscf->balancer.src_key = p;
     182             : 
     183           0 :         p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
     184           0 :         p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
     185           0 :         *p = '\0';
     186             :     }
     187             : 
     188           0 :     uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
     189             : 
     190           0 :     if (uscf->peer.init_upstream) {
     191           0 :         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
     192             :                            "load balancing method redefined");
     193             :     }
     194             : 
     195           0 :     uscf->peer.init_upstream = ngx_http_lua_balancer_init;
     196             : 
     197           0 :     uscf->flags = NGX_HTTP_UPSTREAM_CREATE
     198             :                   |NGX_HTTP_UPSTREAM_WEIGHT
     199             :                   |NGX_HTTP_UPSTREAM_MAX_FAILS
     200             :                   |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
     201             :                   |NGX_HTTP_UPSTREAM_DOWN;
     202             : 
     203           0 :     return NGX_CONF_OK;
     204             : }
     205             : 
     206             : 
     207             : static ngx_int_t
     208           0 : ngx_http_lua_balancer_init(ngx_conf_t *cf,
     209             :     ngx_http_upstream_srv_conf_t *us)
     210             : {
     211           0 :     if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
     212           0 :         return NGX_ERROR;
     213             :     }
     214             : 
     215             :     /* this callback is called upon individual requests */
     216           0 :     us->peer.init = ngx_http_lua_balancer_init_peer;
     217             : 
     218           0 :     return NGX_OK;
     219             : }
     220             : 
     221             : 
     222             : static ngx_int_t
     223           0 : ngx_http_lua_balancer_init_peer(ngx_http_request_t *r,
     224             :     ngx_http_upstream_srv_conf_t *us)
     225             : {
     226             :     ngx_http_lua_srv_conf_t            *bcf;
     227             :     ngx_http_lua_balancer_peer_data_t  *bp;
     228             : 
     229           0 :     bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t));
     230           0 :     if (bp == NULL) {
     231           0 :         return NGX_ERROR;
     232             :     }
     233             : 
     234           0 :     r->upstream->peer.data = &bp->rrp;
     235             : 
     236           0 :     if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
     237           0 :         return NGX_ERROR;
     238             :     }
     239             : 
     240           0 :     r->upstream->peer.get = ngx_http_lua_balancer_get_peer;
     241           0 :     r->upstream->peer.free = ngx_http_lua_balancer_free_peer;
     242             : 
     243             : #if (NGX_HTTP_SSL)
     244           0 :     r->upstream->peer.set_session = ngx_http_lua_balancer_set_session;
     245           0 :     r->upstream->peer.save_session = ngx_http_lua_balancer_save_session;
     246             : #endif
     247             : 
     248           0 :     bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module);
     249             : 
     250           0 :     bp->conf = bcf;
     251           0 :     bp->request = r;
     252             : 
     253           0 :     return NGX_OK;
     254             : }
     255             : 
     256             : 
     257             : static ngx_int_t
     258           0 : ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data)
     259             : {
     260             :     lua_State                          *L;
     261             :     ngx_int_t                           rc;
     262             :     ngx_http_request_t                 *r;
     263             :     ngx_http_lua_ctx_t                 *ctx;
     264             :     ngx_http_lua_srv_conf_t            *lscf;
     265             :     ngx_http_lua_main_conf_t           *lmcf;
     266           0 :     ngx_http_lua_balancer_peer_data_t  *bp = data;
     267             : 
     268           0 :     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
     269             :                    "lua balancer peer, tries: %ui", pc->tries);
     270             : 
     271           0 :     lscf = bp->conf;
     272             : 
     273           0 :     r = bp->request;
     274             : 
     275           0 :     ngx_http_lua_assert(lscf->balancer.handler && r);
     276             : 
     277           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     278             : 
     279           0 :     if (ctx == NULL) {
     280           0 :         ctx = ngx_http_lua_create_ctx(r);
     281           0 :         if (ctx == NULL) {
     282           0 :             return NGX_ERROR;
     283             :         }
     284             : 
     285           0 :         L = ngx_http_lua_get_lua_vm(r, ctx);
     286             : 
     287             :     } else {
     288           0 :         L = ngx_http_lua_get_lua_vm(r, ctx);
     289             : 
     290             :         dd("reset ctx");
     291           0 :         ngx_http_lua_reset_ctx(r, L, ctx);
     292             :     }
     293             : 
     294           0 :     ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER;
     295             : 
     296           0 :     bp->sockaddr = NULL;
     297           0 :     bp->socklen = 0;
     298           0 :     bp->more_tries = 0;
     299           0 :     bp->total_tries++;
     300             : 
     301           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     302             : 
     303             :     /* balancer_by_lua does not support yielding and
     304             :      * there cannot be any conflicts among concurrent requests,
     305             :      * thus it is safe to store the peer data in the main conf.
     306             :      */
     307           0 :     lmcf->balancer_peer_data = bp;
     308             : 
     309           0 :     rc = lscf->balancer.handler(r, lscf, L);
     310             : 
     311           0 :     if (rc == NGX_ERROR) {
     312           0 :         return NGX_ERROR;
     313             :     }
     314             : 
     315           0 :     if (ctx->exited && ctx->exit_code != NGX_OK) {
     316           0 :         rc = ctx->exit_code;
     317           0 :         if (rc == NGX_ERROR
     318           0 :             || rc == NGX_BUSY
     319           0 :             || rc == NGX_DECLINED
     320             : #ifdef HAVE_BALANCER_STATUS_CODE_PATCH
     321           0 :             || rc >= NGX_HTTP_SPECIAL_RESPONSE
     322             : #endif
     323             :         ) {
     324           0 :             return rc;
     325             :         }
     326             : 
     327           0 :         if (rc > NGX_OK) {
     328           0 :             return NGX_ERROR;
     329             :         }
     330             :     }
     331             : 
     332           0 :     if (bp->sockaddr && bp->socklen) {
     333           0 :         pc->sockaddr = bp->sockaddr;
     334           0 :         pc->socklen = bp->socklen;
     335           0 :         pc->cached = 0;
     336           0 :         pc->connection = NULL;
     337           0 :         pc->name = bp->host;
     338             : 
     339           0 :         bp->rrp.peers->single = 0;
     340             : 
     341           0 :         if (bp->more_tries) {
     342           0 :             r->upstream->peer.tries += bp->more_tries;
     343             :         }
     344             : 
     345             :         dd("tries: %d", (int) r->upstream->peer.tries);
     346             : 
     347           0 :         return NGX_OK;
     348             :     }
     349             : 
     350           0 :     return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp);
     351             : }
     352             : 
     353             : 
     354             : static ngx_int_t
     355           0 : ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r)
     356             : {
     357             :     u_char                  *err_msg;
     358             :     size_t                   len;
     359             :     ngx_int_t                rc;
     360             : 
     361             :     /* init nginx context in Lua VM */
     362           0 :     ngx_http_lua_set_req(L, r);
     363           0 :     ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */);
     364             : 
     365             :     /*  {{{ make new env inheriting main thread's globals table */
     366           0 :     lua_createtable(L, 0, 1 /* nrec */);   /* the metatable for the new env */
     367           0 :     ngx_http_lua_get_globals_table(L);
     368           0 :     lua_setfield(L, -2, "__index");
     369           0 :     lua_setmetatable(L, -2);    /*  setmetatable({}, {__index = _G}) */
     370             :     /*  }}} */
     371             : 
     372           0 :     lua_setfenv(L, -2);    /*  set new running env for the code closure */
     373             : 
     374           0 :     lua_pushcfunction(L, ngx_http_lua_traceback);
     375           0 :     lua_insert(L, 1);  /* put it under chunk and args */
     376             : 
     377             :     /*  protected call user code */
     378           0 :     rc = lua_pcall(L, 0, 1, 1);
     379             : 
     380           0 :     lua_remove(L, 1);  /* remove traceback function */
     381             : 
     382             :     dd("rc == %d", (int) rc);
     383             : 
     384           0 :     if (rc != 0) {
     385             :         /*  error occurred when running loaded code */
     386           0 :         err_msg = (u_char *) lua_tolstring(L, -1, &len);
     387             : 
     388           0 :         if (err_msg == NULL) {
     389           0 :             err_msg = (u_char *) "unknown reason";
     390           0 :             len = sizeof("unknown reason") - 1;
     391             :         }
     392             : 
     393           0 :         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
     394             :                       "failed to run balancer_by_lua*: %*s", len, err_msg);
     395             : 
     396           0 :         lua_settop(L, 0); /*  clear remaining elems on stack */
     397             : 
     398           0 :         return NGX_ERROR;
     399             :     }
     400             : 
     401           0 :     lua_settop(L, 0); /*  clear remaining elems on stack */
     402           0 :     return rc;
     403             : }
     404             : 
     405             : 
     406             : void
     407           0 : ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data,
     408             :     ngx_uint_t state)
     409             : {
     410           0 :     ngx_http_lua_balancer_peer_data_t  *bp = data;
     411             : 
     412           0 :     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
     413             :                    "lua balancer free peer, tries: %ui", pc->tries);
     414             : 
     415           0 :     if (bp->sockaddr && bp->socklen) {
     416           0 :         bp->last_peer_state = (int) state;
     417             : 
     418           0 :         if (pc->tries) {
     419           0 :             pc->tries--;
     420             :         }
     421             : 
     422           0 :         return;
     423             :     }
     424             : 
     425             :     /* fallback */
     426             : 
     427           0 :     ngx_http_upstream_free_round_robin_peer(pc, data, state);
     428             : }
     429             : 
     430             : 
     431             : #if (NGX_HTTP_SSL)
     432             : 
     433             : static ngx_int_t
     434           0 : ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data)
     435             : {
     436           0 :     ngx_http_lua_balancer_peer_data_t  *bp = data;
     437             : 
     438           0 :     if (bp->sockaddr && bp->socklen) {
     439             :         /* TODO */
     440           0 :         return NGX_OK;
     441             :     }
     442             : 
     443           0 :     return ngx_http_upstream_set_round_robin_peer_session(pc, &bp->rrp);
     444             : }
     445             : 
     446             : 
     447             : static void
     448           0 : ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data)
     449             : {
     450           0 :     ngx_http_lua_balancer_peer_data_t  *bp = data;
     451             : 
     452           0 :     if (bp->sockaddr && bp->socklen) {
     453             :         /* TODO */
     454           0 :         return;
     455             :     }
     456             : 
     457           0 :     ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp);
     458           0 :     return;
     459             : }
     460             : 
     461             : #endif
     462             : 
     463             : 
     464             : #ifndef NGX_LUA_NO_FFI_API
     465             : 
     466             : int
     467           0 : ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r,
     468             :     const u_char *addr, size_t addr_len, int port, char **err)
     469             : {
     470             :     ngx_url_t              url;
     471             :     ngx_http_lua_ctx_t    *ctx;
     472             :     ngx_http_upstream_t   *u;
     473             : 
     474             :     ngx_http_lua_main_conf_t           *lmcf;
     475             :     ngx_http_lua_balancer_peer_data_t  *bp;
     476             : 
     477           0 :     if (r == NULL) {
     478           0 :         *err = "no request found";
     479           0 :         return NGX_ERROR;
     480             :     }
     481             : 
     482           0 :     u = r->upstream;
     483             : 
     484           0 :     if (u == NULL) {
     485           0 :         *err = "no upstream found";
     486           0 :         return NGX_ERROR;
     487             :     }
     488             : 
     489           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     490           0 :     if (ctx == NULL) {
     491           0 :         *err = "no ctx found";
     492           0 :         return NGX_ERROR;
     493             :     }
     494             : 
     495           0 :     if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) {
     496           0 :         *err = "API disabled in the current context";
     497           0 :         return NGX_ERROR;
     498             :     }
     499             : 
     500           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     501             : 
     502             :     /* we cannot read r->upstream->peer.data here directly because
     503             :      * it could be overridden by other modules like
     504             :      * ngx_http_upstream_keepalive_module.
     505             :      */
     506           0 :     bp = lmcf->balancer_peer_data;
     507           0 :     if (bp == NULL) {
     508           0 :         *err = "no upstream peer data found";
     509           0 :         return NGX_ERROR;
     510             :     }
     511             : 
     512           0 :     ngx_memzero(&url, sizeof(ngx_url_t));
     513             : 
     514           0 :     url.url.data = ngx_palloc(r->pool, addr_len);
     515           0 :     if (url.url.data == NULL) {
     516           0 :         *err = "no memory";
     517           0 :         return NGX_ERROR;
     518             :     }
     519             : 
     520           0 :     ngx_memcpy(url.url.data, addr, addr_len);
     521             : 
     522           0 :     url.url.len = addr_len;
     523           0 :     url.default_port = (in_port_t) port;
     524           0 :     url.uri_part = 0;
     525           0 :     url.no_resolve = 1;
     526             : 
     527           0 :     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
     528           0 :         if (url.err) {
     529           0 :             *err = url.err;
     530             :         }
     531             : 
     532           0 :         return NGX_ERROR;
     533             :     }
     534             : 
     535           0 :     if (url.addrs && url.addrs[0].sockaddr) {
     536           0 :         bp->sockaddr = url.addrs[0].sockaddr;
     537           0 :         bp->socklen = url.addrs[0].socklen;
     538           0 :         bp->host = &url.addrs[0].name;
     539             : 
     540             :     } else {
     541           0 :         *err = "no host allowed";
     542           0 :         return NGX_ERROR;
     543             :     }
     544             : 
     545           0 :     return NGX_OK;
     546             : }
     547             : 
     548             : 
     549             : int
     550           0 : ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r,
     551             :     long connect_timeout, long send_timeout, long read_timeout,
     552             :     char **err)
     553             : {
     554             :     ngx_http_lua_ctx_t    *ctx;
     555             :     ngx_http_upstream_t   *u;
     556             : 
     557             : #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
     558             :     ngx_http_upstream_conf_t           *ucf;
     559             : #endif
     560             :     ngx_http_lua_main_conf_t           *lmcf;
     561             :     ngx_http_lua_balancer_peer_data_t  *bp;
     562             : 
     563           0 :     if (r == NULL) {
     564           0 :         *err = "no request found";
     565           0 :         return NGX_ERROR;
     566             :     }
     567             : 
     568           0 :     u = r->upstream;
     569             : 
     570           0 :     if (u == NULL) {
     571           0 :         *err = "no upstream found";
     572           0 :         return NGX_ERROR;
     573             :     }
     574             : 
     575           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     576           0 :     if (ctx == NULL) {
     577           0 :         *err = "no ctx found";
     578           0 :         return NGX_ERROR;
     579             :     }
     580             : 
     581           0 :     if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) {
     582           0 :         *err = "API disabled in the current context";
     583           0 :         return NGX_ERROR;
     584             :     }
     585             : 
     586           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     587             : 
     588           0 :     bp = lmcf->balancer_peer_data;
     589           0 :     if (bp == NULL) {
     590           0 :         *err = "no upstream peer data found";
     591           0 :         return NGX_ERROR;
     592             :     }
     593             : 
     594             : #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
     595             :     if (!bp->cloned_upstream_conf) {
     596             :         /* we clone the upstream conf for the current request so that
     597             :          * we do not affect other requests at all. */
     598             : 
     599             :         ucf = ngx_palloc(r->pool, sizeof(ngx_http_upstream_conf_t));
     600             : 
     601             :         if (ucf == NULL) {
     602             :             *err = "no memory";
     603             :             return NGX_ERROR;
     604             :         }
     605             : 
     606             :         ngx_memcpy(ucf, u->conf, sizeof(ngx_http_upstream_conf_t));
     607             : 
     608             :         u->conf = ucf;
     609             :         bp->cloned_upstream_conf = 1;
     610             : 
     611             :     } else {
     612             :         ucf = u->conf;
     613             :     }
     614             : #endif
     615             : 
     616           0 :     if (connect_timeout > 0) {
     617             : #if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
     618           0 :         u->connect_timeout = (ngx_msec_t) connect_timeout;
     619             : #else
     620             :         ucf->connect_timeout = (ngx_msec_t) connect_timeout;
     621             : #endif
     622             :     }
     623             : 
     624           0 :     if (send_timeout > 0) {
     625             : #if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
     626           0 :         u->send_timeout = (ngx_msec_t) send_timeout;
     627             : #else
     628             :         ucf->send_timeout = (ngx_msec_t) send_timeout;
     629             : #endif
     630             :     }
     631             : 
     632           0 :     if (read_timeout > 0) {
     633             : #if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS)
     634           0 :         u->read_timeout = (ngx_msec_t) read_timeout;
     635             : #else
     636             :         ucf->read_timeout = (ngx_msec_t) read_timeout;
     637             : #endif
     638             :     }
     639             : 
     640           0 :     return NGX_OK;
     641             : }
     642             : 
     643             : 
     644             : int
     645           0 : ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r,
     646             :     int count, char **err)
     647             : {
     648             : #if (nginx_version >= 1007005)
     649             :     ngx_uint_t             max_tries, total;
     650             : #endif
     651             :     ngx_http_lua_ctx_t    *ctx;
     652             :     ngx_http_upstream_t   *u;
     653             : 
     654             :     ngx_http_lua_main_conf_t           *lmcf;
     655             :     ngx_http_lua_balancer_peer_data_t  *bp;
     656             : 
     657           0 :     if (r == NULL) {
     658           0 :         *err = "no request found";
     659           0 :         return NGX_ERROR;
     660             :     }
     661             : 
     662           0 :     u = r->upstream;
     663             : 
     664           0 :     if (u == NULL) {
     665           0 :         *err = "no upstream found";
     666           0 :         return NGX_ERROR;
     667             :     }
     668             : 
     669           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     670           0 :     if (ctx == NULL) {
     671           0 :         *err = "no ctx found";
     672           0 :         return NGX_ERROR;
     673             :     }
     674             : 
     675           0 :     if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) {
     676           0 :         *err = "API disabled in the current context";
     677           0 :         return NGX_ERROR;
     678             :     }
     679             : 
     680           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     681             : 
     682           0 :     bp = lmcf->balancer_peer_data;
     683           0 :     if (bp == NULL) {
     684           0 :         *err = "no upstream peer data found";
     685           0 :         return NGX_ERROR;
     686             :     }
     687             : 
     688             : #if (nginx_version >= 1007005)
     689           0 :     max_tries = r->upstream->conf->next_upstream_tries;
     690           0 :     total = bp->total_tries + r->upstream->peer.tries - 1;
     691             : 
     692           0 :     if (max_tries && total + count > max_tries) {
     693           0 :         count = max_tries - total;
     694           0 :         *err = "reduced tries due to limit";
     695             : 
     696             :     } else {
     697           0 :         *err = NULL;
     698             :     }
     699             : #else
     700             :     *err = NULL;
     701             : #endif
     702             : 
     703           0 :     bp->more_tries = count;
     704           0 :     return NGX_OK;
     705             : }
     706             : 
     707             : 
     708             : int
     709           0 : ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r,
     710             :     int *status, char **err)
     711             : {
     712             :     ngx_http_lua_ctx_t         *ctx;
     713             :     ngx_http_upstream_t        *u;
     714             :     ngx_http_upstream_state_t  *state;
     715             : 
     716             :     ngx_http_lua_balancer_peer_data_t  *bp;
     717             :     ngx_http_lua_main_conf_t           *lmcf;
     718             : 
     719           0 :     if (r == NULL) {
     720           0 :         *err = "no request found";
     721           0 :         return NGX_ERROR;
     722             :     }
     723             : 
     724           0 :     u = r->upstream;
     725             : 
     726           0 :     if (u == NULL) {
     727           0 :         *err = "no upstream found";
     728           0 :         return NGX_ERROR;
     729             :     }
     730             : 
     731           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     732           0 :     if (ctx == NULL) {
     733           0 :         *err = "no ctx found";
     734           0 :         return NGX_ERROR;
     735             :     }
     736             : 
     737           0 :     if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) {
     738           0 :         *err = "API disabled in the current context";
     739           0 :         return NGX_ERROR;
     740             :     }
     741             : 
     742           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     743             : 
     744           0 :     bp = lmcf->balancer_peer_data;
     745           0 :     if (bp == NULL) {
     746           0 :         *err = "no upstream peer data found";
     747           0 :         return NGX_ERROR;
     748             :     }
     749             : 
     750           0 :     if (r->upstream_states && r->upstream_states->nelts > 1) {
     751           0 :         state = r->upstream_states->elts;
     752           0 :         *status = (int) state[r->upstream_states->nelts - 2].status;
     753             : 
     754             :     } else {
     755           0 :         *status = 0;
     756             :     }
     757             : 
     758           0 :     return bp->last_peer_state;
     759             : }
     760             : 
     761             : #endif  /* NGX_LUA_NO_FFI_API */

Generated by: LCOV version 1.13