static ngx_int_t 
ngx_tcp_check_init_process(ngx_cycle_t *cycle) 
{
    ngx_str_t                      shm_name;
    ngx_uint_t                     i;
    ngx_msec_t                     t, delay;
    check_conf_t                  *cf;
    ngx_shm_zone_t                *shm_zone;
    ngx_tcp_check_peer_shm_t      *peer_shm;
    ngx_tcp_check_peers_shm_t     *peers_shm;
    ngx_tcp_check_peer_conf_t     *peer_conf;
    ngx_tcp_check_peers_conf_t    *peers_conf;
    ngx_tcp_upstream_srv_conf_t   *uscf;

    if (ngx_tcp_check_get_shm_name(&shm_name, cycle->pool) == NGX_ERROR) {
        return NGX_ERROR;
    }

    shm_zone = ngx_shared_memory_find(cycle, &shm_name, &ngx_tcp_upstream_module);

    if (shm_zone == NULL || shm_zone->data == NULL) {
        return NGX_OK;
    }

    peers_conf = shm_zone->data;
    peers_shm = peers_conf->peers_shm;

    ngx_log_debug2(NGX_LOG_DEBUG_TCP, cycle->log, 0, 
            "tcp check upstream init_process, shm_name: %V, peer number: %ud",
            &shm_name, peers_conf->peers.nelts);

    srand(ngx_pid);

    peer_conf = peers_conf->peers.elts;
    peer_shm = peers_shm->peers;

    for (i = 0; i < peers_conf->peers.nelts; i++) {
        peer_conf[i].shm = &peer_shm[i];

        peer_conf[i].check_ev.handler = ngx_tcp_check_begin_handler;
        peer_conf[i].check_ev.log = cycle->log;
        peer_conf[i].check_ev.data = &peer_conf[i];
        peer_conf[i].check_ev.timer_set = 0;

        peer_conf[i].check_timeout_ev.handler = ngx_tcp_check_timeout_handler;
        peer_conf[i].check_timeout_ev.log = cycle->log;
        peer_conf[i].check_timeout_ev.data = &peer_conf[i];
        peer_conf[i].check_timeout_ev.timer_set = 0;

        uscf = peer_conf[i].conf;
        cf = uscf->check_type_conf;

        if (cf->need_pool) {
            peer_conf[i].pool = ngx_create_pool(ngx_pagesize, cycle->log);
            if (peer_conf[i].pool == NULL) {
                return NGX_ERROR;
            }
        }

        peer_conf[i].send_handler = cf->send_handler;
        peer_conf[i].recv_handler = cf->recv_handler;

        peer_conf[i].init = cf->init;
        peer_conf[i].parse = cf->parse;
        peer_conf[i].reinit = cf->reinit;

        /* Default delay interval is 1 second. 
           I don't want to trigger the check event too close. */
        delay = uscf->check_interval > 1000 ? uscf->check_interval : 1000;
        t = ngx_random() % delay;

        ngx_add_timer(&peer_conf[i].check_ev, t);
    }

    return NGX_OK;
}
static ngx_int_t 
ngx_tcp_upstream_check_status_handler(ngx_http_request_t *r) 
{
    ngx_buf_t                     *b;
    ngx_str_t                      shm_name;
    ngx_int_t                      rc;
    ngx_uint_t                     i;
    ngx_chain_t                    out;
    ngx_shm_zone_t                *shm_zone;
    ngx_tcp_check_peer_shm_t      *peer_shm;
    ngx_tcp_check_peers_shm_t     *peers_shm;
    ngx_tcp_check_peer_conf_t     *peer_conf;
    ngx_tcp_check_peers_conf_t    *peers_conf;


    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    rc = ngx_http_discard_request_body(r);

    if (rc != NGX_OK) {
        return rc;
    }

    r->headers_out.content_type.len = sizeof("text/html; charset=utf-8") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html; charset=utf-8";

    if (r->method == NGX_HTTP_HEAD) {
        r->headers_out.status = NGX_HTTP_OK;

        rc = ngx_http_send_header(r);

        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    }

    if (ngx_tcp_check_get_shm_name(&shm_name, r->pool) == NGX_ERROR) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    shm_zone = ngx_shared_memory_find((ngx_cycle_t *)ngx_cycle, &shm_name, 
            &ngx_tcp_upstream_module);

    if (shm_zone == NULL || shm_zone->data == NULL) {

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                "[tcp upstream check] can not find the shared memory zone \"%V\" ", &shm_name);

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    peers_conf = shm_zone->data;
    peers_shm = peers_conf->peers_shm;

    peer_conf = peers_conf->peers.elts;
    peer_shm = peers_shm->peers;

    b = ngx_create_temp_buf(r->pool, ngx_pagesize);
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    out.buf = b;
    out.next = NULL;

    b->last = ngx_sprintf(b->last, 
            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\n"
            "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
            "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
            "<head>\n"
            "  <title>Nginx tcp upstream check status</title>\n"
            "</head>\n"
            "<body>\n"
            "<h1>Nginx tcp upstream check status</h1>\n"
            "<h2>Check upstream server number: %ui, shm_name: %V</h2>\n"
            "<table style=\"background-color:white\" cellspacing=\"0\" cellpadding=\"3\" border=\"1\">\n"
            "  <tr bgcolor=\"#C0C0C0\">\n"
            "    <th>Index</th>\n"
            "    <th>Name</th>\n"
            "    <th>Status</th>\n"
            "    <th>Business</th>\n"
            "    <th>Rise counts</th>\n"
            "    <th>Fall counts</th>\n"
            "    <th>Access counts</th>\n"
            "    <th>Check type</th>\n"
            "  </tr>\n",
            peers_conf->peers.nelts, &shm_name);

    for (i = 0; i < peers_conf->peers.nelts; i++) {
        b->last = ngx_sprintf(b->last, 
                "  <tr%s>\n"
                "    <td>%ui</td>\n" 
                "    <td>%V</td>\n" 
                "    <td>%s</td>\n" 
                "    <td>%ui</td>\n" 
                "    <td>%ui</td>\n" 
                "    <td>%ui</td>\n" 
                "    <td>%ui</td>\n" 
                "    <td>%s</td>\n" 
                "  </tr>\n",
                peer_shm[i].down ? " bgcolor=\"#FF0000\"" : "",
                i, 
                &peer_conf[i].peer->name, 
                peer_shm[i].down ? "down" : "up",
                peer_shm[i].business,
                peer_shm[i].rise_count, 
                peer_shm[i].fall_count, 
                peer_shm[i].access_count, 
                peer_conf[i].conf->check_type_conf->name);
    }

    b->last = ngx_sprintf(b->last, 
            "</table>\n"
            "</body>\n"
            "</html>\n");

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = b->last - b->pos;

    b->last_buf = 1;

    rc = ngx_http_send_header(r);

    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }

    return ngx_http_output_filter(r, &out);
}
static ngx_int_t
ngx_http_upstream_check_init_shm_zone(ngx_shm_zone_t *shm_zone, void *data)
{
    size_t                               size;
    ngx_str_t                            oshm_name = ngx_null_string;
    ngx_uint_t                           i, same, number;
    ngx_shm_zone_t                      *oshm_zone;
    ngx_slab_pool_t                     *shpool;
    ngx_http_check_peer_t               *peer;
    ngx_http_check_peers_t              *peers;
    ngx_http_check_peer_shm_t           *peer_shm, *opeer_shm;
    ngx_http_check_peers_shm_t          *peers_shm, *opeers_shm;
    ngx_http_upstream_check_srv_conf_t  *ucscf;

    opeers_shm = NULL;
    peers_shm = NULL;

    same = 0;
    peers = check_peers_ctx;

    number =  peers->peers.nelts;
    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

    if (peers == NULL || number == 0) {
        return NGX_OK;
    }

    if (data) {
        opeers_shm = data;

        if (opeers_shm->number == number
            && opeers_shm->checksum == peers->checksum) {

            peers_shm = data;
            same = 1;
        }
    }

    if (!same) {

        if (ngx_http_check_shm_generation > 1) {

            ngx_http_check_get_shm_name(&oshm_name, ngx_cycle->pool,
                                        ngx_http_check_shm_generation - 1);

            /* The global variable ngx_cycle still points to the old version */
            oshm_zone = ngx_shared_memory_find((ngx_cycle_t *)ngx_cycle,
                                               &oshm_name,
                                               &ngx_http_upstream_check_module);

            if (oshm_zone) {
                opeers_shm = oshm_zone->data;

                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
                               "http upstream check, find oshm_zone:%p, "
                               "opeers_shm: %p",
                               oshm_zone, opeers_shm);
            }
        }

        size = sizeof(*peers_shm) +
               (number - 1) * sizeof(ngx_http_check_peer_shm_t);

        peers_shm = ngx_slab_alloc(shpool, size);

        if (peers_shm == NULL) {
            goto failure;
        }

        ngx_memzero(peers_shm, size);
    }

    peers_shm->generation = ngx_http_check_shm_generation;
    peers_shm->checksum = peers->checksum;
    peers_shm->number = number;

    peer = peers->peers.elts;

    for (i = 0; i < number; i++) {

        peer_shm = &peers_shm->peers[i];

        /* This function may be triggered before the old stale
         * work process exits. The owner may stick to the old
         * pid. */
        peer_shm->owner = NGX_INVALID_PID;

        if (same) {
            continue;
        }

        peer_shm->socklen = peer[i].peer_addr->socklen;
        peer_shm->sockaddr = ngx_slab_alloc(shpool, peer_shm->socklen);
        if (peer_shm->sockaddr == NULL) {
            goto failure;
        }

        ngx_memcpy(peer_shm->sockaddr, peer[i].peer_addr->sockaddr,
                   peer_shm->socklen);

        if (opeers_shm) {

            opeer_shm = ngx_http_check_find_shm_peer(opeers_shm,
                                                     peer[i].peer_addr);
            if (opeer_shm) {
                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
                               "http upstream check: inherit opeer:%V",
                               &peer[i].peer_addr->name);

                ngx_http_check_set_shm_peer(peer_shm, opeer_shm, 0);

                continue;
            }
        }

        ucscf = peer[i].conf;
        ngx_http_check_set_shm_peer(peer_shm, NULL, ucscf->default_down);
    }

    peers->peers_shm = peers_shm;
    shm_zone->data = peers_shm;

    return NGX_OK;

failure:
    ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
                  "http upstream check_shm_size is too small, "
                  "you should specify a larger size.");
    return NGX_ERROR;
}