static ngx_int_t ngx_http_vhost_traffic_status_dump_restore_add_node(ngx_event_t *ev, ngx_http_vhost_traffic_status_node_t *ovtsn, ngx_str_t *key) { size_t size; uint32_t hash; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_http_vhost_traffic_status_ctx_t *ctx; ngx_http_vhost_traffic_status_node_t *vtsn; ctx = ev->data; if (key->len == 0) { return NGX_ERROR; } shpool = (ngx_slab_pool_t *) ctx->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); /* find node */ hash = ngx_crc32_short(key->data, key->len); node = ngx_http_vhost_traffic_status_node_lookup(ctx->rbtree, key, hash); /* copy node */ if (node == NULL) { size = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_vhost_traffic_status_node_t, data) + key->len; node = ngx_slab_alloc_locked(shpool, size); if (node == NULL) { ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "dump_restore_add_node::ngx_slab_alloc_locked() failed"); ngx_shmtx_unlock(&shpool->mutex); return NGX_ERROR; } vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; node->key = hash; *vtsn = *ovtsn; ngx_memcpy(vtsn->data, key->data, key->len); ngx_rbtree_insert(ctx->rbtree, node); } ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; }
static ngx_int_t ngx_http_vhost_traffic_status_shm_add_upstream(ngx_http_request_t *r, ngx_http_vhost_traffic_status_ctx_t *ctx, ngx_http_core_srv_conf_t *cscf, ngx_http_vhost_traffic_status_loc_conf_t *vtscf) { u_char *p; size_t size; uint32_t hash; ngx_uint_t i; ngx_msec_int_t ms; ngx_str_t key; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_http_vhost_traffic_status_node_t *vtsn; ngx_http_upstream_srv_conf_t *uscf; ngx_http_upstream_t *u; ngx_http_upstream_state_t *state; if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { return NGX_OK; } u = r->upstream; if (u->resolved == NULL) { uscf = u->conf->upstream; } else { return NGX_ERROR; } state = r->upstream_states->elts; i = 0; ms = 0; for ( ;; ) { if (state[i].status) { ms += (ngx_msec_int_t) (state[i].response_sec * 1000 + state[i].response_msec); } if (++i == r->upstream_states->nelts) { break; } } ms = ngx_max(ms, 0); shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; key.len = (uscf->port ? 0 : uscf->host.len) + sizeof("@") - 1 + state[0].peer->len; key.data = ngx_pnalloc(r->pool, key.len); if (key.data == NULL) { return NGX_ERROR; } p = key.data; if (uscf->port) { *p++ = '@'; p = ngx_cpymem(p, state[0].peer->data, state[0].peer->len); } else { p = ngx_cpymem(p, uscf->host.data, uscf->host.len); *p++ = '@'; p = ngx_cpymem(p, state[0].peer->data, state[0].peer->len); } hash = ngx_crc32_short(key.data, key.len); if (vtscf->vtsn_upstream && vtscf->vtsn_hash == hash) { ngx_shmtx_lock(&shpool->mutex); ngx_vhost_traffic_status_node_set(r, vtscf->vtsn_upstream); vtscf->vtsn_upstream->stat_upstream.rtms = (ngx_msec_t) (vtscf->vtsn_upstream->stat_upstream.rtms + ms) / 2 + (vtscf->vtsn_upstream->stat_upstream.rtms + ms) % 2; ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; } ngx_shmtx_lock(&shpool->mutex); node = ngx_http_vhost_traffic_status_node_lookup(ctx->rbtree, &key, hash); if (node == NULL) { size = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_vhost_traffic_status_node_t, data) + key.len; node = ngx_slab_alloc_locked(shpool, size); if (node == NULL) { ngx_shmtx_unlock(&shpool->mutex); return NGX_ERROR; } vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; node->key = hash; vtsn->len = (u_char) key.len; ngx_vhost_traffic_status_node_init(r, vtsn); vtsn->stat_upstream.rtms = ms; vtsn->stat_upstream.type = uscf->port ? NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UA : NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UG; ngx_memcpy(vtsn->data, key.data, key.len); ngx_rbtree_insert(ctx->rbtree, node); } else { vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; ngx_vhost_traffic_status_node_set(r, vtsn); vtsn->stat_upstream.rtms = (ngx_msec_t) (vtsn->stat_upstream.rtms + ms) / 2 + (vtsn->stat_upstream.rtms + ms) % 2; } vtscf->vtsn_upstream = vtsn; vtscf->vtsn_hash = hash; ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; }
static u_char * ngx_http_vhost_traffic_status_display_set_upstream_group(ngx_http_request_t *r, ngx_rbtree_t *rbtree, const char *fmt, u_char *buf, ngx_http_vhost_traffic_status_loc_conf_t *vtscf) { size_t len; u_char *p, *o, *s; uint32_t hash; ngx_uint_t i, j; ngx_str_t key; ngx_rbtree_node_t *node; ngx_http_upstream_server_t *us; ngx_http_upstream_main_conf_t *umcf; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_vhost_traffic_status_node_t *vtsn; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); uscfp = umcf->upstreams.elts; len = 0; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; len = ngx_max(uscf->host.len, len); } key.len = len + sizeof("@[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]:65535") - 1; key.data = ngx_pnalloc(r->pool, key.len); if (key.data == NULL) { return buf; } p = key.data; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; /* groups */ if (uscf->servers && !uscf->port) { us = uscf->servers->elts; o = buf; buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_ARRAY_S, &uscf->host); s = buf; for (j = 0; j < uscf->servers->nelts; j++) { p = ngx_cpymem(p, uscf->host.data, uscf->host.len); *p++ = '@'; p = ngx_cpymem(p, us[j].addrs->name.data, us[j].addrs->name.len); key.len = uscf->host.len + sizeof("@") - 1 + us[j].addrs->name.len; hash = ngx_crc32_short(key.data, key.len); node = ngx_http_vhost_traffic_status_node_lookup(rbtree, &key, hash); if (node != NULL) { vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; buf = ngx_sprintf(buf, fmt, &us[j].addrs->name, vtsn->stat_request_counter, vtsn->stat_in_bytes, vtsn->stat_out_bytes, vtsn->stat_1xx_counter, vtsn->stat_2xx_counter, vtsn->stat_3xx_counter, vtsn->stat_4xx_counter, vtsn->stat_5xx_counter, vtsn->stat_upstream.rtms, us[j].weight, us[j].max_fails, us[j].fail_timeout, ngx_vhost_traffic_status_boolean_to_string(us[j].backup), ngx_vhost_traffic_status_boolean_to_string(us[j].down)); } else { buf = ngx_sprintf(buf, fmt, &us[j].addrs->name, 0, 0, 0, 0, 0, 0, 0, 0, (ngx_msec_t) 0, us[j].weight, us[j].max_fails, us[j].fail_timeout, ngx_vhost_traffic_status_boolean_to_string(us[j].backup), ngx_vhost_traffic_status_boolean_to_string(us[j].down)); } p = key.data; } if (s == buf) { buf = o; } else { buf--; buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_ARRAY_E); buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_NEXT); } } } /* alones */ o = buf; ngx_str_set(&key, "::nogroups"); buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_ARRAY_S, &key); s = buf; buf = ngx_http_vhost_traffic_status_display_set_upstream_alone(r, rbtree->root, rbtree->sentinel, fmt, buf, vtscf); if (s == buf) { buf = o; } else { buf--; buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_ARRAY_E); buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_NEXT); } return buf; }
static ngx_int_t ngx_http_vhost_traffic_status_shm_add_server(ngx_http_request_t *r, ngx_http_vhost_traffic_status_ctx_t *ctx, ngx_http_core_srv_conf_t *cscf, ngx_http_vhost_traffic_status_loc_conf_t *vtscf) { size_t size; uint32_t hash; ngx_str_t key; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_http_vhost_traffic_status_node_t *vtsn; shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; if (vtscf->vtsn_server) { ngx_shmtx_lock(&shpool->mutex); ngx_vhost_traffic_status_node_set(r, vtscf->vtsn_server); ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; } key = cscf->server_name; hash = ngx_crc32_short(key.data, key.len); ngx_shmtx_lock(&shpool->mutex); node = ngx_http_vhost_traffic_status_node_lookup(ctx->rbtree, &key, hash); if (node == NULL) { size = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_vhost_traffic_status_node_t, data) + key.len; node = ngx_slab_alloc_locked(shpool, size); if (node == NULL) { ngx_shmtx_unlock(&shpool->mutex); return NGX_ERROR; } vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; node->key = hash; vtsn->len = (u_char) key.len; ngx_vhost_traffic_status_node_init(r, vtsn); ngx_memcpy(vtsn->data, key.data, key.len); ngx_rbtree_insert(ctx->rbtree, node); } else { vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; ngx_vhost_traffic_status_node_set(r, vtsn); } vtscf->vtsn_server = vtsn; ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; }