Пример #1
0
APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(const apt_obj_list_t *list)
{
	if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
		return NULL;
	}
	return APR_RING_LAST(&list->head);
}
Пример #2
0
APT_DECLARE(void*) apt_obj_list_tail(apt_obj_list_t *list)
{
	apt_list_elem_t *elem;
	if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
		return NULL;
	}
	elem = APR_RING_LAST(&list->head);
	return elem->obj;
}
Пример #3
0
static void mpf_timers_reschedule(mpf_timer_manager_t *manager)
{
    mpf_timer_t *it;
    for(it = APR_RING_LAST(&manager->head);
            it != APR_RING_SENTINEL(&manager->head, mpf_timer_t, link);
            it = APR_RING_PREV(it, link)) {

        it->scheduled_time -= manager->elapsed_time;
    }
    manager->elapsed_time = 0;
}
Пример #4
0
static void apt_timers_reschedule(apt_timer_queue_t *queue)
{
    apt_timer_t *it;
    for(it = APR_RING_LAST(&queue->head);
            it != APR_RING_SENTINEL(&queue->head, apt_timer_t, link);
            it = APR_RING_PREV(it, link)) {

        it->scheduled_time -= queue->elapsed_time;
    }
    queue->elapsed_time = 0;
}
Пример #5
0
/**
 * Split the contents of a brigade after bucket 'e' to an existing brigade
 *
 * XXXX: Should this function be added to APR-Util?
 */
static void brigade_move(apr_bucket_brigade *b, apr_bucket_brigade *a,
                         apr_bucket *e)
{
    apr_bucket *f;

    if (e != APR_BRIGADE_SENTINEL(b)) {
        f = APR_RING_LAST(&b->list);
        APR_RING_UNSPLICE(e, f, link);
        APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
    }

    APR_BRIGADE_CHECK_CONSISTENCY(a);
    APR_BRIGADE_CHECK_CONSISTENCY(b);
}
Пример #6
0
/*
 * This function stop extra idle threads to the cnt.
 * @return the number of threads stopped
 * NOTE: There could be busy threads become idle during this function
 */
static struct apr_thread_list_elt *trim_threads(apr_thread_pool_t *me,
                                                apr_size_t *cnt, int idle)
{
    struct apr_thread_list *thds;
    apr_size_t n, n_dbg, i;
    struct apr_thread_list_elt *head, *tail, *elt;

    apr_thread_mutex_lock(me->lock);
    if (idle) {
        thds = me->idle_thds;
        n = me->idle_cnt;
    }
    else {
        thds = me->busy_thds;
        n = me->thd_cnt - me->idle_cnt;
    }
    if (n <= *cnt) {
        apr_thread_mutex_unlock(me->lock);
        *cnt = 0;
        return NULL;
    }
    n -= *cnt;

    head = APR_RING_FIRST(thds);
    for (i = 0; i < *cnt; i++) {
        head = APR_RING_NEXT(head, link);
    }
    tail = APR_RING_LAST(thds);
    if (idle) {
        APR_RING_UNSPLICE(head, tail, link);
        me->idle_cnt = *cnt;
    }

    n_dbg = 0;
    for (elt = head; elt != tail; elt = APR_RING_NEXT(elt, link)) {
        elt->state = TH_STOP;
        n_dbg++;
    }
    elt->state = TH_STOP;
    n_dbg++;
    assert(n == n_dbg);
    *cnt = n;

    apr_thread_mutex_unlock(me->lock);

    APR_RING_PREV(head, link) = NULL;
    APR_RING_NEXT(tail, link) = NULL;
    return head;
}
Пример #7
0
static APR_INLINE apt_bool_t mpf_timer_insert(mpf_timer_manager_t *manager, mpf_timer_t *timer)
{
    mpf_timer_t *it;
    for(it = APR_RING_LAST(&manager->head);
            it != APR_RING_SENTINEL(&manager->head, mpf_timer_t, link);
            it = APR_RING_PREV(it, link)) {

        if(it->scheduled_time <= timer->scheduled_time) {
            APR_RING_INSERT_AFTER(it,timer,link);
            return TRUE;
        }
    }
    APR_RING_INSERT_HEAD(&manager->head,timer,mpf_timer_t,link);
    return TRUE;
}
Пример #8
0
static APR_INLINE apt_bool_t apt_timer_insert(apt_timer_queue_t *timer_queue, apt_timer_t *timer)
{
    apt_timer_t *it;
    for(it = APR_RING_LAST(&timer_queue->head);
            it != APR_RING_SENTINEL(&timer_queue->head, apt_timer_t, link);
            it = APR_RING_PREV(it, link)) {

        if(it->scheduled_time <= timer->scheduled_time) {
            APR_RING_INSERT_AFTER(it,timer,link);
            return TRUE;
        }
    }
    APR_RING_INSERT_HEAD(&timer_queue->head,timer,apt_timer_t,link);
    return TRUE;
}
Пример #9
0
APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
                                                    apr_bucket *e)
{
    apr_bucket_brigade *a;
    apr_bucket *f;

    a = apr_brigade_create(b->p, b->bucket_alloc);
    /* Return an empty brigade if there is nothing left in 
     * the first brigade to split off 
     */
    if (e != APR_BRIGADE_SENTINEL(b)) {
        f = APR_RING_LAST(&b->list);
        APR_RING_UNSPLICE(e, f, link);
        APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
    }

    APR_BRIGADE_CHECK_CONSISTENCY(a);
    APR_BRIGADE_CHECK_CONSISTENCY(b);

    return a;
}
Пример #10
0
static apr_status_t
rate_limit_filter(ap_filter_t *f, apr_bucket_brigade *input_bb)
{
    apr_status_t rv = APR_SUCCESS;
    rl_ctx_t *ctx = f->ctx;
    apr_bucket *fb;
    int do_sleep = 0;
    apr_bucket_alloc_t *ba = f->r->connection->bucket_alloc;
    apr_bucket_brigade *bb = input_bb;

    if (f->c->aborted) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01454) "rl: conn aborted");
        apr_brigade_cleanup(bb);
        return APR_ECONNABORTED;
    }

    if (ctx == NULL) {

        const char *rl = NULL;
        int ratelimit;

        /* no subrequests. */
        if (f->r->main != NULL) {
            ap_remove_output_filter(f);
            return ap_pass_brigade(f->next, bb);
        }

        rl = apr_table_get(f->r->subprocess_env, "rate-limit");

        if (rl == NULL) {
            ap_remove_output_filter(f);
            return ap_pass_brigade(f->next, bb);
        }
        
        /* rl is in kilo bytes / second  */
        ratelimit = atoi(rl) * 1024;
        if (ratelimit <= 0) {
            /* remove ourselves */
            ap_remove_output_filter(f);
            return ap_pass_brigade(f->next, bb);
        }

        /* first run, init stuff */
        ctx = apr_palloc(f->r->pool, sizeof(rl_ctx_t));
        f->ctx = ctx;
        ctx->state = RATE_LIMIT;
        ctx->speed = ratelimit;

        /* calculate how many bytes / interval we want to send */
        /* speed is bytes / second, so, how many  (speed / 1000 % interval) */
        ctx->chunk_size = (ctx->speed / (1000 / RATE_INTERVAL_MS));
        ctx->tmpbb = apr_brigade_create(f->r->pool, ba);
        ctx->holdingbb = apr_brigade_create(f->r->pool, ba);
    }

    while (ctx->state != RATE_ERROR &&
           (!APR_BRIGADE_EMPTY(bb) || !APR_BRIGADE_EMPTY(ctx->holdingbb))) {
        apr_bucket *e;

        if (!APR_BRIGADE_EMPTY(ctx->holdingbb)) {
            APR_BRIGADE_CONCAT(bb, ctx->holdingbb);
        }

        while (ctx->state == RATE_FULLSPEED && !APR_BRIGADE_EMPTY(bb)) {
            /* Find where we 'stop' going full speed. */
            for (e = APR_BRIGADE_FIRST(bb);
                 e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) {
                if (AP_RL_BUCKET_IS_END(e)) {
                    apr_bucket *f;
                    f = APR_RING_LAST(&bb->list);
                    APR_RING_UNSPLICE(e, f, link);
                    APR_RING_SPLICE_TAIL(&ctx->holdingbb->list, e, f,
                                         apr_bucket, link);
                    ctx->state = RATE_LIMIT;
                    break;
                }
            }

            if (f->c->aborted) {
                apr_brigade_cleanup(bb);
                ctx->state = RATE_ERROR;
                break;
            }

            fb = apr_bucket_flush_create(ba);
            APR_BRIGADE_INSERT_TAIL(bb, fb);
            rv = ap_pass_brigade(f->next, bb);

            if (rv != APR_SUCCESS) {
                ctx->state = RATE_ERROR;
                ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, f->r, APLOGNO(01455)
                              "rl: full speed brigade pass failed.");
            }
        }

        while (ctx->state == RATE_LIMIT && !APR_BRIGADE_EMPTY(bb)) {
            for (e = APR_BRIGADE_FIRST(bb);
                 e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) {
                if (AP_RL_BUCKET_IS_START(e)) {
                    apr_bucket *f;
                    f = APR_RING_LAST(&bb->list);
                    APR_RING_UNSPLICE(e, f, link);
                    APR_RING_SPLICE_TAIL(&ctx->holdingbb->list, e, f,
                                         apr_bucket, link);
                    ctx->state = RATE_FULLSPEED;
                    break;
                }
            }

            while (!APR_BRIGADE_EMPTY(bb)) {
                apr_bucket *stop_point;
                apr_off_t len = 0;

                if (f->c->aborted) {
                    apr_brigade_cleanup(bb);
                    ctx->state = RATE_ERROR;
                    break;
                }

                if (do_sleep) {
                    apr_sleep(RATE_INTERVAL_MS * 1000);
                }
                else {
                    do_sleep = 1;
                }

                apr_brigade_length(bb, 1, &len);

                rv = apr_brigade_partition(bb, ctx->chunk_size, &stop_point);
                if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
                    ctx->state = RATE_ERROR;
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01456)
                                  "rl: partition failed.");
                    break;
                }

                if (stop_point != APR_BRIGADE_SENTINEL(bb)) {
                    apr_bucket *f;
                    apr_bucket *e = APR_BUCKET_PREV(stop_point);
                    f = APR_RING_FIRST(&bb->list);
                    APR_RING_UNSPLICE(f, e, link);
                    APR_RING_SPLICE_HEAD(&ctx->tmpbb->list, f, e, apr_bucket,
                                         link);
                }
                else {
                    APR_BRIGADE_CONCAT(ctx->tmpbb, bb);
                }

                fb = apr_bucket_flush_create(ba);

                APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, fb);

#if 0
                brigade_dump(f->r, ctx->tmpbb);
                brigade_dump(f->r, bb);
#endif

                rv = ap_pass_brigade(f->next, ctx->tmpbb);
                apr_brigade_cleanup(ctx->tmpbb);

                if (rv != APR_SUCCESS) {
                    ctx->state = RATE_ERROR;
                    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, f->r, APLOGNO(01457)
                                  "rl: brigade pass failed.");
                    break;
                }
            }
        }
    }

    return rv;
}
Пример #11
0
/**
 * Perform routine maintenance on the resource list. This call
 * may instantiate new resources or expire old resources.
 */
static apr_status_t reslist_maint(apr_reslist_t *reslist)
{
    apr_time_t now;
    apr_status_t rv;
    apr_res_t *res;
    int created_one = 0;

    apr_thread_mutex_lock(reslist->listlock);

    /* Check if we need to create more resources, and if we are allowed to. */
    while (reslist->nidle < reslist->min && reslist->ntotal < reslist->hmax) {
        /* Create the resource */
        rv = create_resource(reslist, &res);
        if (rv != APR_SUCCESS) {
            free_container(reslist, res);
            apr_thread_mutex_unlock(reslist->listlock);
            return rv;
        }
        /* Add it to the list */
        push_resource(reslist, res);
        /* Update our counters */
        reslist->ntotal++;
        /* If someone is waiting on that guy, wake them up. */
        rv = apr_thread_cond_signal(reslist->avail);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(reslist->listlock);
            return rv;
        }
        created_one++;
    }

    /* We don't need to see if we're over the max if we were under it before */
    if (created_one) {
        apr_thread_mutex_unlock(reslist->listlock);
        return APR_SUCCESS;
    }

    /* Check if we need to expire old resources */
    now = apr_time_now();
    while (reslist->nidle > reslist->smax && reslist->nidle > 0) {
        /* Peak at the last resource in the list */
        res = APR_RING_LAST(&reslist->avail_list);
        /* See if the oldest entry should be expired */
        if (now - res->freed < reslist->ttl) {
            /* If this entry is too young, none of the others
             * will be ready to be expired either, so we are done. */
            break;
        }
        APR_RING_REMOVE(res, link);
        reslist->nidle--;
        reslist->ntotal--;
        rv = destroy_resource(reslist, res);
        free_container(reslist, res);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(reslist->listlock);
            return rv;
        }
    }

    apr_thread_mutex_unlock(reslist->listlock);
    return APR_SUCCESS;
}