int JK_METHOD ajp_maintain()

in native/common/jk_ajp_common.c [3510:3636]


int JK_METHOD ajp_maintain(jk_worker_t *pThis, time_t mstarted, int global,
                           jk_log_context_t *l)
{
    JK_TRACE_ENTER(l);

    if (pThis && pThis->worker_private) {
        ajp_worker_t *aw = pThis->worker_private;
        int i;
        unsigned int n = 0, k = 0, cnt = 0;
        unsigned int m, m_count = 0;
        jk_sock_t   *m_sock;

        /* Do connection pool maintenance only if timeouts or keepalives are set
         */
        if (aw->cache_timeout <= 0 &&
            aw->conn_ping_interval <= 0) {
            /* Nothing to do.
             */
            JK_TRACE_EXIT(l);
            return JK_TRUE;
        }

        JK_ENTER_CS(&aw->cs);
        /* Count open slots
         */
        for (i = (int)aw->ep_cache_sz - 1; i >= 0; i--) {
            if (aw->ep_cache[i] && IS_VALID_SOCKET(aw->ep_cache[i]->sd))
                cnt++;
        }
        m_sock = (jk_sock_t *)malloc((cnt + 1) * sizeof(jk_sock_t));
        /* Handle worker cache timeouts
         */
        if (aw->cache_timeout > 0) {
            for (i = (int)aw->ep_cache_sz - 1;
                    i >= 0; i--) {
                /* Skip the closed sockets
                 */
                if (IS_SLOT_AVAIL(aw->ep_cache[i]) &&
                    IS_VALID_SOCKET(aw->ep_cache[i]->sd)) {
                    int elapsed = (int)difftime(mstarted,
                                                aw->ep_cache[i]->last_access);
                    if (elapsed > aw->cache_timeout) {
                        time_t rt = 0;
                        n++;
                        if (JK_IS_DEBUG_LEVEL(l))
                            rt = time(NULL);
                        aw->ep_cache[i]->reuse = JK_FALSE;
                        m_sock[m_count++] = aw->ep_cache[i]->sd;
                        aw->ep_cache[i]->sd = JK_INVALID_SOCKET;
                        ajp_reset_endpoint(aw->ep_cache[i], l);
                        if (JK_IS_DEBUG_LEVEL(l))
                            jk_log(l, JK_LOG_DEBUG,
                                   "(%s) cleaning pool slot=%d elapsed %d in %d",
                                   aw->name, i, elapsed,
                                   (int)(difftime(time(NULL), rt)));
                    }
                }
                if (cnt <= aw->ep_mincache_sz + n) {
                    if (JK_IS_DEBUG_LEVEL(l)) {
                        jk_log(l, JK_LOG_DEBUG,
                               "(%s) reached pool min size %u from %u cache slots",
                               aw->name, aw->ep_mincache_sz, aw->ep_cache_sz);
                    }
                    break;
                }
            }
        }
        /* Handle worker connection keepalive
         */
        if (aw->conn_ping_interval > 0 && aw->ping_timeout > 0) {
            for (i = (int)aw->ep_cache_sz - 1; i >= 0; i--) {
                /* Skip the closed sockets
                 */
                if (IS_SLOT_AVAIL(aw->ep_cache[i]) &&
                    IS_VALID_SOCKET(aw->ep_cache[i]->sd)) {
                    int elapsed = (int)difftime(mstarted,
                                                aw->ep_cache[i]->last_access);
                    if (elapsed > aw->conn_ping_interval) {
                        k++;
                        /* handle cping/cpong.
                         */
                        if (ajp_handle_cping_cpong(aw->ep_cache[i],
                            aw->ping_timeout, l) == JK_FALSE) {
                            jk_log(l, JK_LOG_INFO,
                                   "(%s) failed sending request, "
                                   "socket %d keepalive cping/cpong "
                                   "failure (errno=%d)",
                                   aw->name,
                                   aw->ep_cache[i]->sd,
                                   aw->ep_cache[i]->last_errno);
                            aw->ep_cache[i]->reuse = JK_FALSE;
                            m_sock[m_count++] = aw->ep_cache[i]->sd;
                            aw->ep_cache[i]->sd = JK_INVALID_SOCKET;
                            ajp_reset_endpoint(aw->ep_cache[i], l);
                        }
                    }
                }
            }
        }
        JK_LEAVE_CS(&aw->cs);
        /* Shutdown sockets outside of the lock.
         * This has benefits only if maintain was
         * called from the watchdog thread.
         */
        for (m = 0; m < m_count; m++) {
            if (IS_VALID_SOCKET(m_sock[m])) {
                jk_shutdown_socket(m_sock[m], l);
                JK_ATOMIC_DECREMENT(&(aw->s->connected));
            }
        }
        free(m_sock);
        if ((k + n) && JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "(%s) pinged %u and recycled %u sockets in %d seconds "
                   "from %u pool slots",
                   aw->name, k, n, (int)(difftime(time(NULL), mstarted)),
                   aw->ep_cache_sz);
        JK_TRACE_EXIT(l);
        return JK_TRUE;
    }
    else {
        JK_LOG_NULL_PARAMS(l);
    }

    JK_TRACE_EXIT(l);
    return JK_FALSE;
}