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_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); }
/* * Clear all events from the event list. Must already have the aeld_mutex * locked. */ static void _clear_event_list(alpsc_ev_app_t *list, int32_t *size) { int32_t i; for (i = 0; i < *size; i++) { _free_event(&list[i]); } *size = 0; return; }
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; } }
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; }
/* * For starting apps, push to the app list. For ending apps, removes from the * app list. For suspend/resume apps, edits the app list. Always adds to the * event list. */ static void _update_app(struct job_record *job_ptr, struct step_record *step_ptr, alpsc_ev_app_state_e state) { uint64_t apid; int32_t i; alpsc_ev_app_t app; int found; // If aeld thread isn't running, do nothing if (aeld_running == 0) { return; } // Fill in the new event _initialize_event(&app, job_ptr, step_ptr, state); pthread_mutex_lock(&aeld_mutex); // Add it to the event list, only if aeld is up if (aeld_running == 2) { _add_to_app_list(&event_list, &event_list_size, &event_list_capacity, &app); } // Now deal with the app list // Maintain app list even if aeld is down, so we have it ready when // it comes up. switch(state) { case ALPSC_EV_START: // This is new, add to the app list _add_to_app_list(&app_list, &app_list_size, &app_list_capacity, &app); break; case ALPSC_EV_END: // Search for the app matching this apid found = 0; apid = SLURM_ID_HASH(job_ptr->job_id, step_ptr->step_id); for (i = 0; i < app_list_size; i++) { if (app_list[i].apid == apid) { found = 1; // Free allocated info _free_event(&app_list[i]); // Copy last list entry to this spot if (i < app_list_size - 1) { memcpy(&app_list[i], &app_list[app_list_size - 1], sizeof(alpsc_ev_app_t)); } app_list_size--; break; } } // Not found if (!found) { debug("Application %"PRIu64" not found in app list", apid); } break; case ALPSC_EV_SUSPEND: case ALPSC_EV_RESUME: // Search for the app matching this apid apid = SLURM_ID_HASH(job_ptr->job_id, step_ptr->step_id); for (i = 0; i < app_list_size; i++) { if (app_list[i].apid == apid) { // Found it, update the state app_list[i].state = (state == ALPSC_EV_SUSPEND) ? ALPSC_EV_SUSPEND : ALPSC_EV_START; break; } } // Not found if (i >= app_list_size) { debug("Application %"PRIu64" not found in app list", apid); } break; default: break; } pthread_mutex_unlock(&aeld_mutex); _free_event(&app); return; }
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; }