Example #1
0
void stats_initialize(void)
{
    if (_stats_running)
        return;

    /* set up global struct */
    _stats.global_tree = avl_tree_new(_compare_stats, NULL);
    _stats.source_tree = avl_tree_new(_compare_source_stats, NULL);

    _stats.event_listeners = NULL;
    thread_mutex_create (&_stats.listeners_lock);

    _stats_running = 1;

    stats_event_time (NULL, "server_start", STATS_GENERAL);

    /* global currently active stats */
    stats_event_flags (NULL, "clients", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "sources", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "stats", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "banned_IPs", "0", STATS_COUNTERS);
    stats_event (NULL, "listeners", "0");

    /* global accumulating stats */
    stats_event_flags (NULL, "client_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "source_client_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "source_relay_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "source_total_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "stats_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "listener_connections", "0", STATS_COUNTERS);
    stats_event_flags (NULL, "outgoing_kbitrate", "0", STATS_COUNTERS|STATS_REGULAR);
    stats_event_flags (NULL, "stream_kbytes_sent", "0", STATS_COUNTERS|STATS_REGULAR);
    stats_event_flags (NULL, "stream_kbytes_read", "0", STATS_COUNTERS|STATS_REGULAR);
}
Example #2
0
static void *_stats_thread(void *arg)
{
    stats_event_t *event;
    stats_event_t *copy;
    event_listener_t *listener;

    stats_event_time (NULL, "server_start");
    stats_event_time_iso8601 (NULL, "server_start_iso8601");

    /* global currently active stats */
    stats_event (NULL, "clients", "0");
    stats_event (NULL, "connections", "0");
    stats_event (NULL, "sources", "0");
    stats_event (NULL, "stats", "0");
    stats_event (NULL, "listeners", "0");

    /* global accumulating stats */
    stats_event (NULL, "client_connections", "0");
    stats_event (NULL, "source_client_connections", "0");
    stats_event (NULL, "source_relay_connections", "0");
    stats_event (NULL, "source_total_connections", "0");
    stats_event (NULL, "stats_connections", "0");
    stats_event (NULL, "listener_connections", "0");

    ICECAST_LOG_INFO("stats thread started");
    while (_stats_running) {
        thread_mutex_lock(&_global_event_mutex);
        if (_global_event_queue.head != NULL) {
            /* grab the next event from the queue */
            event = _get_event_from_queue (&_global_event_queue);
            thread_mutex_unlock(&_global_event_mutex);

            if (event == NULL)
                continue;
            event->next = NULL;

            thread_mutex_lock(&_stats_mutex);

            /* check if we are dealing with a global or source event */
            if (event->source == NULL)
                process_global_event (event);
            else
                process_source_event (event);

            /* now we have an event that's been processed into the running stats */
            /* this event should get copied to event listeners' queues */
            listener = (event_listener_t *)_event_listeners;
            while (listener) {
                copy = _copy_event(event);
                thread_mutex_lock (&listener->mutex);
                _add_event_to_queue (copy, &listener->queue);
                thread_mutex_unlock (&listener->mutex);

                listener = listener->next;
            }

            /* now we need to destroy the event */
            _free_event(event);

            thread_mutex_unlock(&_stats_mutex);
            continue;
        }
        else
        {
            thread_mutex_unlock(&_global_event_mutex);
        }

        thread_sleep(300000);
    }

    return NULL;
}
/* This is called when there has been a change in the metadata. Usually
 * artist and title are provided separately so here we update the stats
 * and write log entry if required.
 */
static void update_comments (source_t *source)
{
    ogg_state_t *ogg_info = source->format->_state;
    char *title = ogg_info->title;
    char *artist = ogg_info->artist;
    char *metadata = NULL;
    unsigned int len = 1; /* space for the nul byte at least */
    ogg_codec_t *codec;
    char codec_names [100] = "";

    if (ogg_info->artist)
    {
        if (title)
        {
            len += strlen(artist) + strlen(title) + 3;
            metadata = calloc (1, len);
            snprintf (metadata, len, "%s - %s", artist, title);
        }
        else
        {
            len += strlen(artist);
            metadata = calloc (1, len);
            snprintf (metadata, len, "%s", artist);
        }
    }
    else
    {
        if (title)
        {
            len += strlen (title);
            metadata = calloc (1, len);
            snprintf (metadata, len, "%s", title);
        }
    }
	json_stats_update(source->mount, ogg_info->artist, ogg_info->title, source->listeners);
    if (metadata)
    {
        logging_playlist (source->mount, metadata, source->listeners);
        free (metadata);
    }
    stats_event (source->mount, "artist", artist);
    stats_event (source->mount, "title", title);
    stats_event_time (source->mount, "metadata_updated", STATS_GENERAL);

    codec = ogg_info->codecs;
    while (codec)
    {
        if (codec->name)
        {
            size_t len = strlen (codec_names);
            size_t remaining = sizeof (codec_names) - len;
            char *where = codec_names + len;
            char *separator = "/";
            if (len == 0)
                separator = "";
            snprintf (where, remaining, "%s%s", separator, codec->name);
        }
        codec = codec->next;
    }
    stats_event (source->mount, "subtype", codec_names);
    yp_touch (source->mount);
}
Example #4
0
/* Perform any initialisation just before the stream data is processed, the header
 * info is processed by now and the format details are setup
 */
static void source_init (source_t *source)
{
    ice_config_t *config = config_get_config();
    char *listenurl;
    const char *str;
    int listen_url_size;
    mount_proxy *mountinfo;

    /* 6 for max size of port */
    listen_url_size = strlen("http://") + strlen(config->hostname) +
        strlen(":") + 6 + strlen(source->mount) + 1;

    listenurl = malloc (listen_url_size);
    memset (listenurl, '\000', listen_url_size);
    snprintf (listenurl, listen_url_size, "http://%s%s",
            config->hostname, source->mount);
    config_release_config();

    str = httpp_getvar(source->parser, "ice-audio-info");
    source->audio_info = util_dict_new();
    if (str)
    {
        _parse_audio_info (source, str);
        stats_event (source->mount, "audio_info", str);
    }

    stats_event (source->mount, "listenurl", listenurl);

    free(listenurl);

    if (source->dumpfilename != NULL)
    {
        source->dumpfile = fopen (source->dumpfilename, "ab");
        if (source->dumpfile == NULL)
        {
            WARN2("Cannot open dump file \"%s\" for appending: %s, disabling.",
                    source->dumpfilename, strerror(errno));
        }
    }

    /* grab a read lock, to make sure we get a chance to cleanup */
    thread_rwlock_rlock (source->shutdown_rwlock);

    /* start off the statistics */
    source->listeners = 0;
    stats_event_inc (NULL, "source_total_connections");
    stats_event (source->mount, "slow_listeners", "0");
    stats_event_args (source->mount, "listeners", "%lu", source->listeners);
    stats_event_args (source->mount, "listener_peak", "%lu", source->peak_listeners);
    stats_event_time (source->mount, "stream_start");

    DEBUG0("Source creation complete");
    source->last_read = time (NULL);
    source->prev_listeners = -1;
    source->running = 1;

    mountinfo = config_find_mount (config_get_config(), source->mount);
    if (mountinfo)
    {
        if (mountinfo->on_connect)
            source_run_script (mountinfo->on_connect, source->mount);
        auth_stream_start (mountinfo, source->mount);
    }
    config_release_config();

    /*
    ** Now, if we have a fallback source and override is on, we want
    ** to steal its clients, because it means we've come back online
    ** after a failure and they should be gotten back from the waiting
    ** loop or jingle track or whatever the fallback is used for
    */

    if (source->fallback_override && source->fallback_mount)
    {
        source_t *fallback_source;

        avl_tree_rlock(global.source_tree);
        fallback_source = source_find_mount(source->fallback_mount);

        if (fallback_source)
            source_move_clients (fallback_source, source);

        avl_tree_unlock(global.source_tree);
    }
}
Example #5
0
static void *_stats_thread(void *arg)
{
    stats_event_t *event;
    stats_event_t *copy;
    event_listener_t *listener;

    if (!kitsune_is_updating()) { /**DSU control */
        stats_event (NULL, "server", ICECAST_VERSION_STRING);
        stats_event_time (NULL, "server_start");

        /* global currently active stats */
        stats_event (NULL, "clients", "0");
        stats_event (NULL, "connections", "0");
        stats_event (NULL, "sources", "0");
        stats_event (NULL, "stats", "0");
        
        /* global accumulating stats */
        stats_event (NULL, "client_connections", "0");
        stats_event (NULL, "source_client_connections", "0");
        stats_event (NULL, "source_relay_connections", "0");
        stats_event (NULL, "source_total_connections", "0");
        stats_event (NULL, "stats_connections", "0");
        stats_event (NULL, "listener_connections", "0");
        INFO0 ("stats thread started");
    }

    while (_stats_running) {
      kitsune_update("stats"); /**DSU updatepoint */
        if (_global_event_queue != NULL) {
            /* grab the next event from the queue */
            thread_mutex_lock(&_global_event_mutex);
            event = (stats_event_t *)_global_event_queue;
            _global_event_queue = event->next;
            thread_mutex_unlock(&_global_event_mutex);

            event->next = NULL;

            thread_mutex_lock(&_stats_mutex);

            /* check if we are dealing with a global or source event */
            if (event->source == NULL)
                process_global_event (event);
            else
                process_source_event (event);
            
            /* now we have an event that's been processed into the running stats */
            /* this event should get copied to event listeners' queues */
            listener = (event_listener_t *)_event_listeners;
            while (listener) {
                copy = _copy_event(event);
                thread_mutex_lock(listener->mutex);
                _add_event_to_queue(copy, listener->queue);
                thread_mutex_unlock(listener->mutex);

                listener = listener->next;
            }

            /* now we need to destroy the event */
            _free_event(event);

            thread_mutex_unlock(&_stats_mutex);
            continue;
        }

        thread_sleep(300000);
    }

    return NULL;
}