static char *_get_stats(const char *source, const char *name) { stats_node_t *stats = NULL; stats_source_t *src = NULL; char *value = NULL; if (source == NULL) { avl_tree_rlock (_stats.global_tree); stats = _find_node(_stats.global_tree, name); if (stats) value = (char *)strdup(stats->value); avl_tree_unlock (_stats.global_tree); } else { avl_tree_rlock (_stats.source_tree); src = _find_source(_stats.source_tree, source); if (src) { avl_tree_rlock (src->stats_tree); avl_tree_unlock (_stats.source_tree); stats = _find_node(src->stats_tree, name); if (stats) value = (char *)strdup(stats->value); avl_tree_unlock (src->stats_tree); } else avl_tree_unlock (_stats.source_tree); } return value; }
long stats_handle (const char *mount) { stats_source_t *src_stats; if (mount == NULL) return 0; avl_tree_wlock (_stats.source_tree); src_stats = _find_source(_stats.source_tree, mount); if (src_stats == NULL) { src_stats = (stats_source_t *)calloc (1, sizeof (stats_source_t)); if (src_stats == NULL) abort(); DEBUG1 ("new source stat %s", mount); src_stats->source = (char *)strdup (mount); src_stats->stats_tree = avl_tree_new (_compare_stats, NULL); src_stats->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN; avl_insert (_stats.source_tree, (void *)src_stats); } avl_tree_wlock (src_stats->stats_tree); avl_tree_unlock (_stats.source_tree); return (long)src_stats; }
static void process_source_event (stats_event_t *event) { stats_source_t *snode; avl_tree_wlock (_stats.source_tree); snode = _find_source(_stats.source_tree, event->source); if (snode == NULL) { if (event->action == STATS_EVENT_REMOVE) { avl_tree_unlock (_stats.source_tree); return; } snode = (stats_source_t *)calloc(1,sizeof(stats_source_t)); if (snode == NULL) abort(); DEBUG1 ("new source stat %s", event->source); snode->source = (char *)strdup(event->source); snode->stats_tree = avl_tree_new(_compare_stats, NULL); snode->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN; avl_insert(_stats.source_tree, (void *)snode); } if (event->action == STATS_EVENT_REMOVE && event->name == NULL) { int fallback_stream = 0; avl_tree_wlock (snode->stats_tree); fallback_stream = _find_node (snode->stats_tree, "fallback") == NULL ? 1 : 0; if (fallback_stream) avl_delete(_stats.source_tree, (void *)snode, _free_source_stats); else avl_tree_unlock (snode->stats_tree); avl_tree_unlock (_stats.source_tree); return; } avl_tree_wlock (snode->stats_tree); avl_tree_unlock (_stats.source_tree); process_source_stat (snode, event); avl_tree_unlock (snode->stats_tree); }
static char *_get_stats(char *source, char *name) { stats_node_t *stats = NULL; stats_source_t *src = NULL; char *value = NULL; thread_mutex_lock(&_stats_mutex); if (source == NULL) { stats = _find_node(_stats.global_tree, name); } else { src = _find_source(_stats.source_tree, source); if (src) { stats = _find_node(src->stats_tree, name); } } if (stats) value = (char *)strdup(stats->value); thread_mutex_unlock(&_stats_mutex); return value; }
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 process_source_event (stats_event_t *event) { stats_source_t *snode = _find_source(_stats.source_tree, event->source); if (snode == NULL) { if (event->action == STATS_EVENT_REMOVE) return; snode = (stats_source_t *)calloc(1,sizeof(stats_source_t)); if (snode == NULL) return; ICECAST_LOG_DEBUG("new source stat %s", event->source); snode->source = (char *)strdup(event->source); snode->stats_tree = avl_tree_new(_compare_stats, NULL); if (event->action == STATS_EVENT_HIDDEN) snode->hidden = 1; else snode->hidden = 0; avl_insert(_stats.source_tree, (void *) snode); } if (event->name) { stats_node_t *node = _find_node(snode->stats_tree, event->name); if (node == NULL) { if (event->action == STATS_EVENT_REMOVE) return; /* adding node */ if (event->value) { ICECAST_LOG_DEBUG("new node %s (%s)", event->name, event->value); node = (stats_node_t *)calloc(1,sizeof(stats_node_t)); node->name = (char *)strdup(event->name); node->value = (char *)strdup(event->value); node->hidden = snode->hidden; avl_insert(snode->stats_tree, (void *)node); } return; } if (event->action == STATS_EVENT_REMOVE) { ICECAST_LOG_DEBUG("delete node %s", event->name); avl_delete(snode->stats_tree, (void *)node, _free_stats); return; } modify_node_event (node, event); return; } if (event->action == STATS_EVENT_HIDDEN) { avl_node *node = avl_get_first (snode->stats_tree); if (event->value) snode->hidden = 1; else snode->hidden = 0; while (node) { stats_node_t *stats = (stats_node_t*)node->key; stats->hidden = snode->hidden; node = avl_get_next (node); } return; } if (event->action == STATS_EVENT_REMOVE) { ICECAST_LOG_DEBUG("delete source node %s", event->source); avl_delete(_stats.source_tree, (void *)snode, _free_source_stats); } }