Exemplo n.º 1
0
static void
rtpp_mif_run(void *argp)
{
    struct rtpp_module_if_priv *pvt;
    struct rtpp_wi *wi;
    int signum;
    const char *aname;
    struct rtpp_acct *rap;

    pvt = (struct rtpp_module_if_priv *)argp;
    for (;;) {
        wi = rtpp_queue_get_item(pvt->req_q, 0);
        if (rtpp_wi_get_type(wi) == RTPP_WI_TYPE_SGNL) {
            signum = rtpp_wi_sgnl_get_signum(wi);
            rtpp_wi_free(wi);
            if (signum == SIGTERM) {
                break;
            }
            continue;
        }
        aname = rtpp_wi_apis_getnamearg(wi, (void **)&rap, sizeof(rap));
        if (aname == do_acct_aname) {
            pvt->mip->on_session_end.func(pvt->mpvt, rap);
        }
        CALL_METHOD(rap->rcnt, decref);
        rtpp_wi_free(wi);
    }
}
Exemplo n.º 2
0
static void
rtpp_anetio_sthread(struct sthread_args *args)
{
    int n, nsend, i;
    struct rtpp_wi *wi, *wis[100];
#ifdef RTPP_DEBUG
    double tp[3], runtime, sleeptime;
    long run_n;

    runtime = sleeptime = 0.0;
    run_n = 0;
    tp[0] = getdtime();
#endif
    for (;;) {
        nsend = rtpp_queue_get_items(args->out_q, wis, 100, 0);
#ifdef RTPP_DEBUG
        tp[1] = getdtime();
#endif

        for (i = 0; i < nsend; i++) {
            wi = wis[i];
            if (wi->wi_type == RTPP_WI_TYPE_SGNL) {
                rtpp_wi_free(wi);
                goto out;
            }
            do {
                n = sendto(wi->sock, wi->msg, wi->msg_len, wi->flags,
                           wi->sendto, wi->tolen);
                if (wi->debug != 0) {
                    rtpp_log_write(RTPP_LOG_DBUG, args->glog,
                                   "rtpp_anetio_sthread: sendto(%d, %p, %d, %d, %p, %d) = %d",
                                   wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto,
                                   wi->tolen, n);
                }
                if (n >= 0) {
                    wi->nsend--;
                } else if (n == -1 && errno != ENOBUFS) {
                    break;
                }
            } while (wi->nsend > 0);
            rtpp_wi_free(wi);
        }
#ifdef RTPP_DEBUG
        sleeptime += tp[1] - tp[0];
        tp[0] = getdtime();
        runtime += tp[0] - tp[1];
        if ((run_n % 10000) == 0) {
            rtpp_log_write(RTPP_LOG_DBUG, args->glog, "rtpp_anetio_sthread(%p): run %ld aload = %f filtered = %f", \
                           args, run_n, runtime / (runtime + sleeptime), args->average_load.lastval);
        }
        if (runtime + sleeptime > 1.0) {
            recfilter_apply(&args->average_load, runtime / (runtime + sleeptime));
            runtime = sleeptime = 0.0;
        }
        run_n += 1;
#endif
    }
out:
    return;
}
Exemplo n.º 3
0
static void
rtpp_notify_queue_run(void *arg)
{
    struct rtpp_wi *wi;
    struct rtpp_notify_wi *wi_data;
    struct rtpp_notify_priv *pvt;

    pvt = (struct rtpp_notify_priv *)arg;
    for (;;) {
        wi = rtpp_queue_get_item(pvt->nqueue, 0);
        if (rtpp_wi_get_type(wi) == RTPP_WI_TYPE_SGNL) {
            rtpp_wi_free(wi);
            break;
        }
        wi_data = rtpp_wi_data_get_ptr(wi, sizeof(struct rtpp_notify_wi), 0);

        /* main work here */
        do_timeout_notification(wi_data, 3, wi->log);

        /* deallocate wi */
        rtpp_wi_free(wi);
    }
}
Exemplo n.º 4
0
struct rtpp_notify *
rtpp_notify_ctor(struct rtpp_log *glog)
{
    struct rtpp_notify_priv *pvt;

    pvt = rtpp_zmalloc(sizeof(struct rtpp_notify_priv));
    if (pvt == NULL) {
        goto e0;
    }
    pvt->nqueue = rtpp_queue_init(1, "rtpp_notify");
    if (pvt->nqueue == NULL) {
        goto e1;
    }

    /* Pre-allocate sigterm, so that we don't have any malloc() in dtor() */
    pvt->sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0);
    if (pvt->sigterm == NULL) {
        goto e2;
    }

    if (pthread_create(&pvt->thread_id, NULL, (void *(*)(void *))&rtpp_notify_queue_run, pvt) != 0) {
        goto e3;
    }

    CALL_METHOD(glog->rcnt, incref);
    pvt->glog = glog;
    pvt->pub.schedule = &rtpp_notify_schedule;
    pvt->pub.dtor = &rtpp_notify_dtor;

    return (&pvt->pub);

e3:
    rtpp_wi_free(pvt->sigterm);
e2:
    rtpp_queue_destroy(pvt->nqueue);
e1:
    free(pvt);
e0:
    return (NULL);
}
Exemplo n.º 5
0
static void
rtpp_proc_async_run(void *arg)
{
    struct cfg *cf;
    double last_tick_time;
    int alarm_tick, i, ndrain, rtp_only;
    struct rtpp_proc_async_cf *proc_cf;
    long long ncycles_ref;
#ifdef RTPP_DEBUG
    int ncycles_ref_pre, last_ctick;
#endif
    struct sign_arg *s_a;
    struct rtpp_wi *wi, *wis[10];
    struct sthread_args *sender;
    double tp[4];
    struct rtpp_proc_rstats *rstats;
    struct rtpp_stats_obj *stats_cf;

    cf = (struct cfg *)arg;
    proc_cf = cf->stable->rtpp_proc_cf;
    stats_cf = cf->stable->rtpp_stats;
    rstats = &proc_cf->rstats;

    last_tick_time = 0;
    wi = rtpp_queue_get_item(proc_cf->time_q, 0);
    s_a = (struct sign_arg *)rtpp_wi_sgnl_get_data(wi, NULL);
#ifdef RTPP_DEBUG
    last_ctick = s_a->clock_tick;
    ncycles_ref_pre = s_a->ncycles_ref;
#endif
    rtpp_wi_free(wi);

    tp[0] = getdtime();
    for (;;) {
        i = rtpp_queue_get_items(proc_cf->time_q, wis, 10, 0);
        if (i <= 0) {
            continue;
        }
        i -= 1;
        s_a = (struct sign_arg *)rtpp_wi_sgnl_get_data(wis[i], NULL);
        ndrain = (s_a->ncycles_ref - ncycles_ref) / (cf->stable->target_pfreq / MAX_RTP_RATE);
#ifdef RTPP_DEBUG
        last_ctick = s_a->clock_tick;
        ncycles_ref_pre = ncycles_ref;
#endif
        ncycles_ref = s_a->ncycles_ref;
        for(; i > -1; i--) {
            rtpp_wi_free(wis[i]);
        }

        tp[1] = getdtime();
#if RTPP_DEBUG
        if (last_ctick % (unsigned int)cf->stable->target_pfreq == 0 || last_ctick < 1000) {
            rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld sptime %f, CSV: %f,%f,%f", \
              last_ctick, tp[1], (double)last_ctick / cf->stable->target_pfreq, \
              ((double)ncycles_ref / cf->stable->target_pfreq) - tp[1], tp[1]);
        }
#endif

        if (ndrain < 1) {
            ndrain = 1;
        }

#if RTPP_DEBUG
        if (ndrain > 1) {
            rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld " \
              "ncycles_ref %lld, ncycles_ref_pre %lld, ndrain %d CSV: %f,%f,%d", \
              last_ctick, ncycles_ref, ncycles_ref_pre, ndrain, \
              (double)last_ctick / cf->stable->target_pfreq, ndrain);
        }
#endif

        alarm_tick = 0;
        if (last_tick_time == 0 || last_tick_time > tp[1]) {
            last_tick_time = tp[1];
        } else if (last_tick_time + (double)TIMETICK < tp[1]) {
            alarm_tick = 1;
            last_tick_time = tp[1];
        }

        if (alarm_tick || (ncycles_ref % 7) == 0) {
            rtp_only = 0;
        } else {
            rtp_only = 1;
        }

        pthread_mutex_lock(&cf->sessinfo.lock);
        if (cf->sessinfo.nsessions > 0) {
            if (rtp_only == 0) {
                i = poll(cf->sessinfo.pfds_rtcp, cf->sessinfo.nsessions, 0);
            }
            i = poll(cf->sessinfo.pfds_rtp, cf->sessinfo.nsessions, 0);
            pthread_mutex_unlock(&cf->sessinfo.lock);
            if (i < 0 && errno == EINTR) {
                rtpp_command_async_wakeup(cf->stable->rtpp_cmd_cf);
                tp[0] = getdtime();
                continue;
            }
        } else {
            pthread_mutex_unlock(&cf->sessinfo.lock);
        }

        tp[2] = getdtime();

        sender = rtpp_anetio_pick_sender(proc_cf->op);
        if (rtp_only == 0) {
            pthread_mutex_lock(&cf->glock);
            process_rtp(cf, tp[2], alarm_tick, ndrain, sender, rstats);
        } else {
            process_rtp_only(cf, tp[2], ndrain, sender, rstats);
            pthread_mutex_lock(&cf->glock);
        }

        if (cf->rtp_nsessions > 0) {
            process_rtp_servers(cf, tp[2], sender, rstats);
        }
        pthread_mutex_unlock(&cf->glock);
        rtpp_anetio_pump_q(sender);
        rtpp_command_async_wakeup(cf->stable->rtpp_cmd_cf);
        tp[3] = getdtime();
        flush_rstats(stats_cf, rstats);

#if RTPP_DEBUG
        recfilter_apply(&proc_cf->sleep_time, tp[1] - tp[0]);
        recfilter_apply(&proc_cf->poll_time, tp[2] - tp[1]);
        recfilter_apply(&proc_cf->proc_time, tp[3] - tp[2]);
#endif
        tp[0] = tp[3];
#if RTPP_DEBUG
        if (last_ctick % (unsigned int)cf->stable->target_pfreq == 0 || last_ctick < 1000) {
#if 0
            rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld eptime %f, CSV: %f,%f,%f", \
              last_ctick, tp[3], (double)last_ctick / cf->stable->target_pfreq, tp[3] - tp[1], tp[3]);
#endif
            rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld eptime %f sleep_time %f poll_time %f proc_time %f CSV: %f,%f,%f,%f", \
              last_ctick, tp[3], proc_cf->sleep_time.lastval, proc_cf->poll_time.lastval, proc_cf->proc_time.lastval, \
              (double)last_ctick / cf->stable->target_pfreq, proc_cf->sleep_time.lastval, proc_cf->poll_time.lastval, proc_cf->proc_time.lastval);
        }
#endif
    }

}
Exemplo n.º 6
0
struct rtpp_module_if *
rtpp_module_if_ctor(struct rtpp_cfg_stable *cfsp, struct rtpp_log *log,
  const char *mpath)
{
    struct rtpp_refcnt *rcnt;
    struct rtpp_module_if_priv *pvt;
    const char *derr;

    pvt = rtpp_rzmalloc(sizeof(struct rtpp_module_if_priv), &rcnt);
    if (pvt == NULL) {
        goto e0;
    }
    pvt->pub.rcnt = rcnt;
    pvt->dmp = dlopen(mpath, RTLD_NOW);
    if (pvt->dmp == NULL) {
        derr = dlerror();
        if (strstr(derr, mpath) == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't dlopen(%s): %s", mpath, derr);
        } else {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't dlopen() module: %s", derr);
        }
        goto e1;
    }
    pvt->mip = dlsym(pvt->dmp, "rtpp_module");
    if (pvt->mip == NULL) {
        derr = dlerror();
        if (strstr(derr, mpath) == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't find 'rtpp_module' symbol in the %s"
              ": %s", mpath, derr);
        } else {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't find 'rtpp_module' symbol: %s",
              derr);
        }
        goto e2;
    }
    if (!MI_VER_CHCK(pvt->mip)) {
        RTPP_LOG(log, RTPP_LOG_ERR, "incompatible API version in the %s, "
          "consider recompiling the module", mpath);
        goto e2;
    }

#if RTPP_CHECK_LEAKS
    pvt->mip->_malloc = &rtpp_memdeb_malloc;
    pvt->mip->_zmalloc = &rtpp_zmalloc_memdeb;
    pvt->mip->_free = &rtpp_memdeb_free;
    pvt->mip->_realloc = &rtpp_memdeb_realloc;
    pvt->mip->_strdup = &rtpp_memdeb_strdup;
    pvt->mip->_asprintf = &rtpp_memdeb_asprintf;
    pvt->mip->_vasprintf = &rtpp_memdeb_vasprintf;
    pvt->memdeb_p = rtpp_memdeb_init();
    rtpp_memdeb_setlog(pvt->memdeb_p, log);
#else
    pvt->mip->_malloc = (rtpp_module_malloc_t)&malloc;
    pvt->mip->_zmalloc = (rtpp_module_zmalloc_t)&rtpp_zmalloc;
    pvt->mip->_free = (rtpp_module_free_t)&free;
    pvt->mip->_realloc = (rtpp_module_realloc_t)&realloc;
    pvt->mip->_strdup = (rtpp_module_strdup_t)&strdup;
    pvt->mip->_asprintf = rtpp_module_asprintf;
    pvt->mip->_vasprintf = rtpp_module_vasprintf;
#endif
    if (pvt->memdeb_p == NULL) {
        goto e2;
    }
    /* We make a copy, so that the module cannot screw us up */
    pvt->mip->memdeb_p = pvt->memdeb_p;
    pvt->sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0);
    if (pvt->sigterm == NULL) {
        goto e3;
    }
    pvt->req_q = rtpp_queue_init(1, "rtpp_module_if(%s)", pvt->mip->name);
    if (pvt->req_q == NULL) {
        goto e4;
    }
    if (pvt->mip->ctor != NULL) {
        pvt->mpvt = pvt->mip->ctor(cfsp);
        if (pvt->mpvt == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "module '%s' failed to initialize",
              pvt->mip->name);
            goto e5;
        }
    }
    if (pvt->mip->on_session_end.argsize != rtpp_acct_OSIZE()) {
        RTPP_LOG(log, RTPP_LOG_ERR, "incompatible API version in the %s, "
          "consider recompiling the module", mpath);
        goto e6;
    }

    if (pthread_create(&pvt->thread_id, NULL,
      (void *(*)(void *))&rtpp_mif_run, pvt) != 0) {
        goto e6;
    }
    CALL_METHOD(log->rcnt, incref);
    pvt->log = log;
    pvt->pub.do_acct = &rtpp_mif_do_acct;
    CALL_METHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_mif_dtor,
      pvt);
    return ((&pvt->pub));
e6:
    if (pvt->mip->dtor != NULL) {
        pvt->mip->dtor(pvt->mpvt);
    }
e5:
    rtpp_queue_destroy(pvt->req_q);
#if RTPP_CHECK_LEAKS
    if (rtpp_memdeb_dumpstats(pvt->memdeb_p, 1) != 0) {
        RTPP_LOG(log, RTPP_LOG_ERR, "module '%s' leaked memory in the failed "
          "constructor", pvt->mip->name);
    }
#endif
e4:
    rtpp_wi_free(pvt->sigterm);
e3:
#if RTPP_CHECK_LEAKS
    rtpp_memdeb_dtor(pvt->memdeb_p);
#endif
e2:
    dlclose(pvt->dmp);
e1:
    CALL_METHOD(rcnt, decref);
    free(pvt);
e0:
    return (NULL);
}
Exemplo n.º 7
0
struct rtpp_anetio_cf *
rtpp_netio_async_init(struct cfg *cf, int qlen)
{
    struct rtpp_anetio_cf *netio_cf;
    int i, ri;

    netio_cf = rtpp_zmalloc(sizeof(*netio_cf));
    if (netio_cf == NULL)
        return (NULL);

    for (i = 0; i < SEND_THREADS; i++) {
        netio_cf->args[i].out_q = rtpp_queue_init(qlen, "RTPP->NET%.2d", i);
        if (netio_cf->args[i].out_q == NULL) {
            for (ri = i - 1; ri >= 0; ri--) {
                rtpp_queue_destroy(netio_cf->args[ri].out_q);
            }
            goto e0;
        }
        netio_cf->args[i].glog = cf->stable->glog;
        netio_cf->args[i].dmode = cf->stable->dmode;
#ifdef RTPP_DEBUG
        recfilter_init(&netio_cf->args[i].average_load, 0.9, 0.0, 0);
#endif
    }

    for (i = 0; i < SEND_THREADS; i++) {
        netio_cf->args[i].sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0);
        if (netio_cf->args[i].sigterm == NULL) {
            for (ri = i - 1; ri >= 0; ri--) {
                rtpp_wi_free(netio_cf->args[ri].sigterm);
            }
            goto e1;
        }
    }

    cf->stable->rtpp_netio_cf = netio_cf;
    for (i = 0; i < SEND_THREADS; i++) {
        if (pthread_create(&(netio_cf->thread_id[i]), NULL, (void *(*)(void *))&rtpp_anetio_sthread, &netio_cf->args[i]) != 0) {
            for (ri = i - 1; ri >= 0; ri--) {
                rtpp_queue_put_item(netio_cf->args[ri].sigterm, netio_cf->args[ri].out_q);
                pthread_join(netio_cf->thread_id[ri], NULL);
            }
            for (ri = i; ri < SEND_THREADS; ri++) {
                rtpp_wi_free(netio_cf->args[ri].sigterm);
            }
            goto e1;
        }
    }

    return (netio_cf);

#if 0
e2:
    for (i = 0; i < SEND_THREADS; i++) {
        rtpp_wi_free(netio_cf->args[i].sigterm);
    }
#endif
e1:
    for (i = 0; i < SEND_THREADS; i++) {
        rtpp_queue_destroy(netio_cf->args[i].out_q);
    }
e0:
    free(netio_cf);
    return (NULL);
}
Exemplo n.º 8
0
static void
rtpp_anetio_sthread(struct sthread_args *args)
{
    int n, nsend, i, send_errno, nretry;
    struct rtpp_wi *wi, *wis[100];
#if RTPP_DEBUG_timers
    double tp[3], runtime, sleeptime;
    long run_n;

    runtime = sleeptime = 0.0;
    run_n = 0;
    tp[0] = getdtime();
#endif
    for (;;) {
        nsend = rtpp_queue_get_items(args->out_q, wis, 100, 0);
#if RTPP_DEBUG_timers
        tp[1] = getdtime();
#endif

        for (i = 0; i < nsend; i++) {
	    wi = wis[i];
            if (wi->wi_type == RTPP_WI_TYPE_SGNL) {
                rtpp_wi_free(wi);
                goto out;
            }
            nretry = 0;
            do {
                n = sendto(wi->sock, wi->msg, wi->msg_len, wi->flags,
                  wi->sendto, wi->tolen);
                send_errno = (n < 0) ? errno : 0;
#if RTPP_DEBUG_netio >= 1
                if (wi->debug != 0) {
                    char daddr[MAX_AP_STRBUF];

                    addrport2char_r(wi->sendto, daddr, sizeof(daddr), ':');
                    if (n < 0) {
                        RTPP_ELOG(wi->log, RTPP_LOG_DBUG,
                          "sendto(%d, %p, %lld, %d, %p (%s), %d) = %d",
                          wi->sock, wi->msg, (long long)wi->msg_len, wi->flags,
                          wi->sendto, daddr, wi->tolen, n);
                    } else if (n < wi->msg_len) {
                        RTPP_LOG(wi->log, RTPP_LOG_DBUG,
                          "sendto(%d, %p, %lld, %d, %p (%s), %d) = %d: short write",
                          wi->sock, wi->msg, (long long)wi->msg_len, wi->flags,
                          wi->sendto, daddr, wi->tolen, n);
#if RTPP_DEBUG_netio >= 2
                    } else {
                        RTPP_LOG(wi->log, RTPP_LOG_DBUG,
                          "sendto(%d, %p, %d, %d, %p (%s), %d) = %d",
                          wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, daddr,
                          wi->tolen, n);
#endif
                    }
                }
#endif
                if (n >= 0) {
                    wi->nsend--;
                } else {
                    /* "EPERM" is Linux thing, yield and retry */
                    if ((send_errno == EPERM || send_errno == ENOBUFS)
                      && nretry < RTPP_ANETIO_MAX_RETRY) {
                        sched_yield();
                        nretry++;
                    } else {
                        break;
                    }
                }
            } while (wi->nsend > 0);
            rtpp_wi_free(wi);
        }
#if RTPP_DEBUG_timers
        sleeptime += tp[1] - tp[0];
        tp[0] = getdtime();
        runtime += tp[0] - tp[1];
        if ((run_n % 10000) == 0) {
            RTPP_LOG(args->glog, RTPP_LOG_DBUG, "rtpp_anetio_sthread(%p): run %ld aload = %f filtered = %f", \
              args, run_n, runtime / (runtime + sleeptime), args->average_load.lastval);
        }
        if (runtime + sleeptime > 1.0) {
            recfilter_apply(&args->average_load, runtime / (runtime + sleeptime));
            runtime = sleeptime = 0.0;
        }
        run_n += 1;
#endif
    }
out:
    return;
}