/* This removes any source stats from virtual mountpoints, ie mountpoints * where no source_t exists. This function requires the global sources lock * to be held before calling. */ void stats_clear_virtual_mounts (void) { avl_node *snode; avl_tree_wlock (_stats.source_tree); snode = avl_get_first(_stats.source_tree); while (snode) { stats_source_t *src = (stats_source_t *)snode->key; source_t *source = source_find_mount_raw (src->source); if (source == NULL) { stats_node_t *node; avl_tree_wlock (src->stats_tree); node = _find_node (src->stats_tree, "fallback"); if (node == NULL) { /* no source_t and no fallback file stat, so delete */ snode = avl_get_next (snode); avl_delete (_stats.source_tree, src, _free_source_stats); continue; } avl_tree_unlock (src->stats_tree); } snode = avl_get_next (snode); } avl_tree_unlock (_stats.source_tree); }
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); }
/* build an XML doc containing information about currently running sources. * If a mountpoint is passed then that source will not be added to the XML * doc even if the source is running */ xmlDocPtr admin_build_sourcelist (const char *mount) { avl_node *node; source_t *source; xmlNodePtr xmlnode, srcnode; xmlDocPtr doc; char buf[22]; time_t now = time(NULL); doc = xmlNewDoc("1.0"); xmlnode = xmlNewDocNode(doc, NULL, "icestats", NULL); xmlDocSetRootElement(doc, xmlnode); if (mount) { xmlNewChild(xmlnode, NULL, "current_source", mount); } node = avl_get_first(global.source_tree); while(node) { source = (source_t *)node->key; if (mount && strcmp (mount, source->mount) == 0) { node = avl_get_next (node); continue; } if (source->running) { srcnode = xmlNewChild(xmlnode, NULL, "source", NULL); xmlSetProp(srcnode, "mount", source->mount); xmlNewChild(srcnode, NULL, "fallback", (source->fallback_mount != NULL)? source->fallback_mount:""); snprintf(buf, sizeof(buf), "%ld", source->listeners); xmlNewChild(srcnode, NULL, "listeners", buf); snprintf(buf, sizeof(buf), "%lu", (unsigned long)(now - source->con->con_time)); xmlNewChild(srcnode, NULL, "Connected", buf); xmlNewChild(srcnode, NULL, "content-type", source->format->contenttype); if (source->authenticator) { xmlNewChild(srcnode, NULL, "authenticator", source->authenticator->type); } } node = avl_get_next(node); } return(doc); }
int avl_get_span_by_two_keys (avl_tree * tree, void * low_key, void * high_key, unsigned long * low, unsigned long * high) { unsigned long i, j; avl_node * low_node, * high_node; int order; /* we may need to swap them */ order = tree->compare_fun (tree->compare_arg, low_key, high_key); if (order > 0) { void * temp = low_key; low_key = high_key; high_key = temp; } low_node = avl_get_index_by_key (tree, low_key, &i); high_node = avl_get_index_by_key (tree, high_key, &j); if (low_node) { avl_node * left; /* search left */ left = avl_get_prev (low_node); while (left && (i > 0) && (tree->compare_fun (tree->compare_arg, low_key, left->key) == 0)) { left = avl_get_prev (left); i = i - 1; } } else { i = i + 1; } if (high_node) { avl_node * right; /* search right */ right = avl_get_next (high_node); while (right && (j <= tree->length) && (tree->compare_fun (tree->compare_arg, high_key, right->key) == 0)) { right = avl_get_next (right); j = j + 1; } } else { j = j + 1; } *low = i; *high = j; return 0; }
static int command_alloc(client_t *client) { xmlDocPtr doc = xmlNewDoc (XMLSTR("1.0")); xmlNodePtr rootnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); avl_node *node; xmlDocSetRootElement(doc, rootnode); avl_tree_rlock (global.alloc_tree); node = avl_get_first (global.alloc_tree); while (node) { alloc_node *an = node->key; char value[25]; xmlNodePtr bnode = xmlNewChild (rootnode, NULL, XMLSTR("block"), NULL); xmlSetProp (bnode, XMLSTR("name"), XMLSTR(an->name)); snprintf (value, sizeof value, "%d", an->count); xmlNewChild (bnode, NULL, XMLSTR("count"), XMLSTR(value)); snprintf (value, sizeof value, "%d", an->allocated); xmlNewChild (bnode, NULL, XMLSTR("allocated"), XMLSTR(value)); node = avl_get_next (node); } avl_tree_unlock (global.alloc_tree); return admin_send_response (doc, client, RAW, "stats.xsl"); }
// write filename extension for matching mime type. // lookup matching mime type and write extension into buffer space provided void fserve_write_mime_ext (const char *mimetype, char *buf, unsigned int len) { avl_node *node; int semi; if (mimetype == NULL || buf == NULL || len > 2000) return; semi = strcspn (mimetype, "; "); if (semi == 0) return; if (mimetype [semi]) { char *mt = alloca (++semi); snprintf (mt, semi, "%s", mimetype); mimetype = (const char *)mt; } thread_spin_lock (&pending_lock); node = avl_get_first (mimetypes); while (node) { mime_type *mime = (mime_type *)node->key; if (mime && strcmp (mime->type, mimetype) == 0) { snprintf (buf, len, "%s", mime->ext); break; } node = avl_get_next (node); } thread_spin_unlock (&pending_lock); }
int fserve_kill_client (client_t *client, const char *mount, int response) { int loop = 2, id; fbinfo finfo; xmlDocPtr doc; xmlNodePtr node; const char *idtext, *v = "0"; char buf[50]; finfo.flags = 0; finfo.mount = (char*)mount; finfo.limit = 0; finfo.fallback = NULL; idtext = httpp_get_query_param (client->parser, "id"); if (idtext == NULL) return client_send_400 (client, "missing parameter id"); id = atoi(idtext); doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); snprintf (buf, sizeof(buf), "Client %d not found", id); avl_tree_rlock (fh_cache); while (1) { avl_node *node; fh_node *fh = find_fh (&finfo); if (fh) { thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); node = avl_get_first (fh->clients); while (node) { client_t *listener = (client_t *)node->key; if (listener->connection.id == id) { listener->connection.error = 1; snprintf (buf, sizeof(buf), "Client %d removed", id); v = "1"; loop = 0; break; } node = avl_get_next (node); } thread_mutex_unlock (&fh->lock); avl_tree_rlock (fh_cache); } if (loop == 0) break; loop--; if (loop == 1) finfo.flags = FS_FALLBACK; } avl_tree_unlock (fh_cache); xmlNewChild (node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewChild (node, NULL, XMLSTR("return"), XMLSTR(v)); return admin_send_response (doc, client, response, "response.xsl"); }
void stats_global_calc (void) { stats_event_t event; avl_node *anode; char buffer [VAL_BUFSIZE]; connection_stats (); avl_tree_rlock (_stats.global_tree); anode = avl_get_first(_stats.global_tree); while (anode) { stats_node_t *node = (stats_node_t *)anode->key; if (node->flags & STATS_REGULAR) stats_listener_send (node->flags, "EVENT global %s %s\n", node->name, node->value); anode = avl_get_next (anode); } avl_tree_unlock (_stats.global_tree); build_event (&event, NULL, "outgoing_kbitrate", buffer); event.flags = STATS_COUNTERS|STATS_HIDDEN; snprintf (buffer, sizeof(buffer), "%" PRIu64, (int64_t)global_getrate_avg (global.out_bitrate) * 8 / 1024); process_event (&event); }
int fserve_list_clients_xml (xmlNodePtr parent, fbinfo *finfo) { int ret = 0; fh_node *fh; avl_node *anode; avl_tree_rlock (fh_cache); fh = find_fh (finfo); if (fh == NULL) { avl_tree_unlock (fh_cache); return 0; } thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); anode = avl_get_first (fh->clients); while (anode) { client_t *listener = (client_t *)anode->key; stats_listener_to_xml (listener, parent); ret++; anode = avl_get_next (anode); } thread_mutex_unlock (&fh->lock); return ret; }
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int flags) { avl_node *avlnode; xmlNodePtr ret = NULL; /* general stats first */ avl_tree_rlock (_stats.global_tree); avlnode = avl_get_first(_stats.global_tree); while (avlnode) { stats_node_t *stat = avlnode->key; if (stat->flags & flags) xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode = avl_get_next (avlnode); } avl_tree_unlock (_stats.global_tree); /* now per mount stats */ avl_tree_rlock (_stats.source_tree); avlnode = avl_get_first(_stats.source_tree); while (avlnode) { stats_source_t *source = (stats_source_t *)avlnode->key; if (((flags&STATS_HIDDEN) || (source->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) && (show_mount == NULL || strcmp (show_mount, source->source) == 0)) { avl_node *avlnode2; xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL); avl_tree_rlock (source->stats_tree); avlnode2 = avl_get_first (source->stats_tree); xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source)); if (ret == NULL) ret = xmlnode; while (avlnode2) { stats_node_t *stat = avlnode2->key; if ((flags&STATS_HIDDEN) || (stat->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode2 = avl_get_next (avlnode2); } avl_tree_unlock (source->stats_tree); } avlnode = avl_get_next (avlnode); } avl_tree_unlock (_stats.source_tree); return ret; }
/* Check whether this client is currently on this mount, the client may be * on either the active or pending lists. * return 1 if ok to add or 0 to prevent */ static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth) { /* allow multiple authenticated relays */ if (client->username == NULL) return 1; if (auth && auth->allow_duplicate_users == 0) { avl_node *node; avl_tree_rlock (source->client_tree); node = avl_get_first (source->client_tree); while (node) { client_t *existing_client = (client_t *)node->key; if (existing_client->username && strcmp (existing_client->username, client->username) == 0) { avl_tree_unlock (source->client_tree); return 0; } node = avl_get_next (node); } avl_tree_unlock (source->client_tree); avl_tree_rlock (source->pending_tree); node = avl_get_first (source->pending_tree); while (node) { client_t *existing_client = (client_t *)node->key; if (existing_client->username && strcmp (existing_client->username, client->username) == 0) { avl_tree_unlock (source->pending_tree); return 0; } node = avl_get_next (node); } avl_tree_unlock (source->pending_tree); } return 1; }
/* Check for changes in the YP servers configured */ static void check_servers (void) { struct yp_server *server = (struct yp_server *)active_yps, **server_p = (struct yp_server **)&active_yps; while (server) { if (server->remove) { struct yp_server *to_go = server; DEBUG1 ("YP server \"%s\"removed", server->url); *server_p = server->next; server = server->next; destroy_yp_server (to_go); continue; } server_p = &server->next; server = server->next; } /* add new server entries */ while (pending_yps) { avl_node *node; server = (struct yp_server *)pending_yps; pending_yps = server->next; DEBUG1("Add pending yps %s", server->url); server->next = (struct yp_server *)active_yps; active_yps = server; /* new YP server configured, need to populate with existing sources */ avl_tree_rlock (global.source_tree); node = avl_get_first (global.source_tree); while (node) { ypdata_t *yp; source_t *source = node->key; thread_rwlock_rlock (&source->lock); if (source->yp_public && (yp = create_yp_entry (source->mount)) != NULL) { DEBUG1 ("Adding existing mount %s", source->mount); yp->server = server; yp->touch_interval = server->touch_interval; yp->next = server->mounts; server->mounts = yp; } thread_rwlock_unlock (&source->lock); node = avl_get_next (node); } avl_tree_unlock (global.source_tree); } }
/* 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 xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int hidden) { avl_node *avlnode; xmlNodePtr ret = NULL; thread_mutex_lock(&_stats_mutex); /* general stats first */ avlnode = avl_get_first(_stats.global_tree); while (avlnode) { stats_node_t *stat = avlnode->key; if (stat->hidden <= hidden) xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode = avl_get_next (avlnode); } /* now per mount stats */ avlnode = avl_get_first(_stats.source_tree); while (avlnode) { stats_source_t *source = (stats_source_t *)avlnode->key; if (source->hidden <= hidden && (show_mount == NULL || strcmp (show_mount, source->source) == 0)) { avl_node *avlnode2 = avl_get_first (source->stats_tree); xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL); xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source)); if (ret == NULL) ret = xmlnode; while (avlnode2) { stats_node_t *stat = avlnode2->key; xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode2 = avl_get_next (avlnode2); } } avlnode = avl_get_next (avlnode); } thread_mutex_unlock(&_stats_mutex); return ret; }
static void command_show_listeners(client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode, listenernode; avl_node *client_node; client_t *current; char buf[22]; char *userAgent = NULL; time_t now = time(NULL); doc = xmlNewDoc("1.0"); node = xmlNewDocNode(doc, NULL, "icestats", NULL); srcnode = xmlNewChild(node, NULL, "source", NULL); xmlSetProp(srcnode, "mount", source->mount); xmlDocSetRootElement(doc, node); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", source->listeners); xmlNewChild(srcnode, NULL, "Listeners", buf); avl_tree_rlock(source->client_tree); client_node = avl_get_first(source->client_tree); while(client_node) { current = (client_t *)client_node->key; listenernode = xmlNewChild(srcnode, NULL, "listener", NULL); xmlNewChild(listenernode, NULL, "IP", current->con->ip); userAgent = httpp_getvar(current->parser, "user-agent"); if (userAgent) { xmlNewChild(listenernode, NULL, "UserAgent", userAgent); } else { xmlNewChild(listenernode, NULL, "UserAgent", "Unknown"); } memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", now - current->con->con_time); xmlNewChild(listenernode, NULL, "Connected", buf); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%lu", current->con->id); xmlNewChild(listenernode, NULL, "ID", buf); if (current->username) { xmlNewChild(listenernode, NULL, "username", current->username); } client_node = avl_get_next(client_node); } avl_tree_unlock(source->client_tree); admin_send_response(doc, client, response, LISTCLIENTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); client_destroy(client); }
int avl_get_span_by_key (avl_tree * tree, void * key, unsigned long * low, unsigned long * high) { unsigned long m, i, j; avl_node * node; node = avl_get_index_by_key (tree, key, &m); /* did we find an exact match? * if so, we have to search left and right * to find the span, since we know nothing about * the arrangement of like keys. */ if (node) { avl_node * left, * right; /* search left */ left = avl_get_prev (node); i = m; while (left && (i > 0) && (tree->compare_fun (tree->compare_arg, key, left->key) == 0)) { left = avl_get_prev (left); i = i - 1; } /* search right */ right = avl_get_next (node); j = m; while (right && (j <= tree->length) && (tree->compare_fun (tree->compare_arg, key, right->key) == 0)) { right = avl_get_next (right); j = j + 1; } *low = i; *high = j + 1; return 0; } else { *low = *high = m; } return 0; }
/* populate within srcnode, groups of 0 or more listener tags detailing * information about each listener connected on the provide source. */ void admin_source_listeners (source_t *source, xmlNodePtr srcnode) { avl_node *node; if (source == NULL) return; node = avl_get_first (source->clients); while (node) { client_t *listener = (client_t *)node->key; stats_listener_to_xml (listener, srcnode); node = avl_get_next (node); } }
/* This removes any source stats from virtual mountpoints, ie mountpoints * where no source_t exists. This function requires the global sources lock * to be held before calling. */ void stats_clear_virtual_mounts (void) { avl_node *snode; thread_mutex_lock (&_stats_mutex); snode = avl_get_first(_stats.source_tree); while (snode) { stats_source_t *src = (stats_source_t *)snode->key; source_t *source = source_find_mount_raw (src->source); if (source == NULL) { /* no source_t is reserved so remove them now */ snode = avl_get_next (snode); ICECAST_LOG_DEBUG("releasing %s stats", src->source); avl_delete (_stats.source_tree, src, _free_source_stats); continue; } snode = avl_get_next (snode); } thread_mutex_unlock (&_stats_mutex); }
static void command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); avl_tree_rlock (global.source_tree); if (response == PLAINTEXT) { char buffer [4096], *buf = buffer; unsigned int remaining = sizeof (buffer); int ret = snprintf (buffer, remaining, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); avl_node *node = avl_get_first(global.source_tree); while (node && ret > 0 && (unsigned)ret < remaining) { source_t *source = (source_t *)node->key; node = avl_get_next(node); if (source->hidden) continue; remaining -= ret; buf += ret; ret = snprintf (buf, remaining, "%s\n", source->mount); } avl_tree_unlock (global.source_tree); /* handle last line */ if (ret > 0 && (unsigned)ret < remaining) { remaining -= ret; buf += ret; } sock_write_bytes (client->con->sock, buffer, sizeof (buffer)-remaining); } else { xmlDocPtr doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); } client_destroy(client); return; }
/* return a list of blocks which contain lines of text. Each line is a mountpoint * reference that a slave will use for relaying. The prepend setting is to indicate * if some something else needs to be added to each line. */ refbuf_t *stats_get_streams (int prepend) { #define STREAMLIST_BLKSIZE 4096 avl_node *node; unsigned int remaining = STREAMLIST_BLKSIZE, prelen; refbuf_t *start = refbuf_new (remaining), *cur = start; const char *pre = ""; char *buffer = cur->data; if (prepend) pre = "/admin/streams?mount="; prelen = strlen (pre); /* now the stats for each source */ avl_tree_rlock (_stats.source_tree); node = avl_get_first(_stats.source_tree); while (node) { int ret; stats_source_t *source = (stats_source_t *)node->key; if ((source->flags & STATS_HIDDEN) == 0) { if (remaining <= strlen (source->source) + prelen + 3) { cur->len = STREAMLIST_BLKSIZE - remaining; cur->next = refbuf_new (STREAMLIST_BLKSIZE); remaining = STREAMLIST_BLKSIZE; cur = cur->next; buffer = cur->data; } ret = snprintf (buffer, remaining, "%s%s\r\n", pre, source->source); if (ret > 0) { buffer += ret; remaining -= ret; } } node = avl_get_next(node); } avl_tree_unlock (_stats.source_tree); cur->len = STREAMLIST_BLKSIZE - remaining; return start; }
void thread_exit_c(long val, int line, char *file) { thread_type *th = thread_self(); #if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES) if (th) { avl_node *node; mutex_t *tmutex; char name[40]; _mutex_lock(&_mutextree_mutex); while (node) { tmutex = (mutex_t *)node->key; if (tmutex->thread_id == th->thread_id) { LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]", th->thread_id, th->name, file, line, mutex_to_string(tmutex, name)); } node = avl_get_next (node); } _mutex_unlock(&_mutextree_mutex); } #endif if (th && th->detached) { #ifdef THREAD_DEBUG LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); #endif _mutex_lock(&_threadtree_mutex); avl_delete(_threadtree, th, _free_thread); _mutex_unlock(&_threadtree_mutex); } pthread_exit ((void*)val); }
refbuf_t *stats_get_streams (void) { #define STREAMLIST_BLKSIZE 4096 avl_node *node; unsigned int remaining = STREAMLIST_BLKSIZE; refbuf_t *start = refbuf_new (remaining), *cur = start; char *buffer = cur->data; /* now the stats for each source */ thread_mutex_lock (&_stats_mutex); node = avl_get_first(_stats.source_tree); while (node) { int ret; stats_source_t *source = (stats_source_t *)node->key; if (source->hidden == 0) { if (remaining <= strlen (source->source) + 3) { cur->len = STREAMLIST_BLKSIZE - remaining; cur->next = refbuf_new (STREAMLIST_BLKSIZE); remaining = STREAMLIST_BLKSIZE; cur = cur->next; buffer = cur->data; } ret = snprintf (buffer, remaining, "%s\r\n", source->source); if (ret > 0) { buffer += ret; remaining -= ret; } } node = avl_get_next(node); } thread_mutex_unlock(&_stats_mutex); cur->len = STREAMLIST_BLKSIZE - remaining; return start; }
int auth_is_listener_connected(source_t *source, char *username) { client_t *client; avl_node *client_node; avl_tree_rlock(source->client_tree); client_node = avl_get_first(source->client_tree); while(client_node) { client = (client_t *)client_node->key; if (client->username) { if (!strcmp(client->username, username)) { avl_tree_unlock(source->client_tree); return 1; } } client_node = avl_get_next(client_node); } avl_tree_unlock(source->client_tree); return 0; }
thread_type *thread_self(void) { avl_node *node; thread_type *th; pthread_t sys_thread = pthread_self(); _mutex_lock(&_threadtree_mutex); if (_threadtree == NULL) { #ifdef THREAD_DEBUG LOG_WARN("Thread tree is empty, this must be wrong!"); #endif _mutex_unlock(&_threadtree_mutex); return NULL; } node = avl_get_first(_threadtree); while (node) { th = (thread_type *)node->key; if (th && pthread_equal(sys_thread, th->sys_thread)) { _mutex_unlock(&_threadtree_mutex); return th; } node = avl_get_next(node); } _mutex_unlock(&_threadtree_mutex); #ifdef THREAD_DEBUG LOG_ERROR("Nonexistant thread alive..."); #endif return NULL; }
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode) { htpasswd_auth_state *state; xmlNodePtr newnode; avl_node *node; state = auth->state; htpasswd_recheckfile (state); thread_rwlock_rlock (&state->file_rwlock); node = avl_get_first (state->users); while (node) { htpasswd_user *user = (htpasswd_user *)node->key; newnode = xmlNewChild (srcnode, NULL, "User", NULL); xmlNewChild(newnode, NULL, "username", user->name); xmlNewChild(newnode, NULL, "password", user->pass); node = avl_get_next (node); } thread_rwlock_unlock (&state->file_rwlock); return AUTH_OK; }
int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { xmlDocPtr res; xsltStylesheetPtr cur; int len; refbuf_t *content = NULL; char **params = NULL; xmlSetGenericErrorFunc ("", log_parse_failure); xsltSetGenericErrorFunc ("", log_parse_failure); thread_mutex_lock(&xsltlock); cur = xslt_get_stylesheet(xslfilename); if (cur == NULL) { thread_mutex_unlock(&xsltlock); ERROR1 ("problem reading stylesheet \"%s\"", xslfilename); return client_send_404 (client, "Could not parse XSLT file"); } if (client->parser->queryvars) { // annoying but we need to surround the args with ' when passing them in int i, arg_count = client->parser->queryvars->length * 2; avl_node *node = avl_get_first (client->parser->queryvars); params = calloc (arg_count+1, sizeof (char *)); for (i = 0; node && i < arg_count; node = avl_get_next (node)) { http_var_t *param = (http_var_t *)node->key; char *tmp = util_url_escape (param->value); params[i++] = param->name; // use alloca for now, should really url esc into a supplied buffer params[i] = (char*)alloca (strlen (tmp) + 3); sprintf (params[i++], "\'%s\'", tmp); free (tmp); } params[i] = NULL; } res = xsltApplyStylesheet (cur, doc, (const char **)params); free (params); if (res == NULL || xslt_SaveResultToBuf (&content, &len, res, cur) < 0) { thread_mutex_unlock (&xsltlock); xmlFreeDoc (res); WARN1 ("problem applying stylesheet \"%s\"", xslfilename); return client_send_404 (client, "XSLT problem"); } else { /* the 100 is to allow for the hardcoded headers */ refbuf_t *refbuf = refbuf_new (100); const char *mediatype = NULL; /* lets find out the content type to use */ if (cur->mediaType) mediatype = (char *)cur->mediaType; else { /* check method for the default, a missing method assumes xml */ if (cur->method && xmlStrcmp (cur->method, XMLSTR("html")) == 0) mediatype = "text/html"; else if (cur->method && xmlStrcmp (cur->method, XMLSTR("text")) == 0) mediatype = "text/plain"; else mediatype = "text/xml"; } snprintf (refbuf->data, 100, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n", mediatype, len); thread_mutex_unlock (&xsltlock); client->respcode = 200; client_set_queue (client, NULL); client->refbuf = refbuf; refbuf->len = strlen (refbuf->data); refbuf->next = content; } xmlFreeDoc(res); return fserve_setup_client (client); }
void fserve_scan (time_t now) { avl_node *node; avl_tree_wlock (fh_cache); node = avl_get_first (fh_cache); while (node) { fh_node *fh = node->key; node = avl_get_next (node); thread_mutex_lock (&fh->lock); if (global.running != ICE_RUNNING) fh->expire = 0; if (now == (time_t)0) { fh->expire = 0; thread_mutex_unlock (&fh->lock); continue; } if (fh->finfo.limit) { fbinfo *finfo = &fh->finfo; if (fh->stats == 0) { int len = strlen (finfo->mount) + 10; char *str = alloca (len); char buf[20]; snprintf (str, len, "%s-%s", (finfo->flags & FS_FALLBACK) ? "fallback" : "file", finfo->mount); fh->stats = stats_handle (str); stats_set_flags (fh->stats, "fallback", "file", STATS_COUNTERS|STATS_HIDDEN); stats_set_flags (fh->stats, "outgoing_kbitrate", "0", STATS_COUNTERS|STATS_HIDDEN); snprintf (buf, sizeof (buf), "%d", fh->refcount); stats_set_flags (fh->stats, "listeners", buf, STATS_GENERAL|STATS_HIDDEN); snprintf (buf, sizeof (buf), "%d", fh->peak); stats_set_flags (fh->stats, "listener_peak", buf, STATS_GENERAL|STATS_HIDDEN); fh->prev_count = fh->refcount; } else { stats_lock (fh->stats, NULL); if (fh->prev_count != fh->refcount) { fh->prev_count = fh->refcount; stats_set_args (fh->stats, "listeners", "%ld", fh->refcount); stats_set_args (fh->stats, "listener_peak", "%ld", fh->peak); } } if (fh->stats_update <= now) { fh->stats_update = now + 5; stats_set_args (fh->stats, "outgoing_kbitrate", "%ld", (long)((8 * rate_avg (fh->out_bitrate))/1024)); } stats_release (fh->stats); } if (fh->refcount == 0 && fh->expire >= 0 && now >= fh->expire) { DEBUG1 ("timeout of %s", fh->finfo.mount); if (fh->stats) { stats_lock (fh->stats, NULL); stats_set (fh->stats, NULL, NULL); } remove_fh_from_cache (fh); thread_mutex_unlock (&fh->lock); _delete_fh (fh); continue; } thread_mutex_unlock (&fh->lock); } avl_tree_unlock (fh_cache); }
void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file) { #ifdef DEBUG_MUTEXES thread_type *th = thread_self(); if (!th) { LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line); } LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); mutex->line = line; # ifdef CHECK_MUTEXES if (th) { int locks = 0; avl_node *node; mutex_t *tmutex; _mutex_lock(&_mutextree_mutex); while (node) { tmutex = (mutex_t *)node->key; if (tmutex->mutex_id == mutex->mutex_id) { if (tmutex->thread_id != th->thread_id) { LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); _mutex_unlock(&_mutextree_mutex); return; } } else if (tmutex->thread_id == th->thread_id) { locks++; } node = avl_get_next (node); } if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) { /* Don't have double mutex, has more than this mutex left */ LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!", _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); } _mutex_unlock(&_mutextree_mutex); } # endif /* CHECK_MUTEXES */ _mutex_unlock(mutex); _mutex_lock(&_mutextree_mutex); LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); mutex->line = -1; if (mutex->thread_id == th->thread_id) { mutex->thread_id = MUTEX_STATE_NOTLOCKED; } _mutex_unlock(&_mutextree_mutex); #else _mutex_unlock(mutex); #endif /* DEBUG_MUTEXES */ }
void thread_mutex_lock_c(mutex_t *mutex, int line, char *file) { #ifdef DEBUG_MUTEXES thread_type *th = thread_self(); if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line); LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); # ifdef CHECK_MUTEXES /* Just a little sanity checking to make sure that we're locking ** mutexes correctly */ if (th) { int locks = 0; avl_node *node; mutex_t *tmutex; _mutex_lock(&_mutextree_mutex); node = avl_get_first (_mutextree); while (node) { tmutex = (mutex_t *)node->key; if (tmutex->mutex_id == mutex->mutex_id) { if (tmutex->thread_id == th->thread_id) { /* Deadlock, same thread can't lock the same mutex twice */ LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); _mutex_unlock(&_mutextree_mutex); return; } } else if (tmutex->thread_id == th->thread_id) { /* Mutex locked by this thread (not this mutex) */ locks++; } node = avl_get_next(node); } if (locks > 0) { /* Has already got a mutex locked */ if (_multi_mutex.thread_id != th->thread_id) { /* Tries to lock two mutexes, but has not got the double mutex, norty boy! */ LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!", _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); } } _mutex_unlock(&_mutextree_mutex); } # endif /* CHECK_MUTEXES */ _mutex_lock(mutex); _mutex_lock(&_mutextree_mutex); LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1); mutex->line = line; if (th) { mutex->thread_id = th->thread_id; } _mutex_unlock(&_mutextree_mutex); #else _mutex_lock(mutex); #endif /* DEBUG_MUTEXES */ }
static void process_source_stat (stats_source_t *src_stats, stats_event_t *event) { if (event->name) { stats_node_t *node = _find_node (src_stats->stats_tree, event->name); if (node == NULL) { /* adding node */ if (event->action != STATS_EVENT_REMOVE && event->value) { DEBUG3 ("new node on %s \"%s\" (%s)", src_stats->source, 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->flags = event->flags; if (src_stats->flags & STATS_HIDDEN) node->flags |= STATS_HIDDEN; stats_listener_send (node->flags, "EVENT %s %s %s\n", src_stats->source, event->name, event->value); avl_insert (src_stats->stats_tree, (void *)node); } return; } if (event->action == STATS_EVENT_REMOVE) { DEBUG2 ("delete node %s from %s", event->name, src_stats->source); stats_listener_send (node->flags, "DELETE %s %s\n", src_stats->source, event->name); avl_delete (src_stats->stats_tree, (void *)node, _free_stats); return; } modify_node_event (node, event); stats_listener_send (node->flags, "EVENT %s %s %s\n", src_stats->source, node->name, node->value); return; } if (event->action == STATS_EVENT_REMOVE && event->name == NULL) { avl_tree_unlock (src_stats->stats_tree); avl_tree_wlock (_stats.source_tree); avl_tree_wlock (src_stats->stats_tree); avl_delete (_stats.source_tree, (void *)src_stats, _free_source_stats); avl_tree_unlock (_stats.source_tree); return; } /* change source flags status */ if (event->action & STATS_EVENT_HIDDEN) { avl_node *node = avl_get_first (src_stats->stats_tree); int visible = 0; if ((event->flags&STATS_HIDDEN) == (src_stats->flags&STATS_HIDDEN)) return; if (src_stats->flags & STATS_HIDDEN) { stats_node_t *ct = _find_node (src_stats->stats_tree, "server_type"); const char *type = "audio/mpeg"; if (ct) type = ct->value; src_stats->flags &= ~STATS_HIDDEN; stats_listener_send (src_stats->flags, "NEW %s %s\n", type, src_stats->source); visible = 1; } else { stats_listener_send (src_stats->flags, "DELETE %s\n", src_stats->source); src_stats->flags |= STATS_HIDDEN; } while (node) { stats_node_t *stats = (stats_node_t*)node->key; if (visible) { stats->flags &= ~STATS_HIDDEN; stats_listener_send (stats->flags, "EVENT %s %s %s\n", src_stats->source, stats->name, stats->value); } else stats->flags |= STATS_HIDDEN; node = avl_get_next (node); } } }