xml_print( client_t *client, const char *fmt, ... ) { int rval, len; va_list ap; char buf[4096]; va_start (ap, fmt); if(! client->valid ) { va_end(ap); return 1; } vsnprintf (buf, sizeof (buf), fmt, ap); len = strlen(buf); SYS_CALL( rval, write( client->fd, buf, len)); if ( rval < 0 && rval != len ) { va_end(ap); client->valid = 0; return 1; } va_end(ap); return 0; }
void * server_thread (void *arg) { int interactive = (arg != NULL); socklen_t len; int request_len; client_t client; char remote_ip[16]; char request[REQUESTLEN + 1]; llist_entry *le; datum_t rootdatum; for (;;) { client.valid = 0; len = sizeof(client.addr); if (interactive) { pthread_mutex_lock(&server_interactive_mutex); SYS_CALL( client.fd, accept(interactive_socket->sockfd, (struct sockaddr *) &(client.addr), &len)); pthread_mutex_unlock(&server_interactive_mutex); } else { pthread_mutex_lock ( &server_socket_mutex ); SYS_CALL( client.fd, accept(server_socket->sockfd, (struct sockaddr *) &(client.addr), &len)); pthread_mutex_unlock( &server_socket_mutex ); } if ( client.fd < 0 ) { err_ret("server_thread() error"); debug_msg("server_thread() %lx clientfd = %d errno=%d\n", (unsigned long) pthread_self(), client.fd, errno); continue; } my_inet_ntop( AF_INET, (void *)&(client.addr.sin_addr), remote_ip, 16 ); if ( !strcmp(remote_ip, "127.0.0.1") || gmetad_config.all_trusted || (llist_search(&(gmetad_config.trusted_hosts), (void *)remote_ip, strcmp, &le) == 0) ) { client.valid = 1; } if(! client.valid ) { debug_msg("server_thread() %s tried to connect and is not a trusted host", remote_ip); close( client.fd ); continue; } client.filter=0; client.http=0; gettimeofday(&client.now, NULL); if (interactive) { request_len = readline(client.fd, request, REQUESTLEN); if (request_len < 0) { err_msg("server_thread() could not read request from %s", remote_ip); close(client.fd); continue; } debug_msg("server_thread() received request \"%s\" from %s", request, remote_ip); if (process_request(&client, request)) { err_msg("Got a malformed path request from %s", remote_ip); close(client.fd); continue; } } else strcpy(request, "/"); if(root_report_start(&client)) { err_msg("server_thread() %lx unable to write root preamble (DTD, etc)", (unsigned long) pthread_self() ); close(client.fd); continue; } /* Start search at the root node. */ rootdatum.data = &root; rootdatum.size = sizeof(root); if (process_path(&client, request, &rootdatum, NULL)) { err_msg("server_thread() %lx unable to write XML tree info", (unsigned long) pthread_self() ); close(client.fd); continue; } if(root_report_end(&client)) { err_msg("server_thread() %lx unable to write root epilog", (unsigned long) pthread_self() ); } close(client.fd); } }
static int status_report( client_t *client ) { int rval, len; char buf[4096]; debug_msg("Stat request..."); if(! client->valid ) { return 1; } apr_time_t now = apr_time_now(); snprintf (buf, sizeof (buf), "HTTP/1.0 200 OK\r\n" "Server: gmetad/" GANGLIA_VERSION_FULL "\r\n" "Content-Type: application/json\r\n" "Connection: close\r\n" "\r\n" "{" "\"host\":\"%s\"," "\"gridname\":\"%s\"," "\"version\":\"%s\"," "\"boottime\":%lu," "\"uptime\":%lu," "\"uptimeMillis\":%lu," "\"metrics\":{" "\"received\":{" "\"all\":%d" "}," "\"sent\":{" "\"all\":%d," "\"rrdtool\":%d," "\"rrdcached\":%d," "\"graphite\":%d," "\"memcached\":%d," "\"riemann\":%d" "}}" "}\r\n", hostname, gmetad_config.gridname, GANGLIA_VERSION_FULL, (long int)(started / APR_TIME_C(1000)), // ms (long int)((now - started) / APR_USEC_PER_SEC), // ms (long int)((now - started) / APR_TIME_C(1000)), // ms ganglia_scoreboard_get("gmetad_metrics_recvd_all"), ganglia_scoreboard_get("gmetad_metrics_sent_all"), ganglia_scoreboard_get("gmetad_metrics_sent_rrdtool"), ganglia_scoreboard_get("gmetad_metrics_sent_rrdcached"), ganglia_scoreboard_get("gmetad_metrics_sent_graphite"), ganglia_scoreboard_get("gmetad_metrics_sent_memcached"), ganglia_scoreboard_get("gmetad_metrics_sent_riemann") ); void *sbi = ganglia_scoreboard_iterator(); while (sbi) { char *name = ganglia_scoreboard_next(&sbi); int val = ganglia_scoreboard_get(name); debug_msg("%s = %d", name, val); } len = strlen(buf); SYS_CALL( rval, write( client->fd, buf, len)); if ( rval < 0 && rval != len ) { client->valid = 0; return 1; } return 0; }
void * data_thread ( void *arg ) { int i, bytes_read, rval; data_source_list_t *d = (data_source_list_t *)arg; g_inet_addr *addr; g_tcp_socket *sock=0; datum_t key; char *buf; /* This will grow as needed */ unsigned int buf_size = 1024, read_index; struct pollfd struct_poll; apr_time_t start, end; apr_interval_time_t sleep_time, elapsed; double random_factor; unsigned int rand_seed; rand_seed = apr_time_now() * (int)pthread_self(); for(i = 0; d->name[i] != 0; rand_seed = rand_seed * d->name[i++]); if(get_debug_msg_level()) { fprintf(stderr,"Data thread %lu is monitoring [%s] data source\n", (unsigned long)pthread_self(), d->name); for(i = 0; i < d->num_sources; i++) { addr = d->sources[i]; fprintf(stderr, "\t%s\n", addr->name); } } key.data = d->name; key.size = strlen( key.data ) + 1; buf = malloc( buf_size ); if(!buf) { err_quit("data_thread() unable to malloc initial buffer for [%s] data source\n", d->name); } /* Assume the best from the beginning */ d->dead = 0; for (;;) { start = apr_time_now(); sock = NULL; /* If we successfully read from a good data source last time then try the same host again first. */ if(d->last_good_index != -1) sock = g_tcp_socket_new ( d->sources[d->last_good_index] ); /* If there was no good connection last time or the above connect failed then try each host in the list. */ if(!sock) { for(i=0; i < d->num_sources; i++) { /* Find first viable source in list. */ sock = g_tcp_socket_new ( d->sources[i] ); if( sock ) { d->last_good_index = i; break; } else { err_msg("data_thread() for [%s] failed to contact node %s", d->name, d->sources[i]->name); } } } if(!sock) { err_msg("data_thread() got no answer from any [%s] datasource", d->name); d->dead = 1; goto take_a_break; } struct_poll.fd = sock->sockfd; struct_poll.events = POLLIN; read_index = 0; for(;;) { /* Timeout set to 10 seconds */ rval = poll( &struct_poll, 1, 10000); if( rval < 0 ) { /* Error */ err_msg("poll() error in data_thread from source %d for [%s] data source after %d bytes read", d->last_good_index, d->name, read_index); if (d->last_good_index < (d->num_sources - 1)) d->last_good_index += 1; /* skip this source */ else d->last_good_index = -1; /* forget this source */ d->dead = 1; goto take_a_break; } else if (rval == 0) { /* No revents during timeout period */ err_msg("poll() timeout from source %d for [%s] data source after %d bytes read", d->last_good_index, d->name, read_index); if (d->last_good_index < (d->num_sources - 1)) d->last_good_index += 1; /* skip this source */ else d->last_good_index = -1; /* forget this source */ d->dead = 1; goto take_a_break; } else { if( struct_poll.revents & POLLIN ) { if( (read_index + 1024) > buf_size ) { /* We need to malloc more space for the data */ buf = realloc( buf, buf_size+1024 ); if(!buf) { err_quit("data_thread() unable to malloc enough room for [%s] XML", d->name); } buf_size+=1024; } SYS_CALL( bytes_read, read(sock->sockfd, buf+read_index, 1023)); if (bytes_read < 0) { err_msg("data_thread() unable to read() socket for [%s] data source", d->name); d->last_good_index = -1; d->dead = 1; goto take_a_break; } else if(bytes_read == 0) { break; } read_index+= bytes_read; } /* Appears that OSX uses POLLHUP on Sockets that I have loaded the entire message into the buffer... * not that I lost the connection (See FreeBSD lists on this discussion) */ #if !(defined(DARWIN)) if( struct_poll.revents & POLLHUP ) { err_msg("The remote machine closed connection for [%s] data source after %d bytes read", d->name, read_index); d->last_good_index = -1; d->dead = 1; goto take_a_break; } #endif /* DARWIN */ if( struct_poll.revents & POLLERR ) { err_msg("POLLERR! for [%s] data source after %d bytes read", d->name, read_index); d->last_good_index = -1; d->dead = 1; goto take_a_break; } if( struct_poll.revents & POLLNVAL ) { err_msg("POLLNVAL! for [%s] data source after %d bytes read", d->name, read_index); d->last_good_index = -1; d->dead = 1; goto take_a_break; } } } buf[read_index] = '\0'; /* Parse the buffer */ rval = process_xml(d, buf); if(rval) { /* We no longer consider the source dead if its XML parsing * had an error - there may be other reasons for this (rrd issues, etc). */ goto take_a_break; } /* We processed all the data. Mark this source as alive */ d->dead = 0; take_a_break: g_tcp_socket_delete(sock); end = apr_time_now(); /* Sleep somewhere between (step +/- SLEEP_RANDOMIZE percent.) */ random_factor = 1 + (SLEEP_RANDOMIZE / 50.0) * ((rand_r(&rand_seed) - RAND_MAX/2)/(float)RAND_MAX); elapsed = end - start; sleep_time = apr_time_from_sec(d->step) * random_factor - elapsed; if(sleep_time > 0) apr_sleep(sleep_time); } return NULL; }