Ejemplo n.º 1
0
static INT64_T chirp_fs_confuga_close (int fd)
{
	int rc;
	SETUP_FILE

	switch (open_files[fd].type) {
		case CHIRP_FS_CONFUGA_REPL_READ:
			CATCH_CONFUGA(confuga_replica_close(open_files[fd].f.replica, STOPTIME));
			break;
		case CHIRP_FS_CONFUGA_FILE_WRITE: {
			confuga_fid_t fid;
			confuga_off_t size;
			CATCH_CONFUGA(confuga_file_close(open_files[fd].f.file.file, &fid, &size, STOPTIME));
			assert(open_files[fd].f.file.size == size);
			CATCH_CONFUGA(confuga_update(C, open_files[fd].path, fid, size, open_files[fd].f.file.flags));
			break;
		}
		case CHIRP_FS_CONFUGA_META_READ:
			buffer_free(&open_files[fd].f.metadata);
			break;
		case CHIRP_FS_CONFUGA_META_WRITE:
			CATCH_CONFUGA(confuga_metadata_update(C, open_files[fd].path, buffer_tostring(&open_files[fd].f.metadata), buffer_pos(&open_files[fd].f.metadata)));
			buffer_free(&open_files[fd].f.metadata);
			break;
		default:
			assert(0);
	}
	open_files[fd].type = CHIRP_FS_CONFUGA_CLOSED;

	PROLOGUE
}
Ejemplo n.º 2
0
static INT64_T chirp_fs_confuga_pread(int fd, void *buffer, INT64_T length, INT64_T offset)
{
	int rc;
	size_t n;
	SETUP_FILE

	if (offset < 0)
		CATCH(EINVAL);

	switch (open_files[fd].type) {
		case CHIRP_FS_CONFUGA_REPL_READ:
			CATCH_CONFUGA(confuga_replica_pread(open_files[fd].f.replica, buffer, length, &n, offset, STOPTIME));
			break;
		case CHIRP_FS_CONFUGA_META_READ:
			if ((size_t)offset < buffer_pos(&open_files[fd].f.metadata)) {
				n = MIN((size_t)length, buffer_pos(&open_files[fd].f.metadata)-(size_t)offset);
				memcpy(buffer, buffer_tostring(&open_files[fd].f.metadata)+offset, n);
			} else {
				n = 0;
			}
			break;
		default:
			CATCH(EBADF);
	}

	rc = 0;
	goto out;
out:
	if (rc) {
		return (errno = rc, -1);
	} else {
		return n; /* N.B. return n on success */
	}
}
Ejemplo n.º 3
0
char *chirp_ticket_tostring(struct chirp_ticket *ct)
{
	size_t n;
	const char *s;
	char *result;
	buffer_t *B;

	B = buffer_create();

	buffer_printf(B, "subject \"%s\"\n", ct->subject);
	buffer_printf(B, "ticket \"%s\"\n", ct->ticket);
	buffer_printf(B, "expiration \"%lu\"\n", (unsigned long) ct->expiration);
	for(n = 0; n < ct->nrights; n++) {
		buffer_printf(B, "rights \"%s\" \"%s\"\n", ct->rights[n].directory, ct->rights[n].acl);
	}

	s = buffer_tostring(B, &n);
	result = xxmalloc(n + 1);
	memset(result, 0, n + 1);
	memcpy(result, s, n);

	buffer_delete(B);

	return result;
}
Ejemplo n.º 4
0
const char *construct_label(struct rmonitor_file_watch_info *f) {
    struct rmonitor_file_watch_event *e;
    static buffer_t *b = NULL;

    if(!b) {
        b = malloc(sizeof(*b));
        buffer_init(b);
    }

    buffer_rewind(b, 0);

    int event_count = 0;
    char *sep = "";

    list_first_item(f->events);
    while((e = list_next_item(f->events))) {
        if(e->cycle_count > 0) {
            e->total_count += e->cycle_count;
            event_count    += e->cycle_count;

            buffer_printf(b, "%s%s(%" PRId64 ")", sep, e->label, e->cycle_count);
            sep = ",";
        }
    }

    if(event_count) {
        return buffer_tostring(b);
    } else {
        return NULL;
    }
}
Ejemplo n.º 5
0
//Using default sampling interval. We may want to add an option
//to change it.
char *resource_monitor_write_command(const char *monitor_path, const char *template_filename, const char *limits_filename, const char *extra_monitor_options, int debug_output, int time_series, int inotify_stats)
{


    buffer_t cmd_builder;
    buffer_init(&cmd_builder);

    if(!monitor_path)
        fatal("Monitor path should be specified.");

    buffer_printf(&cmd_builder, "%s", monitor_path);
    buffer_printf(&cmd_builder, " --with-output-files=%s", template_filename);

    if(debug_output)
        buffer_printf(&cmd_builder, " -dall -o %s.debug", template_filename);

    if(time_series)
        buffer_printf(&cmd_builder, " --with-time-series");

    if(inotify_stats)
        buffer_printf(&cmd_builder, " --with-inotify");

    if(limits_filename)
        buffer_printf(&cmd_builder, " --limits-file=%s", limits_filename);

    if(extra_monitor_options)
        buffer_printf(&cmd_builder, " %s", extra_monitor_options);

    buffer_printf(&cmd_builder, " --sh []");

    char *result = xxstrdup(buffer_tostring(&cmd_builder));
    buffer_free(&cmd_builder);

    return result;
}
Ejemplo n.º 6
0
static void do_debug(INT64_T flags, const char *fmt, va_list args)
{
	buffer_t B;
	char ubuf[1<<16];

	buffer_init(&B);
	buffer_ubuf(&B, ubuf, sizeof(ubuf));
	buffer_max(&B, sizeof(ubuf));

	if (debug_write == debug_file_write || debug_write == debug_stderr_write || debug_write == debug_stdout_write) {
		struct timeval tv;
		struct tm *tm;
		gettimeofday(&tv, 0);
		tm = localtime(&tv.tv_sec);

		buffer_putfstring(&B, "%04d/%02d/%02d %02d:%02d:%02d.%02ld ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (long) tv.tv_usec / 10000);
		buffer_putfstring(&B, "%s[%d] ", debug_program_name, getpid());
	}
	/* Parrot prints debug messages for children: */
	if (getpid() != debug_getpid()) {
		buffer_putfstring(&B, "<child:%d> ", (int)debug_getpid());
	}
	buffer_putfstring(&B, "%s: ", debug_flags_to_name(flags));

	buffer_putvfstring(&B, fmt, args);
	while(isspace(buffer_tostring(&B)[buffer_pos(&B)-1]))
		buffer_rewind(&B, buffer_pos(&B)-1); /* chomp whitespace */
	buffer_putliteral(&B, "\n");

	debug_write(flags, buffer_tostring(&B));

	if(terminal_available && (flags & (D_ERROR | D_NOTICE | D_FATAL))) {
		if(debug_write != debug_stderr_write || !isatty(STDERR_FILENO)) {
			if(!terminal_f) {
				if((terminal_f = fopen(terminal_path, "a")) == NULL) {
					/* print to wherever stderr is pointing that we could not open the terminal. */
					terminal_available = 0;
				}
			}
		}

		if(terminal_f)
			fprintf(terminal_f, "%s", buffer_tostring(&B));
	}

	buffer_free(&B);
}
Ejemplo n.º 7
0
void jx_print_stream( struct jx *j, FILE *file )
{
	buffer_t buffer;
	buffer_init(&buffer);
	jx_print_buffer(j,&buffer);
	fprintf(file,"%s",buffer_tostring(&buffer));
	buffer_free(&buffer);
}
Ejemplo n.º 8
0
int tracer_args_set( struct tracer *t, INT64_T syscall, const INT64_T *args, int nargs )
{
	if(!t->gotregs) {
		if(ptrace(PTRACE_GETREGS,t->pid,0,&t->regs) == -1)
			ERROR;
		t->gotregs = 1;
	}

#if 0 /* Enable this for extreme debugging... */
	{
		int i;
		buffer_t B;
		buffer_init(&B);
		buffer_putfstring(&B, "SET args[%zu] = {", (size_t)nargs);
		for (i = 0; i < nargs; i++)
			buffer_putfstring(&B, "%" PRId64 ", ", args[i]);
		buffer_putliteral(&B, "}");
		debug(D_DEBUG, "%s", buffer_tostring(&B, NULL));
		buffer_free(&B);
	}
#endif

#ifdef CCTOOLS_CPU_I386
	t->regs.regs32.orig_eax = syscall;
	if(nargs>=1) t->regs.regs32.ebx = args[0];
	if(nargs>=2) t->regs.regs32.ecx = args[1];
	if(nargs>=3) t->regs.regs32.edx = args[2];
	if(nargs>=4) t->regs.regs32.esi = args[3];
	if(nargs>=5) t->regs.regs32.edi = args[4];
	if(nargs>=6) t->regs.regs32.ebp = args[5];
#else
	if(tracer_is_64bit(t)) {
		t->regs.regs64.orig_rax = syscall;
		if(nargs>=1) t->regs.regs64.rdi = args[0];
		if(nargs>=2) t->regs.regs64.rsi = args[1];
		if(nargs>=3) t->regs.regs64.rdx = args[2];
		if(nargs>=4) t->regs.regs64.r10 = args[3];
		if(nargs>=5) t->regs.regs64.r8  = args[4];
		if(nargs>=6) t->regs.regs64.r9  = args[5];
	} else {
		t->regs.regs64.orig_rax = syscall;
		if(nargs>=1) t->regs.regs64.rbx = args[0];
		if(nargs>=2) t->regs.regs64.rcx = args[1];
		if(nargs>=3) t->regs.regs64.rdx = args[2];
		if(nargs>=4) t->regs.regs64.rsi = args[3];
		if(nargs>=5) t->regs.regs64.rdi  = args[4];
		if(nargs>=6) {
			if (t->has_args5_bug) t->regs.regs64.r9 = args[5];
			else                  t->regs.regs64.rbp = args[5];
		}
	}
#endif

	t->setregs = 1;

	return 1;
}
Ejemplo n.º 9
0
int advertise_master_to_catalog(const char *catalog_host, int catalog_port, const char *project_name, const char *master_address, struct work_queue_stats *s, struct work_queue_resources *r, const char *workers_by_pool ) {
	char address[DATAGRAM_ADDRESS_MAX];
	char owner[USERNAME_MAX];
	buffer_t *buffer = NULL;
	const char *text;
	size_t text_size;

	if(!outgoing_datagram) {
		outgoing_datagram = datagram_create(0);
		if(!outgoing_datagram) {
			fprintf(stderr, "Failed to advertise master to catalog server: couldn't create outgoing udp datagram!\n");
			return 0;
		}
	}

	if(!username_get(owner)) {
		strcpy(owner,"unknown");
	}

	buffer = buffer_create();

	int total_workers_working = s->workers_busy + s->workers_full;
	int total_workers         = total_workers_working + s->workers_ready;

	debug(D_WQ,"%s advertising resources to the Catalog -- cores:%d memory:%d disk:%d\n",project_name,r->cores.total,r->memory.total,r->disk.total); //debug to see if information is being passed

	buffer_printf(buffer, 
			"type wq_master\n"
			"project %s\nstarttime %llu\npriority %d\n"
			"port %d\nlifetime %d\n"
			"tasks_waiting %d\ntasks_complete %d\ntasks_running %d\ntotal_tasks_dispatched %d\n"
			"workers_init %d\nworkers_ready %d\nworkers_busy %d\nworkers %d\nworkers_by_pool %s\n"
			"cores_total %d\nmemory_total %d\ndisk_total %d\n"
			"capacity %d\n"
			"my_master %s\n"
			"version %d.%d.%s\nowner %s", 
			project_name, (s->start_time)/1000000, s->priority, 
			s->port, WORK_QUEUE_CATALOG_MASTER_AD_LIFETIME, 
			s->tasks_waiting, s->total_tasks_complete, s->tasks_running, s->total_tasks_dispatched, 
			s->workers_init, s->workers_ready, total_workers_working, total_workers, workers_by_pool, 
			r->cores.total, r->memory.total, r->disk.total,
			s->capacity, 
			master_address,
			CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO, owner);

	text = buffer_tostring(buffer, &text_size);

	if(domain_name_cache_lookup(catalog_host, address)) {
		debug(D_WQ, "Advertising master status to the catalog server at %s:%d ...", catalog_host, catalog_port);
		datagram_send(outgoing_datagram, text, strlen(text), address, catalog_port);
	}

	buffer_delete(buffer);

	return 1;
}
Ejemplo n.º 10
0
static int find (buffer_t *B, const size_t base, buffer_t *path, const char *pattern, int recursive)
{
	int rc = 0;
	DIR *D = opendir(buffer_tostring(path));
	if (D) {
		struct dirent *entry;
		size_t current = buffer_pos(path);
		while ((entry = readdir(D))) {
			struct stat buf;

			if (buffer_putstring(path, entry->d_name) == -1) goto failure;
			/* N.B. We don't use FNM_PATHNAME, so `*.c' matches `foo/bar.c' */
			if (fnmatch(pattern, buffer_tostring(path)+base, 0) == 0) {
				if (buffer_printf(B, "%s%c", buffer_tostring(path), 0) == -1) goto failure; /* NUL padded */
				rc += 1;
			}
			if (recursive && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..") && stat(buffer_tostring(path), &buf) == 0 && S_ISDIR(buf.st_mode)) {
				if (buffer_putliteral(path, "/") == -1) goto failure;
				int found = find(B, base, path, pattern, recursive);
				if (found == -1)
					goto failure;
				else if (found > 0)
					rc += found;
			}
			buffer_rewind(path, current);
		}
	} /* else skip */
	goto out;
failure:
	rc = -1;
	goto out;
out:
	if (D)
		closedir(D);
	return rc;
}
Ejemplo n.º 11
0
static inline int discard_response(BUFFER *b, const char *backend) {
    char sample[1024];
    const char *s = buffer_tostring(b);
    char *d = sample, *e = &sample[sizeof(sample) - 1];

    for(; *s && d < e ;s++) {
        char c = *s;
        if(unlikely(!isprint(c))) c = ' ';
        *d++ = c;
    }
    *d = '\0';

    info("BACKEND: received %zu bytes from %s backend. Ignoring them. Sample: '%s'", buffer_strlen(b), backend, sample);
    buffer_flush(b);
    return 0;
}
Ejemplo n.º 12
0
/** Reads a single summary from stream. Summaries are not parsed, here
	we simply read between markers (--) **/
char *rmsummary_read_single_chunk(FILE *stream)
{
	struct buffer b;
	char   line[MAX_LINE];

	/* Skip comments, blank lines, and markers before the summary */
	char c;
	while( (c = getc(stream)) == '#' || isblank(c) || c == '-' )
	{
		ungetc(c, stream);

		/* Make sure we read complete comment lines */
		do {
			line[MAX_LINE - 1] = '\0';
			fgets(line, MAX_LINE, stream);
		} while(line[MAX_LINE - 1]);
	}

	if(feof(stream))
	{
		return NULL;
	}

	buffer_init(&b);

	ungetc(c, stream);
	while( (c = getc(stream)) != EOF )
	{
		ungetc(c, stream);
		if(c == '#' || c == '\n')
			continue;

		if(c == '-')
			break;

		fgets(line, MAX_LINE, stream);
		buffer_printf(&b, "%s", line);
	}

	char *summ = xxstrdup(buffer_tostring(&b));

	buffer_free(&b);

	return summ;
}
Ejemplo n.º 13
0
int advertise_pool_decision_to_catalog(const char *catalog_host, int catalog_port, const char *pool_name, pid_t pid, time_t start_time, const char *decision, int workers_requested)
{
	char address[DATAGRAM_ADDRESS_MAX];
	char owner[USERNAME_MAX];
	buffer_t B;
	const char *text;
	size_t text_size;

	static time_t last_update_time = 0;

	if(time(0) - last_update_time < WORK_QUEUE_CATALOG_POOL_UPDATE_INTERVAL) return 1;

	if(!outgoing_datagram) {
		outgoing_datagram = datagram_create(0);
		if(!outgoing_datagram) {
			fprintf(stderr, "Couldn't create outgoing udp port, thus work queue master info won't be sent to the catalog server!\n");
			return 0;
		}
	}

	if(!username_get(owner)) {
		strcpy(owner,"unknown");
	}

	// port = MAX_TCP_PORT + process id, this is for the catalog server to
	// distinguish the worker pools from the same host. See make_hash_key()
	// function in catalog_server.c
	INT64_T port = 65535 + pid; 

	buffer_init(&B);
	buffer_abortonfailure(&B, 1);
	buffer_printf(&B, "type wq_pool\npool_name %s\nport %" PRId64 "\nstarttime %llu\ndecision %s\nworkers_requested %d\nowner %s\nlifetime %d", pool_name, port, (unsigned long long) start_time, decision, workers_requested, owner, WORK_QUEUE_CATALOG_POOL_AD_LIFETIME);

	text = buffer_tostring(&B, &text_size);
	debug(D_WQ, "Pool AD: \n%s\n", text);

	if(domain_name_cache_lookup(catalog_host, address)) {
		debug(D_WQ, "Sending the pool decision to the catalog server at %s:%d ...", catalog_host, catalog_port);
		datagram_send(outgoing_datagram, text, text_size, address, catalog_port);
	}

	buffer_free(&B);
	last_update_time = time(0);
	return 1;
}
Ejemplo n.º 14
0
static char *blacklisted_expression(struct batch_queue *q) {
	const char *blacklisted     = hash_table_lookup(q->options, "workers-blacklisted");
	static char *last_blacklist = NULL;

	if(!blacklisted)
		return NULL;

	/* print blacklist only when it changes. */
	if(!last_blacklist || strcmp(last_blacklist, blacklisted) != 0) {
		debug(D_BATCH, "Blacklisted hostnames: %s\n", blacklisted);
	}

	buffer_t b;
	buffer_init(&b);

	char *blist = xxstrdup(blacklisted);


	/* strsep updates blist, so we keep the original pointer in binit so we can free it later */
	char *binit = blist;

	char *sep = "";
	char *hostname;

	buffer_printf(&b, "(");
	while((hostname = strsep(&blist, " "))) {
		buffer_printf(&b, "%s(machine != \"%s\")", sep, hostname);

		sep = " && ";
	}
	buffer_printf(&b, ")");

	char *result = xxstrdup(buffer_tostring(&b));

	free(binit);
	buffer_free(&b);

	if(last_blacklist) {
		free(last_blacklist);
	}

	last_blacklist = xxstrdup(blacklisted);

	return result;
}
Ejemplo n.º 15
0
static int test_variable_renames(void) {
    fprintf(stderr, "Creating chart\n");
    RRDSET *st = rrdset_create("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
    fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name);

    fprintf(stderr, "Creating dimension DIM1\n");
    RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRDDIM_INCREMENTAL);
    fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd1->id, rd1->name);

    fprintf(stderr, "Creating dimension DIM2\n");
    RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRDDIM_INCREMENTAL);
    fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd2->id, rd2->name);

    fprintf(stderr, "Renaming chart to CHARTNAME1\n");
    rrdset_set_name(st, "CHARTNAME1");
    fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name);

    fprintf(stderr, "Renaming chart to CHARTNAME2\n");
    rrdset_set_name(st, "CHARTNAME2");
    fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name);

    fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME1\n");
    rrddim_set_name(st, rd1, "DIM1NAME1");
    fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name);

    fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME2\n");
    rrddim_set_name(st, rd1, "DIM1NAME2");
    fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name);

    fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME1\n");
    rrddim_set_name(st, rd2, "DIM2NAME1");
    fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);

    fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n");
    rrddim_set_name(st, rd2, "DIM2NAME2");
    fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);

    BUFFER *buf = buffer_create(1);
    health_api_v1_chart_variables2json(st, buf);
    fprintf(stderr, "%s", buffer_tostring(buf));
    buffer_free(buf);
    return 1;
}
Ejemplo n.º 16
0
static void update_blacklisted_workers( struct batch_queue *queue, struct list *masters_list ) {

	if(!masters_list || list_size(masters_list) < 1)
		return;

	buffer_t b;
	struct jx *j;

	buffer_init(&b);

	const char *sep = "";
	list_first_item(masters_list);
	while((j=list_next_item(masters_list))) {
		struct jx *blacklisted = jx_lookup(j,"workers_blacklisted");

		if(!blacklisted) {
			continue;
		}

		if(jx_istype(blacklisted, JX_STRING)) {
			buffer_printf(&b, "%s%s", sep, blacklisted->u.string_value);
			sep = " ";
		}

		if(jx_istype(blacklisted, JX_ARRAY)) {
			struct jx *item;
			for (void *i = NULL; (item = jx_iterate_array(blacklisted, &i));) {
				if(jx_istype(item, JX_STRING)) {
					buffer_printf(&b, "%s%s", sep, item->u.string_value);
					sep = " ";
				}
			}
		}
	}

	if(buffer_pos(&b) > 0) {
		batch_queue_set_option(queue, "workers-blacklisted", buffer_tostring(&b));
	} else {
		batch_queue_set_option(queue, "workers-blacklisted", NULL);
	}

	buffer_free(&b);
}
Ejemplo n.º 17
0
int cfs_fflush(CHIRP_FILE * file)
{
	size_t size;
	const char *content;

	if(file->type == LOCAL)
		return fflush(file->f.lfile);

	content = buffer_tostring(&file->f.cfile.B, &size);

	while((INT64_T) size > file->f.cfile.offset) {	/* finish all writes */
		int w = cfs->pwrite(file->f.cfile.fd, content, size, file->f.cfile.offset);
		if(w == -1) {
			file->f.cfile.error = EIO;
			return EOF;
		}
		file->f.cfile.offset += w;
	}
	return 0;
}
Ejemplo n.º 18
0
static int dag_parse_node_regular_command(struct lexer *bk, struct dag_node *n)
{
	struct buffer b;

	buffer_init(&b);

	struct token *t;
	while((t = lexer_next_token(bk)) && t->type != TOKEN_NEWLINE)
	{
		switch(t->type)
		{
		case TOKEN_SPACE:
			buffer_printf(&b, " ");
			break;
		case TOKEN_LITERAL:
			buffer_printf(&b, "%s", t->lexeme);
			break;
		case TOKEN_IO_REDIRECT:
			buffer_printf(&b, "%s", t->lexeme);
			break;
		default:
			lexer_report_error(bk, "Unexpected command token: %s.\n", lexer_print_token(t));
			break;
		}

		lexer_free_token(t);
	}

	if(!t)
	{
		lexer_report_error(bk, "Command does not end with newline.\n");
	}

	n->command = xxstrdup(buffer_tostring(&b));

	buffer_free(&b);

	debug(D_MAKEFLOW_PARSER, "node command=%s", n->command);

	return 1;
}
Ejemplo n.º 19
0
int advertise_master_to_catalog(const char *catalog_host, int catalog_port, const char *project_name, struct work_queue_stats *s, const char *workers_by_pool, int now) {
	char address[DATAGRAM_ADDRESS_MAX];
	char owner[USERNAME_MAX];

	buffer_t *buffer = NULL;
	const char *text;
	size_t text_size;

	static time_t last_update_time = 0;

	if(!now) {
		if(time(0) - last_update_time < WORK_QUEUE_CATALOG_UPDATE_INTERVAL) return 1;
	}

	if(!outgoing_datagram) {
		outgoing_datagram = datagram_create(0);
		if(!outgoing_datagram) {
			fprintf(stderr, "Failed to advertise master to catalog server: couldn't create outgoing udp datagram!\n");
			return 0;
		}
	}

	if(!username_get(owner)) {
		strcpy(owner,"unknown");
	}

	buffer = buffer_create();

	buffer_printf(buffer, "type wq_master\nproject %s\nstart_time %llu\npriority %d\nport %d\nlifetime %d\ntasks_waiting %d\ntasks_complete %d\ntask_running %d\ntotal_tasks_dispatched %d\nworkers_init %d\nworkers_ready %d\nworkers_busy %d\nworkers %d\nworkers_by_pool %s\ncapacity %d\nversion %d.%d.%d\nowner %s", project_name, s->start_time, s->priority, s->port, WORK_QUEUE_CATALOG_LIFETIME, s->tasks_waiting, s->total_tasks_complete, s->workers_busy, s->total_tasks_dispatched, s->workers_init, s->workers_ready, s->workers_busy, s->workers_ready + s->workers_busy, workers_by_pool, s->capacity, CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO, owner);

	text = buffer_tostring(buffer, &text_size);
	if(domain_name_cache_lookup(catalog_host, address)) {
		debug(D_WQ, "Advertising master status to the catalog server at %s:%d ...", catalog_host, catalog_port);
		datagram_send(outgoing_datagram, text, strlen(text), address, catalog_port);
	}

	buffer_delete(buffer);
	last_update_time = time(0);
	return 1;
}
Ejemplo n.º 20
0
int advertise_pool_decision_to_catalog(const char *catalog_host, int catalog_port, const char *pool_name, const char *decision)
{
	char address[DATAGRAM_ADDRESS_MAX];
	char owner[USERNAME_MAX];
	buffer_t *buffer = NULL;
	const char *text;
	size_t text_size;

	static time_t last_update_time = 0;

	if(time(0) - last_update_time < WORK_QUEUE_CATALOG_UPDATE_INTERVAL) return 1;

	if(!outgoing_datagram) {
		outgoing_datagram = datagram_create(0);
		if(!outgoing_datagram) {
			fprintf(stderr, "Couldn't create outgoing udp port, thus work queue master info won't be sent to the catalog server!\n");
			return 0;
		}
	}

	if(!username_get(owner)) {
		strcpy(owner,"unknown");
	}

	buffer = buffer_create();
	buffer_printf(buffer, "type wq_pool\npool_name %s\ndecision %s\nowner %s", pool_name, decision, owner);

	text = buffer_tostring(buffer, &text_size);
	debug(D_WQ, "Pool AD: \n%s\n", text);

	if(domain_name_cache_lookup(catalog_host, address)) {
		debug(D_WQ, "Sending the pool decision to the catalog server at %s:%d ...", catalog_host, catalog_port);
		datagram_send(outgoing_datagram, text, text_size, address, catalog_port);
	}

	buffer_delete(buffer);
	last_update_time = time(0);
	return 1;
}
Ejemplo n.º 21
0
static int ticket_read(char *ticket_filename, struct chirp_ticket *ct)
{
	buffer_t B;
	CHIRP_FILE *tf = cfs_fopen(ticket_filename, "r");
	if(!tf)
		return 0;

	buffer_init(&B);
	buffer_abortonfailure(&B, 1);

	if(!cfs_freadall(tf, &B)) {
		cfs_fclose(tf);
		return 0;
	}
	cfs_fclose(tf);

	int result = chirp_ticket_read(buffer_tostring(&B, NULL), ct);

	buffer_free(&B);

	return result;
}
Ejemplo n.º 22
0
int nvpair_print_alloc(struct nvpair *n, char **text)
{
	size_t needed;

	char *key;
	void *value;

	buffer_t b;
	buffer_init(&b);
	buffer_abortonfailure(&b, 0);

	hash_table_firstkey(n->table);
	while(hash_table_nextkey(n->table, &key, &value)) {
		buffer_printf(&b, "%s %s\n", key, (char *) value);
	}

	*text  = xxstrdup(buffer_tostring(&b, &needed));

	buffer_free(&b);

	return needed;
}
Ejemplo n.º 23
0
struct token *lexer_concat_expandable(struct lexer *lx, struct list *tokens)
{
	struct token *t;

	struct buffer b;
	buffer_init(&b);

	char *substitution;

	list_first_item(tokens);

	while((t = list_pop_head(tokens))) {
		switch(t->type) {
		case TOKEN_SUBSTITUTION:
			substitution = dag_variable_lookup_string(t->lexeme, lx->environment);
			if(!substitution)
				fatal("Variable %s has not yet been defined at line % " PRId64 ".\n", t->lexeme, lx->line_number);
			buffer_printf(&b, "%s", substitution);
			free(substitution);
			break;
		case TOKEN_LITERAL:
			if(strcmp(t->lexeme, "") != 0)           // Skip empty strings.
				buffer_printf(&b, "%s", t->lexeme);
			break;
		default:
			lexer_report_error(lx, "Error in expansion, got: %s.\n", lexer_print_token(t));
			break;
		}

		lexer_free_token(t);
	}

	t = lexer_pack_token(lx, TOKEN_LITERAL);
	t->lexeme = xxstrdup(buffer_tostring(&b));
	buffer_free(&b);

	return t;
}
Ejemplo n.º 24
0
static void set_worker_resources_options( struct batch_queue *queue )
{
	buffer_t b;
	buffer_init(&b);

	if(batch_queue_get_type(queue) == BATCH_QUEUE_TYPE_CONDOR) {
		buffer_printf(&b, " --cores=$$([TARGET.Cpus]) --memory=$$([TARGET.Memory]) --disk=$$([TARGET.Disk/1024])");
	} else {
		if(resources->cores > -1) {
			buffer_printf(&b, " --cores=%" PRId64, resources->cores);
		}

		if(resources->memory > -1) {
			buffer_printf(&b, " --memory=%" PRId64, resources->memory);
		}

		if(resources->disk > -1) {
			buffer_printf(&b, " --disk=%" PRId64, resources->disk);
		}
	}

	resource_args = xxstrdup(buffer_tostring(&b));
	buffer_free(&b);
}
Ejemplo n.º 25
0
// returns the HTTP code
inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
    debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);

    int ret = 400;
    BUFFER *dimensions = NULL;

    buffer_flush(w->response.data);

    char    *google_version = "0.6",
            *google_reqId = "0",
            *google_sig = "0",
            *google_out = "json",
            *responseHandler = NULL,
            *outFileName = NULL;

    time_t last_timestamp_in_data = 0, google_timestamp = 0;

    char *chart = NULL
    , *before_str = NULL
    , *after_str = NULL
    , *group_time_str = NULL
    , *points_str = NULL;

    int group = RRDR_GROUPING_AVERAGE;
    uint32_t format = DATASOURCE_JSON;
    uint32_t options = 0x00000000;

    while(url) {
        char *value = mystrsep(&url, "?&");
        if(!value || !*value) continue;

        char *name = mystrsep(&value, "=");
        if(!name || !*name) continue;
        if(!value || !*value) continue;

        debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);

        // name and value are now the parameters
        // they are not null and not empty

        if(!strcmp(name, "chart")) chart = value;
        else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
            if(!dimensions) dimensions = buffer_create(100);
            buffer_strcat(dimensions, "|");
            buffer_strcat(dimensions, value);
        }
        else if(!strcmp(name, "after")) after_str = value;
        else if(!strcmp(name, "before")) before_str = value;
        else if(!strcmp(name, "points")) points_str = value;
        else if(!strcmp(name, "gtime")) group_time_str = value;
        else if(!strcmp(name, "group")) {
            group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
        }
        else if(!strcmp(name, "format")) {
            format = web_client_api_request_v1_data_format(value);
        }
        else if(!strcmp(name, "options")) {
            options |= web_client_api_request_v1_data_options(value);
        }
        else if(!strcmp(name, "callback")) {
            responseHandler = value;
        }
        else if(!strcmp(name, "filename")) {
            outFileName = value;
        }
        else if(!strcmp(name, "tqx")) {
            // parse Google Visualization API options
            // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
            char *tqx_name, *tqx_value;

            while(value) {
                tqx_value = mystrsep(&value, ";");
                if(!tqx_value || !*tqx_value) continue;

                tqx_name = mystrsep(&tqx_value, ":");
                if(!tqx_name || !*tqx_name) continue;
                if(!tqx_value || !*tqx_value) continue;

                if(!strcmp(tqx_name, "version"))
                    google_version = tqx_value;
                else if(!strcmp(tqx_name, "reqId"))
                    google_reqId = tqx_value;
                else if(!strcmp(tqx_name, "sig")) {
                    google_sig = tqx_value;
                    google_timestamp = strtoul(google_sig, NULL, 0);
                }
                else if(!strcmp(tqx_name, "out")) {
                    google_out = tqx_value;
                    format = web_client_api_request_v1_data_google_format(google_out);
                }
                else if(!strcmp(tqx_name, "responseHandler"))
                    responseHandler = tqx_value;
                else if(!strcmp(tqx_name, "outFileName"))
                    outFileName = tqx_value;
            }
        }
    }

    if(!chart || !*chart) {
        buffer_sprintf(w->response.data, "No chart id is given at the request.");
        goto cleanup;
    }

    RRDSET *st = rrdset_find(host, chart);
    if(!st) st = rrdset_find_byname(host, chart);
    if(!st) {
        buffer_strcat(w->response.data, "Chart is not found: ");
        buffer_strcat_htmlescape(w->response.data, chart);
        ret = 404;
        goto cleanup;
    }
    st->last_accessed_time = now_realtime_sec();

    long long before = (before_str && *before_str)?str2l(before_str):0;
    long long after  = (after_str  && *after_str) ?str2l(after_str):0;
    int       points = (points_str && *points_str)?str2i(points_str):0;
    long      group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0;

    debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
          , w->id
          , chart
          , (dimensions)?buffer_tostring(dimensions):""
          , after
          , before
          , points
          , group
          , format
          , options
    );

    if(outFileName && *outFileName) {
        buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
        debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
    }

    if(format == DATASOURCE_DATATABLE_JSONP) {
        if(responseHandler == NULL)
            responseHandler = "google.visualization.Query.setResponse";

        debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
                w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
        );

        buffer_sprintf(w->response.data,
                "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
                responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
    }
    else if(format == DATASOURCE_JSONP) {
        if(responseHandler == NULL)
            responseHandler = "callback";

        buffer_strcat(w->response.data, responseHandler);
        buffer_strcat(w->response.data, "(");
    }

    ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time
                                 , options, &last_timestamp_in_data);

    if(format == DATASOURCE_DATATABLE_JSONP) {
        if(google_timestamp < last_timestamp_in_data)
            buffer_strcat(w->response.data, "});");

        else {
            // the client already has the latest data
            buffer_flush(w->response.data);
            buffer_sprintf(w->response.data,
                    "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
                    responseHandler, google_version, google_reqId);
        }
    }
    else if(format == DATASOURCE_JSONP)
        buffer_strcat(w->response.data, ");");

    cleanup:
    buffer_free(dimensions);
    return ret;
}
Ejemplo n.º 26
0
struct link *http_query_size_via_proxy(const char *proxy, const char *urlin, const char *action, INT64_T * size, time_t stoptime, int cache_reload)
{
	char url[HTTP_LINE_MAX];
	char newurl[HTTP_LINE_MAX];
	char line[HTTP_LINE_MAX];
	char addr[LINK_ADDRESS_MAX];
	struct link *link;
	int save_errno;
	int response;
	char actual_host[HTTP_LINE_MAX];
	int actual_port;
	*size = 0;

	url_encode(urlin, url, sizeof(url));

	if(proxy && !strcmp(proxy, "DIRECT"))
		proxy = 0;

	if(proxy) {
		int fields = sscanf(proxy, "http://%[^:]:%d", actual_host, &actual_port);
		if(fields == 2) {
			/* host and port are good */
		} else if(fields == 1) {
			actual_port = HTTP_PORT;
		} else {
			debug(D_HTTP, "invalid proxy syntax: %s", proxy);
			return 0;
		}
	} else {
		int fields = sscanf(url, "http://%[^:]:%d", actual_host, &actual_port);
		if(fields != 2) {
			fields = sscanf(url, "http://%[^/]", actual_host);
			if(fields == 1) {
				actual_port = HTTP_PORT;
			} else {
				debug(D_HTTP, "malformed url: %s", url);
				return 0;
			}
		}
	}

	debug(D_HTTP, "connect %s port %d", actual_host, actual_port);
	if(!domain_name_lookup(actual_host, addr))
		return 0;

	link = link_connect(addr, actual_port, stoptime);
	if(!link) {
		errno = ECONNRESET;
		return 0;
	}


	{
		buffer_t B;

		buffer_init(&B);
		buffer_abortonfailure(&B, 1);

		buffer_printf(&B, "%s %s HTTP/1.1\r\n", action, url);
		if(cache_reload)
			buffer_putliteral(&B, "Cache-Control: max-age=0\r\n");
		buffer_putliteral(&B, "Connection: close\r\n");
		buffer_printf(&B, "Host: %s\r\n", actual_host);
		if(getenv("HTTP_USER_AGENT"))
			buffer_printf(&B, "User-Agent: Mozilla/5.0 (compatible; CCTools %d.%d.%s Parrot; http://www.nd.edu/~ccl/ %s)\r\n", CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO, getenv("HTTP_USER_AGENT"));
		else
			buffer_printf(&B, "User-Agent: Mozilla/5.0 (compatible; CCTools %d.%d.%s Parrot; http://www.nd.edu/~ccl/)\r\n", CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO);
		buffer_putliteral(&B, "\r\n"); /* header terminator */

		debug(D_HTTP, "%s", buffer_tostring(&B, NULL));
		link_putstring(link, buffer_tostring(&B, NULL), stoptime);

		buffer_free(&B);
	}

	if(link_readline(link, line, HTTP_LINE_MAX, stoptime)) {
		string_chomp(line);
		debug(D_HTTP, "%s", line);
		if(sscanf(line, "HTTP/%*d.%*d %d", &response) == 1) {
			newurl[0] = 0;
			while(link_readline(link, line, HTTP_LINE_MAX, stoptime)) {
				string_chomp(line);
				debug(D_HTTP, "%s", line);
				sscanf(line, "Location: %s", newurl);
				sscanf(line, "Content-Length: %" SCNd64, size);
				if(strlen(line) <= 2) {
					break;
				}
			}

			switch (response) {
			case 200:
				return link;
				break;
			case 301:
			case 302:
			case 303:
			case 307:
				link_close(link);
				if(newurl[0]) {
					if(!strcmp(url, newurl)) {
						debug(D_HTTP, "error: server gave %d redirect from %s back to the same url!", response, url);
						errno = EIO;
						return 0;
					} else {
						return http_query_size_via_proxy(proxy,newurl,action,size,stoptime,cache_reload);
					}
				} else {
					errno = ENOENT;
					return 0;
				}
				break;
			default:
				link_close(link);
				errno = http_response_to_errno(response);
				return 0;
				break;
			}
		} else {
			debug(D_HTTP, "malformed response");
			save_errno = ECONNRESET;
		}
	} else {
		debug(D_HTTP, "malformed response");
		save_errno = ECONNRESET;
	}

	link_close(link);
	errno = save_errno;
	return 0;
}
Ejemplo n.º 27
0
void *backends_main(void *ptr) {
    netdata_thread_cleanup_push(backends_main_cleanup, ptr);

    int default_port = 0;
    int sock = -1;
    BUFFER *b = buffer_create(1), *response = buffer_create(1);
    int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL;
    int (*backend_response_checker)(BUFFER *) = NULL;

    // ------------------------------------------------------------------------
    // collect configuration options

    struct timeval timeout = {
            .tv_sec = 0,
            .tv_usec = 0
    };
    int enabled             = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0);
    const char *source      = config_get(CONFIG_SECTION_BACKEND, "data source", "average");
    const char *type        = config_get(CONFIG_SECTION_BACKEND, "type", "graphite");
    const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost");
    backend_prefix          = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
    const char *hostname    = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname);
    backend_update_every    = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every);
    int buffer_on_failures  = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10);
    long timeoutms          = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000);
    backend_send_names      = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names);

    charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), NULL, SIMPLE_PATTERN_EXACT);
    hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);


    // ------------------------------------------------------------------------
    // validate configuration options
    // and prepare for sending data to our backend

    backend_options = backend_parse_data_source(source, backend_options);

    if(timeoutms < 1) {
        error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000);
        timeoutms = backend_update_every * 2 * 1000;
    }
    timeout.tv_sec  = (timeoutms * 1000) / 1000000;
    timeout.tv_usec = (timeoutms * 1000) % 1000000;

    if(!enabled || backend_update_every < 1)
        goto cleanup;

    // ------------------------------------------------------------------------
    // select the backend type

    if(!strcmp(type, "graphite") || !strcmp(type, "graphite:plaintext")) {

        default_port = 2003;
        backend_response_checker = process_graphite_response;

        if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
            backend_request_formatter = format_dimension_collected_graphite_plaintext;
        else
            backend_request_formatter = format_dimension_stored_graphite_plaintext;

    }
    else if(!strcmp(type, "opentsdb") || !strcmp(type, "opentsdb:telnet")) {

        default_port = 4242;
        backend_response_checker = process_opentsdb_response;

        if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
            backend_request_formatter = format_dimension_collected_opentsdb_telnet;
        else
            backend_request_formatter = format_dimension_stored_opentsdb_telnet;

    }
    else if (!strcmp(type, "json") || !strcmp(type, "json:plaintext")) {

        default_port = 5448;
        backend_response_checker = process_json_response;

        if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
            backend_request_formatter = format_dimension_collected_json_plaintext;
        else
            backend_request_formatter = format_dimension_stored_json_plaintext;

    }
    else {
        error("BACKEND: Unknown backend type '%s'", type);
        goto cleanup;
    }

    if(backend_request_formatter == NULL || backend_response_checker == NULL) {
        error("BACKEND: backend is misconfigured - disabling it.");
        goto cleanup;
    }


    // ------------------------------------------------------------------------
    // prepare the charts for monitoring the backend operation

    struct rusage thread;

    collected_number
            chart_buffered_metrics = 0,
            chart_lost_metrics = 0,
            chart_sent_metrics = 0,
            chart_buffered_bytes = 0,
            chart_received_bytes = 0,
            chart_sent_bytes = 0,
            chart_receptions = 0,
            chart_transmission_successes = 0,
            chart_transmission_failures = 0,
            chart_data_lost_events = 0,
            chart_lost_bytes = 0,
            chart_backend_reconnects = 0,
            chart_backend_latency = 0;

    RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE);
    rrddim_add(chart_metrics, "buffered", NULL,  1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_metrics, "lost",     NULL,  1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_metrics, "sent",     NULL,  1, 1, RRD_ALGORITHM_ABSOLUTE);

    RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA);
    rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_bytes, "lost",     NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_bytes, "sent",     NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);

    RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE);
    rrddim_add(chart_ops, "write",     NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_ops, "discard",   NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_ops, "failure",   NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
    rrddim_add(chart_ops, "read",      NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);

    /*
     * this is misleading - we can only measure the time we need to send data
     * this time is not related to the time required for the data to travel to
     * the backend database and the time that server needed to process them
     *
     * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html
     *
    RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA);
    rrddim_add(chart_latency, "latency",   NULL,  1, 1000, RRD_ALGORITHM_ABSOLUTE);
    */

    RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED);
    rrddim_add(chart_rusage, "user",   NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
    rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);


    // ------------------------------------------------------------------------
    // prepare the backend main loop

    info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, backend_update_every, hostname, backend_prefix);

    usec_t step_ut = backend_update_every * USEC_PER_SEC;
    time_t after = now_realtime_sec();
    int failures = 0;
    heartbeat_t hb;
    heartbeat_init(&hb);

    while(!netdata_exit) {

        // ------------------------------------------------------------------------
        // Wait for the next iteration point.

        heartbeat_next(&hb, step_ut);
        time_t before = now_realtime_sec();
        debug(D_BACKEND, "BACKEND: preparing buffer for timeframe %lu to %lu", (unsigned long)after, (unsigned long)before);

        // ------------------------------------------------------------------------
        // add to the buffer the data we need to send to the backend

        netdata_thread_disable_cancelability();

        size_t count_hosts = 0;
        size_t count_charts_total = 0;
        size_t count_dims_total = 0;

        rrd_rdlock();
        RRDHOST *host;
        rrdhost_foreach_read(host) {
            if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND|RRDHOST_FLAG_BACKEND_DONT_SEND))) {
                char *name = (host == localhost)?"localhost":host->hostname;
                if (!hosts_pattern || simple_pattern_matches(hosts_pattern, name)) {
                    rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_SEND);
                    info("enabled backend for host '%s'", name);
                }
                else {
                    rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_DONT_SEND);
                    info("disabled backend for host '%s'", name);
                }
            }

            if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND)))
                continue;

            rrdhost_rdlock(host);

            count_hosts++;
            size_t count_charts = 0;
            size_t count_dims = 0;
            size_t count_dims_skipped = 0;

            const char *__hostname = (host == localhost)?hostname:host->hostname;

            RRDSET *st;
            rrdset_foreach_read(st, host) {
                if(likely(backends_can_send_rrdset(backend_options, st))) {
                    rrdset_rdlock(st);

                    count_charts++;

                    RRDDIM *rd;
                    rrddim_foreach_read(rd, st) {
                        if (likely(rd->last_collected_time.tv_sec >= after)) {
                            chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options);
                            count_dims++;
                        }
                        else {
                            debug(D_BACKEND, "BACKEND: not sending dimension '%s' of chart '%s' from host '%s', its last data collection (%lu) is not within our timeframe (%lu to %lu)", rd->id, st->id, __hostname, (unsigned long)rd->last_collected_time.tv_sec, (unsigned long)after, (unsigned long)before);
                            count_dims_skipped++;
                        }
                    }

                    rrdset_unlock(st);
                }
            }

            debug(D_BACKEND, "BACKEND: sending host '%s', metrics of %zu dimensions, of %zu charts. Skipped %zu dimensions.", __hostname, count_dims, count_charts, count_dims_skipped);
            count_charts_total += count_charts;
            count_dims_total += count_dims;

            rrdhost_unlock(host);
        }
        rrd_unlock();

        netdata_thread_enable_cancelability();

        debug(D_BACKEND, "BACKEND: buffer has %zu bytes, added metrics for %zu dimensions, of %zu charts, from %zu hosts", buffer_strlen(b), count_dims_total, count_charts_total, count_hosts);

        // ------------------------------------------------------------------------

        chart_buffered_bytes = (collected_number)buffer_strlen(b);

        // reset the monitoring chart counters
        chart_received_bytes =
        chart_sent_bytes =
        chart_sent_metrics =
        chart_lost_metrics =
        chart_transmission_successes =
        chart_transmission_failures =
        chart_data_lost_events =
        chart_lost_bytes =
        chart_backend_reconnects =
        chart_backend_latency = 0;

        if(unlikely(netdata_exit)) break;

        //fprintf(stderr, "\nBACKEND BEGIN:\n%s\nBACKEND END\n", buffer_tostring(b)); // FIXME
        //fprintf(stderr, "after = %lu, before = %lu\n", after, before);

        // prepare for the next iteration
        // to add incrementally data to buffer
        after = before;

        // ------------------------------------------------------------------------
        // if we are connected, receive a response, without blocking

        if(likely(sock != -1)) {
            errno = 0;

            // loop through to collect all data
            while(sock != -1 && errno != EWOULDBLOCK) {
                buffer_need_bytes(response, 4096);

                ssize_t r = recv(sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
                if(likely(r > 0)) {
                    // we received some data
                    response->len += r;
                    chart_received_bytes += r;
                    chart_receptions++;
                }
                else if(r == 0) {
                    error("BACKEND: '%s' closed the socket", destination);
                    close(sock);
                    sock = -1;
                }
                else {
                    // failed to receive data
                    if(errno != EAGAIN && errno != EWOULDBLOCK) {
                        error("BACKEND: cannot receive data from backend '%s'.", destination);
                    }
                }
            }

            // if we received data, process them
            if(buffer_strlen(response))
                backend_response_checker(response);
        }

        // ------------------------------------------------------------------------
        // if we are not connected, connect to a backend server

        if(unlikely(sock == -1)) {
            usec_t start_ut = now_monotonic_usec();
            size_t reconnects = 0;

            sock = connect_to_one_of(destination, default_port, &timeout, &reconnects, NULL, 0);

            chart_backend_reconnects += reconnects;
            chart_backend_latency += now_monotonic_usec() - start_ut;
        }

        if(unlikely(netdata_exit)) break;

        // ------------------------------------------------------------------------
        // if we are connected, send our buffer to the backend server

        if(likely(sock != -1)) {
            size_t len = buffer_strlen(b);
            usec_t start_ut = now_monotonic_usec();
            int flags = 0;
#ifdef MSG_NOSIGNAL
            flags += MSG_NOSIGNAL;
#endif

            ssize_t written = send(sock, buffer_tostring(b), len, flags);
            chart_backend_latency += now_monotonic_usec() - start_ut;
            if(written != -1 && (size_t)written == len) {
                // we sent the data successfully
                chart_transmission_successes++;
                chart_sent_bytes += written;
                chart_sent_metrics = chart_buffered_metrics;

                // reset the failures count
                failures = 0;

                // empty the buffer
                buffer_flush(b);
            }
            else {
                // oops! we couldn't send (all or some of the) data
                error("BACKEND: failed to write data to database backend '%s'. Willing to write %zu bytes, wrote %zd bytes. Will re-connect.", destination, len, written);
                chart_transmission_failures++;

                if(written != -1)
                    chart_sent_bytes += written;

                // increment the counter we check for data loss
                failures++;

                // close the socket - we will re-open it next time
                close(sock);
                sock = -1;
            }
        }
        else {
            error("BACKEND: failed to update database backend '%s'", destination);
            chart_transmission_failures++;

            // increment the counter we check for data loss
            failures++;
        }

        if(failures > buffer_on_failures) {
            // too bad! we are going to lose data
            chart_lost_bytes += buffer_strlen(b);
            error("BACKEND: reached %d backend failures. Flushing buffers to protect this host - this results in data loss on back-end server '%s'", failures, destination);
            buffer_flush(b);
            failures = 0;
            chart_data_lost_events++;
            chart_lost_metrics = chart_buffered_metrics;
        }

        if(unlikely(netdata_exit)) break;

        // ------------------------------------------------------------------------
        // update the monitoring charts

        if(likely(chart_ops->counter_done)) rrdset_next(chart_ops);
        rrddim_set(chart_ops, "read",         chart_receptions);
        rrddim_set(chart_ops, "write",        chart_transmission_successes);
        rrddim_set(chart_ops, "discard",      chart_data_lost_events);
        rrddim_set(chart_ops, "failure",      chart_transmission_failures);
        rrddim_set(chart_ops, "reconnect",    chart_backend_reconnects);
        rrdset_done(chart_ops);

        if(likely(chart_metrics->counter_done)) rrdset_next(chart_metrics);
        rrddim_set(chart_metrics, "buffered", chart_buffered_metrics);
        rrddim_set(chart_metrics, "lost",     chart_lost_metrics);
        rrddim_set(chart_metrics, "sent",     chart_sent_metrics);
        rrdset_done(chart_metrics);

        if(likely(chart_bytes->counter_done)) rrdset_next(chart_bytes);
        rrddim_set(chart_bytes, "buffered",   chart_buffered_bytes);
        rrddim_set(chart_bytes, "lost",       chart_lost_bytes);
        rrddim_set(chart_bytes, "sent",       chart_sent_bytes);
        rrddim_set(chart_bytes, "received",   chart_received_bytes);
        rrdset_done(chart_bytes);

        /*
        if(likely(chart_latency->counter_done)) rrdset_next(chart_latency);
        rrddim_set(chart_latency, "latency",  chart_backend_latency);
        rrdset_done(chart_latency);
        */

        getrusage(RUSAGE_THREAD, &thread);
        if(likely(chart_rusage->counter_done)) rrdset_next(chart_rusage);
        rrddim_set(chart_rusage, "user",   thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
        rrddim_set(chart_rusage, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
        rrdset_done(chart_rusage);

        if(likely(buffer_strlen(b) == 0))
            chart_buffered_metrics = 0;

        if(unlikely(netdata_exit)) break;
    }

cleanup:
    if(sock != -1)
        close(sock);

    buffer_free(b);
    buffer_free(response);

    netdata_thread_cleanup_pop(1);
    return NULL;
}
Ejemplo n.º 28
0
int main(int argc, char *argv[]) {
	char *host = CATALOG_HOST;
	int   port = CATALOG_PORT;

	static struct option long_options[] = {{"catalog", required_argument, 0, 'c'},
                {0,0,0,0}};

	signed int c;
	while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) > -1) {
		switch (c) {
			case 'c':
				host = optarg;
				break;
			default:
				show_help(argv[0]);
				return EXIT_FAILURE;
		}
	}

	struct datagram *d;
	d = datagram_create(DATAGRAM_PORT_ANY);
	if (!d) {
		fatal("could not create datagram port!");
	}

	buffer_t B;
	const char *text;
	size_t text_size;
	buffer_init(&B);
	buffer_abortonfailure(&B, 1);

	struct utsname name;
	int cpus;
	int uptime;	
	double load[3];
	UINT64_T memory_total, memory_avail;
	char owner[USERNAME_MAX];

	uname(&name);
	string_tolower(name.sysname);
	string_tolower(name.machine);
	string_tolower(name.release);
	load_average_get(load);
	cpus = load_average_get_cpus();
	memory_info_get(&memory_avail, &memory_total);
	uptime = uptime_get();
	username_get(owner);

	buffer_printf(&B, "type %s\nversion %d.%d.%s\ncpu %s\nopsys %s\nopsysversion %s\nload1 %0.02lf\nload5 %0.02lf\nload15 %0.02lf\nmemory_total %llu\nmemory_avail %llu\ncpus %d\nuptime %d\nowner %s\n",
		DEFAULT_TYPE,
		CCTOOLS_VERSION_MAJOR, CCTOOLS_VERSION_MINOR, CCTOOLS_VERSION_MICRO,
		name.machine,
		name.sysname,
		name.release,
		load[0],
		load[1],
		load[2],
		(unsigned long long) memory_total,
		(unsigned long long) memory_avail,
		cpus,
		uptime,
		owner
	);

	int i;
	for (i = optind; i < argc; i++) {
		char *name;
		char *value;

		name  = argv[i];
		value = strchr(name, '=');
		if (!value) {
			fatal("invalid name/value pair = %s", name);
		} else {
			*value++ = 0;
		}

		buffer_printf(&B, "%s %s\n", name, value);
	}

        text = buffer_tostring(&B, &text_size);

	char address[DATAGRAM_ADDRESS_MAX];
	if (domain_name_cache_lookup(host, address)) {
		datagram_send(d, text, text_size, address, port);
	} else {
		fatal("unable to lookup address of host: %s", host);
	}

	buffer_free(&B);
	datagram_delete(d);
	return EXIT_SUCCESS;
}
Ejemplo n.º 29
0
static int search_directory(const char *subject, const char *const base, char fullpath[CHIRP_PATH_MAX], const char *pattern, int flags, struct link *l, time_t stoptime)
{
	if(strlen(pattern) == 0)
		return 0;

	debug(D_DEBUG, "search_directory(subject = `%s', base = `%s', fullpath = `%s', pattern = `%s', flags = %d, ...)", subject, base, fullpath, pattern, flags);

	int access_flags = search_to_access(flags);
	int includeroot = flags & CHIRP_SEARCH_INCLUDEROOT;
	int metadata = flags & CHIRP_SEARCH_METADATA;
	int stopatfirst = flags & CHIRP_SEARCH_STOPATFIRST;

	int result = 0;
	struct chirp_dir *dirp = cfs->opendir(fullpath);
	char *current = fullpath + strlen(fullpath);	/* point to end to current directory */

	if(dirp) {
		errno = 0;
		struct chirp_dirent *entry;
		while((entry = cfs->readdir(dirp))) {
			char *name = entry->name;

			if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strncmp(name, ".__", 3) == 0)
				continue;
			sprintf(current, "/%s", name);

			if(search_match_file(pattern, base)) {
				const char *matched;
				if(includeroot) {
					if(base - fullpath == 1 && fullpath[0] == '/') {
						matched = base;
					} else {
						matched = fullpath;
					}
				} else {
					matched = base;
				}

				result += 1;
				if(access_flags == F_OK || cfs->access(fullpath, access_flags) == 0) {
					if(metadata) {
						/* A match was found, but the matched file couldn't be statted. Generate a result and an error. */
						if(entry->lstatus == -1) {
							link_putfstring(l, "0:%s::\n", stoptime, matched);	// FIXME is this a bug?
							link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_STAT, matched);
						} else {
							BUFFER_STACK_ABORT(B, 4096)
							chirp_stat_encode(B, &entry->info);
							link_putfstring(l, "0:%s:%s:\n", stoptime, matched, buffer_tostring(B));
							if(stopatfirst)
								return 1;
						}
					} else {
						link_putfstring(l, "0:%s::\n", stoptime, matched);
						if(stopatfirst)
							return 1;
					}
				}	/* FIXME access failure */
			}

			if(cfs_isdir(fullpath) && search_should_recurse(base, pattern)) {
				if(chirp_acl_check_dir(fullpath, subject, CHIRP_ACL_LIST)) {
					int n = search_directory(subject, base, fullpath, pattern, flags, l, stoptime);
					if(n > 0) {
						result += n;
						if(stopatfirst)
							return result;
					}
				} else {
					link_putfstring(l, "%d:%d:%s:\n", stoptime, EPERM, CHIRP_SEARCH_ERR_OPEN, fullpath);
				}
			}
			*current = '\0';	/* clear current entry */
			errno = 0;
		}

		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_READ, fullpath);

		errno = 0;
		cfs->closedir(dirp);
		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_CLOSE, fullpath);
	} else {
		link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_OPEN, fullpath);
	}

	return result;
}
Ejemplo n.º 30
0
int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
    int ret = 400;
    buffer_flush(w->response.data);

    BUFFER *dimensions = NULL;

    const char *chart = NULL
    , *before_str = NULL
    , *after_str = NULL
    , *points_str = NULL
    , *multiply_str = NULL
    , *divide_str = NULL
    , *label = NULL
    , *units = NULL
    , *label_color = NULL
    , *value_color = NULL
    , *refresh_str = NULL
    , *precision_str = NULL
    , *scale_str = NULL
    , *alarm = NULL;

    int group = GROUP_AVERAGE;
    uint32_t options = 0x00000000;

    while(url) {
        char *value = mystrsep(&url, "/?&");
        if(!value || !*value) continue;

        char *name = mystrsep(&value, "=");
        if(!name || !*name) continue;
        if(!value || !*value) continue;

        debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);

        // name and value are now the parameters
        // they are not null and not empty

        if(!strcmp(name, "chart")) chart = value;
        else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
            if(!dimensions)
                dimensions = buffer_create(100);

            buffer_strcat(dimensions, "|");
            buffer_strcat(dimensions, value);
        }
        else if(!strcmp(name, "after")) after_str = value;
        else if(!strcmp(name, "before")) before_str = value;
        else if(!strcmp(name, "points")) points_str = value;
        else if(!strcmp(name, "group")) {
            group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
        }
        else if(!strcmp(name, "options")) {
            options |= web_client_api_request_v1_data_options(value);
        }
        else if(!strcmp(name, "label")) label = value;
        else if(!strcmp(name, "units")) units = value;
        else if(!strcmp(name, "label_color")) label_color = value;
        else if(!strcmp(name, "value_color")) value_color = value;
        else if(!strcmp(name, "multiply")) multiply_str = value;
        else if(!strcmp(name, "divide")) divide_str = value;
        else if(!strcmp(name, "refresh")) refresh_str = value;
        else if(!strcmp(name, "precision")) precision_str = value;
        else if(!strcmp(name, "scale")) scale_str = value;
        else if(!strcmp(name, "alarm")) alarm = value;
    }

    if(!chart || !*chart) {
        buffer_no_cacheable(w->response.data);
        buffer_sprintf(w->response.data, "No chart id is given at the request.");
        goto cleanup;
    }

    int scale = (scale_str && *scale_str)?str2i(scale_str):100;

    RRDSET *st = rrdset_find(host, chart);
    if(!st) st = rrdset_find_byname(host, chart);
    if(!st) {
        buffer_no_cacheable(w->response.data);
        buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0);
        ret = 200;
        goto cleanup;
    }
    st->last_accessed_time = now_realtime_sec();

    RRDCALC *rc = NULL;
    if(alarm) {
        rc = rrdcalc_find(st, alarm);
        if (!rc) {
            buffer_no_cacheable(w->response.data);
            buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0);
            ret = 200;
            goto cleanup;
        }
    }

    long long multiply  = (multiply_str  && *multiply_str )?str2l(multiply_str):1;
    long long divide    = (divide_str    && *divide_str   )?str2l(divide_str):1;
    long long before    = (before_str    && *before_str   )?str2l(before_str):0;
    long long after     = (after_str     && *after_str    )?str2l(after_str):-st->update_every;
    int       points    = (points_str    && *points_str   )?str2i(points_str):1;
    int       precision = (precision_str && *precision_str)?str2i(precision_str):-1;

    if(!multiply) multiply = 1;
    if(!divide) divide = 1;

    int refresh = 0;
    if(refresh_str && *refresh_str) {
        if(!strcmp(refresh_str, "auto")) {
            if(rc) refresh = rc->update_every;
            else if(options & RRDR_OPTION_NOT_ALIGNED)
                refresh = st->update_every;
            else {
                refresh = (int)(before - after);
                if(refresh < 0) refresh = -refresh;
            }
        }
        else {
            refresh = str2i(refresh_str);
            if(refresh < 0) refresh = -refresh;
        }
    }

    if(!label) {
        if(alarm) {
            char *s = (char *)alarm;
            while(*s) {
                if(*s == '_') *s = ' ';
                s++;
            }
            label = alarm;
        }
        else if(dimensions) {
            const char *dim = buffer_tostring(dimensions);
            if(*dim == '|') dim++;
            label = dim;
        }
        else
            label = st->name;
    }
    if(!units) {
        if(alarm) {
            if(rc->units)
                units = rc->units;
            else
                units = "";
        }
        else if(options & RRDR_OPTION_PERCENTAGE)
            units = "%";
        else
            units = st->units;
    }

    debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
          , w->id
          , chart
          , alarm?alarm:""
          , (dimensions)?buffer_tostring(dimensions):""
          , after
          , before
          , points
          , group
          , options
    );

    if(rc) {
        if (refresh > 0) {
            buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
            w->response.data->expires = now_realtime_sec() + refresh;
        }
        else buffer_no_cacheable(w->response.data);

        if(!value_color) {
            switch(rc->status) {
                case RRDCALC_STATUS_CRITICAL:
                    value_color = "red";
                    break;

                case RRDCALC_STATUS_WARNING:
                    value_color = "orange";
                    break;

                case RRDCALC_STATUS_CLEAR:
                    value_color = "brightgreen";
                    break;

                case RRDCALC_STATUS_UNDEFINED:
                    value_color = "lightgrey";
                    break;

                case RRDCALC_STATUS_UNINITIALIZED:
                    value_color = "#000";
                    break;

                default:
                    value_color = "grey";
                    break;
            }
        }

        buffer_svg(w->response.data,
                label,
                (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide,
                units,
                label_color,
                value_color,
                precision,
                scale,
                options
        );
        ret = 200;
    }
    else {
        time_t latest_timestamp = 0;
        int value_is_null = 1;
        calculated_number n = NAN;
        ret = 500;

        // if the collected value is too old, don't calculate its value
        if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
            ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL
                                      , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null);

        // if the value cannot be calculated, show empty badge
        if (ret != 200) {
            buffer_no_cacheable(w->response.data);
            value_is_null = 1;
            n = 0;
            ret = 200;
        }
        else if (refresh > 0) {
            buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
            w->response.data->expires = now_realtime_sec() + refresh;
        }
        else buffer_no_cacheable(w->response.data);

        // render the badge
        buffer_svg(w->response.data,
                label,
                (value_is_null)?NAN:(n * multiply / divide),
                units,
                label_color,
                value_color,
                precision,
                scale,
                options
        );
    }

    cleanup:
    buffer_free(dimensions);
    return ret;
}