void _dump_stats_to_queue(stats_event_t **queue) { avl_node *node; avl_node *node2; stats_event_t *event; stats_source_t *source; thread_mutex_lock(&_stats_mutex); /* first we fill our queue with the current stats */ /* start with the global stats */ node = avl_get_first(_stats.global_tree); while (node) { event = _make_event_from_node((stats_node_t *)node->key, NULL); _add_event_to_queue(event, queue); node = avl_get_next(node); } /* now the stats for each source */ node = avl_get_first(_stats.source_tree); while (node) { source = (stats_source_t *)node->key; node2 = avl_get_first(source->stats_tree); while (node2) { event = _make_event_from_node((stats_node_t *)node2->key, source->source); _add_event_to_queue(event, queue); node2 = avl_get_next(node2); } node = avl_get_next(node); } thread_mutex_unlock(&_stats_mutex); }
/* factoring out code for stats loops ** this function copies all stats to queue, and registers ** the queue for all new events atomically. ** note: mutex must already be created! */ static void _register_listener (event_listener_t *listener) { avl_node *node; avl_node *node2; stats_event_t *event; stats_source_t *source; thread_mutex_lock(&_stats_mutex); /* first we fill our queue with the current stats */ /* start with the global stats */ node = avl_get_first(_stats.global_tree); while (node) { event = _make_event_from_node((stats_node_t *) node->key, NULL); _add_event_to_queue(event, &listener->queue); node = avl_get_next(node); } /* now the stats for each source */ node = avl_get_first(_stats.source_tree); while (node) { source = (stats_source_t *)node->key; node2 = avl_get_first(source->stats_tree); while (node2) { event = _make_event_from_node((stats_node_t *)node2->key, source->source); _add_event_to_queue (event, &listener->queue); node2 = avl_get_next(node2); } node = avl_get_next(node); } /* now we register to receive future event notices */ listener->next = (event_listener_t *)_event_listeners; _event_listeners = listener; thread_mutex_unlock(&_stats_mutex); }
static void *_stats_thread(void *arg) { stats_event_t *event; stats_event_t *copy; stats_node_t *node; stats_node_t *anode; stats_source_t *snode; stats_source_t *asnode; event_listener_t *listener; avl_node *avlnode; while (_stats_running) { thread_mutex_lock(&_global_event_mutex); if (_global_event_queue != NULL) { /* grab the next event from the queue */ event = _global_event_queue; _global_event_queue = event->next; event->next = NULL; thread_mutex_unlock(&_global_event_mutex); thread_mutex_lock(&_stats_mutex); if (event->source == NULL) { /* we have a global event */ if (event->value != NULL) { /* adding/updating */ node = _find_node(_stats.global_tree, event->name); if (node == NULL) { /* add node */ anode = (stats_node_t *)malloc(sizeof(stats_node_t)); anode->name = (char *)strdup(event->name); anode->value = (char *)strdup(event->value); avl_insert(_stats.global_tree, (void *)anode); } else { /* update node */ free(node->value); node->value = (char *)strdup(event->value); } } else { /* we're deleting */ node = _find_node(_stats.global_tree, event->name); if (node != NULL) avl_delete(_stats.global_tree, (void *)node, _free_stats); } } else { /* we have a source event */ snode = _find_source(_stats.source_tree, event->source); if (snode != NULL) { /* this is a source we already have a tree for */ if (event->value != NULL) { /* we're add/updating */ node = _find_node(snode->stats_tree, event->name); if (node == NULL) { /* adding node */ anode = (stats_node_t *)malloc(sizeof(stats_node_t)); anode->name = (char *)strdup(event->name); anode->value = (char *)strdup(event->value); avl_insert(snode->stats_tree, (void *)anode); } else { /* updating node */ free(node->value); node->value = (char *)strdup(event->value); } } else { /* we're deleting */ node = _find_node(snode->stats_tree, event->name); if (node != NULL) { avl_delete(snode->stats_tree, (void *)node, _free_stats); avlnode = avl_get_first(snode->stats_tree); if (avlnode == NULL) { avl_delete(_stats.source_tree, (void *)snode, _free_source_stats); } } } } else { /* this is a new source */ asnode = (stats_source_t *)malloc(sizeof(stats_source_t)); asnode->source = (char *)strdup(event->source); asnode->stats_tree = avl_tree_new(_compare_stats, NULL); anode = (stats_node_t *)malloc(sizeof(stats_node_t)); anode->name = (char *)strdup(event->name); anode->value = (char *)strdup(event->value); avl_insert(asnode->stats_tree, (void *)anode); avl_insert(_stats.source_tree, (void *)asnode); } } /* now we have an event that's been processed into the running stats */ /* this event should get copied to event listeners' queues */ listener = _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; } thread_cond_broadcast(&_event_signal_cond); /* 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); } /* wake the other threads so they can shut down cleanly */ thread_cond_broadcast(&_event_signal_cond); thread_exit(0); return NULL; }
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; }
static void queue_global_event (stats_event_t *event) { thread_mutex_lock(&_global_event_mutex); _add_event_to_queue (event, &_global_event_queue); thread_mutex_unlock(&_global_event_mutex); }
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; }