void stats_sendxml(client_t *client) { int bytes; stats_event_t *event; stats_event_t *queue; xmlDocPtr doc; xmlNodePtr node, srcnode; int len; xmlChar *buff = NULL; source_xml_t *snd; source_xml_t *src_nodes = NULL; queue = NULL; _dump_stats_to_queue(&queue); doc = xmlNewDoc("1.0"); node = xmlNewDocNode(doc, NULL, "icestats", NULL); xmlDocSetRootElement(doc, node); event = _get_event_from_queue(&queue); while (event) { if (event->source == NULL) { xmlNewChild(node, NULL, event->name, event->value); } else { srcnode = _find_xml_node(event->source, &src_nodes, node); xmlNewChild(srcnode, NULL, event->name, event->value); } _free_event(event); event = _get_event_from_queue(&queue); } xmlDocDumpMemory(doc, &buff, &len); xmlFreeDoc(doc); client->respcode = 200; bytes = sock_write(client->con->sock, "HTTP/1.0 200 OK\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml\r\n" "\r\n", len); if (bytes > 0) client->con->sent_bytes += bytes; else goto send_error; bytes = sock_write_bytes(client->con->sock, buff, len); if (bytes > 0) client->con->sent_bytes += bytes; send_error: while (src_nodes) { snd = src_nodes->next; free(src_nodes->mount); free(src_nodes); src_nodes = snd; } if (buff) xmlFree(buff); }
void stats_get_xml(xmlDocPtr *doc, int show_hidden) { stats_event_t *event; stats_event_t *queue; xmlNodePtr node, srcnode; source_xml_t *src_nodes = NULL; source_xml_t *next; queue = NULL; _dump_stats_to_queue(&queue); *doc = xmlNewDoc("1.0"); node = xmlNewDocNode(*doc, NULL, "icestats", NULL); xmlDocSetRootElement(*doc, node); event = _get_event_from_queue(&queue); while (event) { if (event->hidden <= show_hidden) { xmlChar *name, *value; name = xmlEncodeEntitiesReentrant (*doc, event->name); value = xmlEncodeEntitiesReentrant (*doc, event->value); srcnode = node; if (event->source) { srcnode = _find_xml_node(event->source, &src_nodes, node); } xmlNewChild(srcnode, NULL, name, value); xmlFree (value); xmlFree (name); } _free_event(event); event = _get_event_from_queue(&queue); } while (src_nodes) { next = src_nodes->next; free(src_nodes->mount); free(src_nodes); src_nodes = next; } }
void stats_get_xml(xmlDocPtr *doc) { stats_event_t *event; stats_event_t *queue; xmlNodePtr node, srcnode; source_xml_t *src_nodes = NULL; source_xml_t *next; queue = NULL; _dump_stats_to_queue(&queue); *doc = xmlNewDoc("1.0"); node = xmlNewDocNode(*doc, NULL, "icestats", NULL); xmlDocSetRootElement(*doc, node); event = _get_event_from_queue(&queue); while (event) { if (event->source == NULL) { xmlNewChild(node, NULL, event->name, event->value); } else { srcnode = _find_xml_node(event->source, &src_nodes, node); xmlNewChild(srcnode, NULL, event->name, event->value); } _free_event(event); event = _get_event_from_queue(&queue); } while (src_nodes) { next = src_nodes->next; free(src_nodes->mount); free(src_nodes); src_nodes = next; } }
void *stats_connection(void *arg) { client_t *client = (client_t *)arg; stats_event_t *event; event_listener_t listener; ICECAST_LOG_INFO("stats client starting"); event_queue_init (&listener.queue); /* increment the thread count */ thread_mutex_lock(&_stats_mutex); _stats_threads++; stats_event_args (NULL, "stats", "%d", _stats_threads); thread_mutex_unlock(&_stats_mutex); thread_mutex_create (&(listener.mutex)); _register_listener (&listener); while (_stats_running) { thread_mutex_lock (&listener.mutex); event = _get_event_from_queue (&listener.queue); thread_mutex_unlock (&listener.mutex); if (event != NULL) { if (_send_event_to_client(event, client) < 0) { _free_event(event); break; } _free_event(event); continue; } thread_sleep (500000); } thread_mutex_lock(&_stats_mutex); _unregister_listener (&listener); _stats_threads--; stats_event_args (NULL, "stats", "%d", _stats_threads); thread_mutex_unlock(&_stats_mutex); thread_mutex_destroy (&listener.mutex); client_destroy (client); ICECAST_LOG_INFO("stats client finished"); return NULL; }
void *stats_connection(void *arg) { stats_connection_t *statcon = (stats_connection_t *)arg; stats_event_t *local_event_queue = NULL; mutex_t local_event_mutex; stats_event_t *event; /* increment the thread count */ thread_mutex_lock(&_stats_mutex); _stats_threads++; thread_mutex_unlock(&_stats_mutex); thread_mutex_create(&local_event_mutex); _atomic_get_and_register(&local_event_queue, &local_event_mutex); while (_stats_running) { thread_mutex_lock(&local_event_mutex); event = _get_event_from_queue(&local_event_queue); if (event != NULL) { if (!_send_event_to_client(event, statcon->con)) { _free_event(event); thread_mutex_unlock(&local_event_mutex); break; } _free_event(event); } else { thread_mutex_unlock(&local_event_mutex); thread_cond_wait(&_event_signal_cond); continue; } thread_mutex_unlock(&local_event_mutex); } thread_mutex_destroy(&local_event_mutex); thread_mutex_lock(&_stats_mutex); _stats_threads--; thread_mutex_unlock(&_stats_mutex); thread_exit(0); return NULL; }
void stats_shutdown(void) { int n; if (!_stats_running) /* We can't shutdown if we're not running. */ return; /* wait for thread to exit */ _stats_running = 0; thread_join(_stats_thread_id); /* wait for other threads to shut down */ do { thread_sleep(300000); thread_mutex_lock(&_stats_mutex); n = _stats_threads; thread_mutex_unlock(&_stats_mutex); } while (n > 0); ICECAST_LOG_INFO("stats thread finished"); /* free the queues */ /* destroy the queue mutexes */ thread_mutex_destroy(&_global_event_mutex); thread_mutex_destroy(&_stats_mutex); avl_tree_free(_stats.source_tree, _free_source_stats); avl_tree_free(_stats.global_tree, _free_stats); while (1) { stats_event_t *event = _get_event_from_queue (&_global_event_queue); if (event == NULL) break; if(event->source) free(event->source); if(event->value) free(event->value); if(event->name) free(event->name); free(event); } }
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; }