예제 #1
0
int get_masters(time_t stoptime)
{
	struct catalog_query *cq;
	struct nvpair *nv;
	int i = 0; //nvpair pointer array iterator
	if(!catalog_host) {
		catalog_host = strdup(CATALOG_HOST);
		catalog_port = CATALOG_PORT;
	}

	cq = catalog_query_create(catalog_host, catalog_port, stoptime );
	if(!cq) {
		fprintf(stderr, "failed to query catalog server %s:%d: %s \n",catalog_host,catalog_port,strerror(errno));
		exit(EXIT_FAILURE);
		return 0;
	}

	while((nv = catalog_query_read(cq,stoptime))) {
		resize_catalog(i);
		if(strcmp(nvpair_lookup_string(nv, "type"), CATALOG_TYPE_WORK_QUEUE_MASTER) == 0) {
			global_catalog[i] = nv; //make the global catalog point to this memory that nv references
			i++; //only increment i when a master nvpair is found
		}else{
			nvpair_delete(nv); //free the memory so something valid can take its place
		}
	}
	resize_catalog(i);
	global_catalog[i] = NULL;
	catalog_query_delete(cq);

	return 1;
}
예제 #2
0
static int server_table_load(time_t stoptime)
{
	struct catalog_query *q;
	struct jx *j;
	char *key;
	void *item;

	if((last_update + update_interval) > time(0)) {
		return 1;
	}

	if(!server_table) {
		server_table = hash_table_create(0, 0);
		if(!server_table)
			return 0;
	}

	if(inhibit_catalog_queries) {
		debug(D_CHIRP, "catalog queries disabled\n");
		return 1;
	}

	hash_table_firstkey(server_table);
	while(hash_table_nextkey(server_table, &key, &item)) {
		hash_table_remove(server_table, key);
		jx_delete(item);
	}

	debug(D_CHIRP, "querying catalog at %s:%d", CATALOG_HOST, CATALOG_PORT);

	q = catalog_query_create(CATALOG_HOST, CATALOG_PORT, stoptime);
	if(!q)
		return 0;

	while((j = catalog_query_read(q, stoptime))) {
		char name[CHIRP_PATH_MAX];
		const char *type, *hname;
		int port;

		type = jx_lookup_string(j, "type");
		if(type && !strcmp(type, "chirp")) {
			hname = jx_lookup_string(j, "name");
			if(hname) {
				port = jx_lookup_integer(j, "port");
				if(!port)
					port = CHIRP_PORT;
				sprintf(name, "%s:%d", hname, port);
				hash_table_insert(server_table, name, j);
			} else {
				jx_delete(j);
			}
		} else {
			jx_delete(j);
		}
	}
	catalog_query_delete(q);
	last_update = time(0);

	return 1;
}
struct list *get_masters_from_catalog(const char *catalog_host, int catalog_port, struct list *regex_list)
{
	struct catalog_query *q;
	struct nvpair *nv;
	struct list *ml;
	struct work_queue_master *m;
	char *regex;
	time_t timeout = 60, stoptime;

	stoptime = time(0) + timeout;

	q = catalog_query_create(catalog_host, catalog_port, stoptime);
	if(!q) {
		fprintf(stderr, "Failed to query catalog server at %s:%d\n", catalog_host, catalog_port);
		return NULL;
	}

	ml = list_create();
	if(!ml)
		return NULL;

	while((nv = catalog_query_read(q, stoptime))) {
		if(strcmp(nvpair_lookup_string(nv, "type"), CATALOG_TYPE_WORK_QUEUE_MASTER) == 0) {
			m = parse_work_queue_master_nvpair(nv);
			if(m) {
				if(regex_list) {
					// Matched preferred masters
					int match_found = 0;
					list_first_item(regex_list);
					while((regex = (char *)list_next_item(regex_list))) {
						if(whole_string_match_regex(m->proj, regex)) {
							debug(D_WQ, "Master matched: %s -> %s\n", regex, m->proj);
							list_push_head(ml, m);
							match_found = 1;
							break;
						}
					}
					if(match_found == 0) {
						free_work_queue_master(m);
					}
				} else {
					list_push_head(ml, m);
				}
			} else {
				fprintf(stderr, "Failed to parse a work queue master record!\n");
			}
		}
		nvpair_delete(nv);
	}

	// Must delete the query otherwise it would occupy 1 tcp connection forever!
	catalog_query_delete(q);
	return ml;
}
int get_pool_decisions_from_catalog(const char *catalog_host, int catalog_port, const char *proj, struct list *decisions) {
	struct catalog_query *q;
	struct nvpair *nv;
	time_t timeout = 60, stoptime;

	stoptime = time(0) + timeout;

	if(!decisions) {
		fprintf(stderr, "No list to store pool decisions.\n");
		return 0;
	}

	q = catalog_query_create(catalog_host, catalog_port, stoptime);
	if(!q) {
		fprintf(stderr, "Failed to query catalog server at %s:%d\n", catalog_host, catalog_port);
		return 0;
	}
	

	// multiple pools
	while((nv = catalog_query_read(q, stoptime))) {
		if(strcmp(nvpair_lookup_string(nv, "type"), CATALOG_TYPE_WORK_QUEUE_POOL) == 0) {
			struct work_queue_pool *p;
			p = parse_work_queue_pool_nvpair(nv);
			debug(D_WQ, "pool %s's decision: %s\n", p->name, p->decision);
			int x = workers_by_item(p->decision, proj);
			if(x >= 0) {
				struct pool_info *pi;
				pi = (struct pool_info *)xxmalloc(sizeof(*pi));
				strncpy(pi->name, p->name, WORK_QUEUE_POOL_NAME_MAX);
				pi->count = x;
				list_push_tail(decisions, pi);
			}
			free(p->decision);
			free(p);
			
		}
		nvpair_delete(nv);
	}

	// Must delete the query otherwise it would occupy 1 tcp connection forever!
	catalog_query_delete(q);
	return 1;
}
int main(int argc, char *argv[])
{
	struct catalog_query *cq;
	struct nvpair *nv;

	work_queue_status_parse_command_line_arguments(argc, argv);

	if(optind > argc) {
		work_queue_status_show_help("work_queue_status");
		exit(EXIT_FAILURE);
	}

	cq = catalog_query_create(CATALOG_HOST, CATALOG_PORT, time(0) + Work_Queue_Status_Timeout);
	if(!cq) {
		fprintf(stderr, "couldn't query catalog %s:%d: %s\n", CATALOG_HOST, CATALOG_PORT, strerror(errno));
		return 1;                                                                                                                                      
	}

	if(Work_Queue_Status_Mode == MODE_TABLE)
		nvpair_print_table_header(stdout, headers);

	while((nv = catalog_query_read(cq, time(0) + Work_Queue_Status_Timeout))) {
		if(strcmp(nvpair_lookup_string(nv, "type"), CATALOG_TYPE_WORK_QUEUE_MASTER) == 0) {
			if(Work_Queue_Status_Mode == MODE_TABLE)
				nvpair_print_table(nv, stdout, headers);
			else
				nvpair_print_text(nv, stdout);
		}
		nvpair_delete(nv);
	}

	if(Work_Queue_Status_Mode == MODE_TABLE)
		nvpair_print_table_footer(stdout, headers);

	return EXIT_SUCCESS;
}
예제 #6
0
int main(int argc, char *argv[])
{
	struct catalog_query *q;
	struct nvpair *n;
	time_t timeout = 60, stoptime;
	const char *catalog_host = 0;
	signed char c;
	int i;
	int count = 0;
	int mode = MODE_TABLE;
	INT64_T total = 0, avail = 0;
	const char *filter_name = 0;
	const char *filter_value = 0;

	debug_config(argv[0]);


	static struct option long_options[] = {
		{"catalog", required_argument, 0, 'c'},
		{"debug", required_argument, 0, 'd'},
		{"debug-file", required_argument, 0, 'o'},
		{"debug-rotate-max", required_argument, 0, 'O'},
		{"server-space", required_argument, 0, 'A'},
		{"all", no_argument, 0, 'a'},
		{"timeout", required_argument, 0, 't'},
		{"brief", no_argument, 0, 's'},
		{"verbose", no_argument, 0, 'l'},
		{"totals", no_argument, 0, 'T'},
		{"version", no_argument, 0, 'v'},
		{"help", no_argument, 0, 'h'},
		{0, 0, 0, 0}
	};

	while((c = getopt_long(argc, argv, "aA:c:d:t:o:O:sTlvh", long_options, NULL)) > -1) {
		switch (c) {
		case 'a':
			show_all_types = 1;
			break;
		case 'c':
			catalog_host = optarg;
			break;
		case 'd':
			debug_flags_set(optarg);
			break;
		case 't':
			timeout = string_time_parse(optarg);
			break;
		case 'A':
			minavail = string_metric_parse(optarg);
			break;
		case 'o':
			debug_config_file(optarg);
			break;
		case 'O':
			debug_config_file_size(string_metric_parse(optarg));
			break;
		case 'v':
			cctools_version_print(stdout, argv[0]);
			return 1;
		case 's':
			mode = MODE_SHORT;
			break;
		case 'l':
			mode = MODE_LONG;
			break;
		case 'T':
			mode = MODE_TOTAL;
			break;
		case 'h':
		default:
			show_help(argv[0]);
			return 1;
		}
	}

	cctools_version_debug(D_DEBUG, argv[0]);

	if(argc - optind == 0) {
		// fine, keep going
	} else if((argc - optind) == 1) {
		filter_name = "name";
		filter_value = argv[optind];
	} else if((argc - optind) == 2) {
		filter_name = argv[optind];
		filter_value = argv[optind + 1];
	} else {
		show_help(argv[0]);
		return 1;
	}

	stoptime = time(0) + timeout;

	q = catalog_query_create(catalog_host, 0, stoptime);
	if(!q) {
		fprintf(stderr, "couldn't query catalog: %s\n", strerror(errno));
		return 1;
	}

	if(mode == MODE_TABLE) {
		nvpair_print_table_header(stdout, headers);
	}

	while((n = catalog_query_read(q, stoptime))) {
		table[count++] = n;
	}

	qsort(table, count, sizeof(*table), (int (*)(const void *, const void *)) compare_entries);

	for(i = 0; i < count; i++) {
		const char *etype = nvpair_lookup_string(table[i], "type");
		if(!show_all_types) {
			if(etype) {
				if(!strcmp(etype, "chirp") || !strcmp(etype, "catalog")) {
					/* ok, keep going */
				} else {
					continue;
				}
			} else {
				continue;
			}
		}

		if(minavail != 0) {
			if(minavail > nvpair_lookup_integer(table[i], "avail")) {
				continue;
			}
		}

		if(filter_name) {
			const char *v = nvpair_lookup_string(table[i], filter_name);
			if(!v || strcmp(filter_value, v))
				continue;
		}

		if(mode == MODE_SHORT) {
			const char *t = nvpair_lookup_string(table[i], "type");
			if(t && !strcmp(t, "chirp")) {
				printf("%s:%d\n", nvpair_lookup_string(table[i], "name"), (int) nvpair_lookup_integer(table[i], "port"));
			}
		} else if(mode == MODE_LONG) {
			nvpair_print_text(table[i], stdout);
		} else if(mode == MODE_TABLE) {
			nvpair_print_table(table[i], stdout, headers);
		} else if(mode == MODE_TOTAL) {
			avail += nvpair_lookup_integer(table[i], "avail");
			total += nvpair_lookup_integer(table[i], "total");
		}
	}

	if(mode == MODE_TOTAL) {
		printf("NODES: %4d\n", count);
		printf("TOTAL: %6sB\n", string_metric(total, -1, 0));
		printf("AVAIL: %6sB\n", string_metric(avail, -1, 0));
		printf("INUSE: %6sB\n", string_metric(total - avail, -1, 0));
	}

	if(mode == MODE_TABLE) {
		nvpair_print_table_footer(stdout, headers);
	}

	return 0;
}
예제 #7
0
int main(int argc, char *argv[])
{
	enum {
		LONGOPT_SERVER_LASTHEARDFROM = INT_MAX-0,
		LONGOPT_SERVER_PROJECT       = INT_MAX-1,
		LONGOPT_WHERE = INT_MAX-2,
	};

	static const struct option long_options[] = {
		{"all", no_argument, 0, 'a'},
		{"brief", no_argument, 0, 's'},
		{"catalog", required_argument, 0, 'c'},
		{"debug", required_argument, 0, 'd'},
		{"debug-file", required_argument, 0, 'o'},
		{"debug-rotate-max", required_argument, 0, 'O'},
		{"help", no_argument, 0, 'h'},
		{"server-lastheardfrom", required_argument, 0, LONGOPT_SERVER_LASTHEARDFROM},
		{"server-project", required_argument, 0, LONGOPT_SERVER_PROJECT},
		{"server-space", required_argument, 0, 'A'},
		{"timeout", required_argument, 0, 't'},
		{"totals", no_argument, 0, 'T'},
		{"verbose", no_argument, 0, 'l'},
		{"version", no_argument, 0, 'v'},
		{"where", required_argument, 0, LONGOPT_WHERE },
		{0, 0, 0, 0}
	};

	struct catalog_query *q;
	struct jx *j;
	time_t timeout = 60, stoptime;
	const char *catalog_host = 0;
	int i;
	int c;
	int count = 0;
	int mode = MODE_TABLE;
	INT64_T sum_total = 0, sum_avail = 0;
	const char *filter_name = 0;
	const char *filter_value = 0;
	const char *where_expr = "true";
	int show_all_types = 0;

	const char *server_project = NULL;
	time_t      server_lastheardfrom = 0;
	uint64_t    server_avail = 0;

	debug_config(argv[0]);

	while((c = getopt_long(argc, argv, "aA:c:d:t:o:O:sTlvh", long_options, NULL)) > -1) {
		switch (c) {
		case 'a':
			show_all_types = 1;
			break;
		case 'c':
			catalog_host = optarg;
			break;
		case 'd':
			debug_flags_set(optarg);
			break;
		case 't':
			timeout = string_time_parse(optarg);
			break;
		case 'A':
			server_avail = string_metric_parse(optarg);
			break;
		case 'o':
			debug_config_file(optarg);
			break;
		case 'O':
			debug_config_file_size(string_metric_parse(optarg));
			break;
		case 'v':
			cctools_version_print(stdout, argv[0]);
			return 1;
		case 's':
			mode = MODE_SHORT;
			break;
		case 'l':
			mode = MODE_LONG;
			break;
		case 'T':
			mode = MODE_TOTAL;
			break;
		case LONGOPT_SERVER_LASTHEARDFROM:
			server_lastheardfrom = time(0)-string_time_parse(optarg);
			break;
		case LONGOPT_SERVER_PROJECT:
			server_project = xxstrdup(optarg);
			break;
		case LONGOPT_WHERE:
			where_expr = optarg;
			break;
		case 'h':
		default:
			show_help(argv[0]);
			return 1;
		}
	}

	cctools_version_debug(D_DEBUG, argv[0]);

	if(argc - optind == 0) {
		// fine, keep going
	} else if((argc - optind) == 1) {
		filter_name = "name";
		filter_value = argv[optind];
	} else if((argc - optind) == 2) {
		filter_name = argv[optind];
		filter_value = argv[optind + 1];
	} else {
		show_help(argv[0]);
		return 1;
	}

	stoptime = time(0) + timeout;

	const char *query_expr;

	if(show_all_types) {
		query_expr = where_expr;
	} else {
		query_expr = string_format("%s && (type==\"chirp\" || type==\"catalog\")",where_expr);
	}

	struct jx *jexpr = jx_parse_string(query_expr);
	if(!jexpr) {
		fprintf(stderr,"invalid expression: %s\n",query_expr);
		return 1;
	}

	q = catalog_query_create(catalog_host, 0, jexpr, stoptime);
	if(!q) {
		fprintf(stderr, "couldn't query catalog: %s\n", strerror(errno));
		return 1;
	}

	if(mode == MODE_TABLE) {
		jx_table_print_header(headers,stdout);
	} else if(mode==MODE_LONG) {
		printf("[\n");
	}

	while((j = catalog_query_read(q, stoptime))) {
		table[count++] = j;
	}

	catalog_query_delete(q);

	qsort(table, count, sizeof(*table), (int (*)(const void *, const void *)) compare_entries);

	for(i = 0; i < count; i++) {
		const char *lastheardfrom = jx_lookup_string(table[i], "lastheardfrom");
		if (lastheardfrom && (time_t)strtoul(lastheardfrom, NULL, 10) < server_lastheardfrom)
			continue;

		const char *avail = jx_lookup_string(table[i], "avail");
		if (avail && strtoul(avail, NULL, 10) < server_avail)
			continue;

		const char *project = jx_lookup_string(table[i], "project");
		if (server_project && (project == NULL || !(strcmp(project, server_project) == 0)))
			continue;

		if(filter_name) {
			const char *v = jx_lookup_string(table[i], filter_name);
			if(!v || strcmp(filter_value, v))
				continue;
		}

		if(mode == MODE_SHORT) {
			const char *t = jx_lookup_string(table[i], "type");
			if(t && !strcmp(t, "chirp")) {
				printf("%s:%d\n", jx_lookup_string(table[i], "name"), (int) jx_lookup_integer(table[i], "port"));
			}
		} else if(mode == MODE_LONG) {
			if(i!=0) printf(",\n");
			jx_print_stream(table[i],stdout);
		} else if(mode == MODE_TABLE) {
			jx_table_print(headers, table[i], stdout);
		} else if(mode == MODE_TOTAL) {
			sum_avail += jx_lookup_integer(table[i], "avail");
			sum_total += jx_lookup_integer(table[i], "total");
		}
	}

	for(i=0;i<count;i++) {
		jx_delete(table[i]);
	}

	if(mode == MODE_TOTAL) {
		printf("NODES: %4d\n", count);
		printf("TOTAL: %6sB\n", string_metric(sum_total, -1, 0));
		printf("AVAIL: %6sB\n", string_metric(sum_avail, -1, 0));
		printf("INUSE: %6sB\n", string_metric(sum_total - sum_avail, -1, 0));
	} else if(mode == MODE_TABLE) {
		jx_table_print_footer(headers,stdout);
	} else if(mode==MODE_LONG) {
		printf("\n]\n");
	}

	return 0;
}
예제 #8
0
/*
 * Obtains information from the Catalog, format it, and make return it to user.
 */
int main(int argc, char** argv) {

    static const struct option long_options[] = {
        {"help", no_argument, 0, 'h'},
        {"project", required_argument, 0, 'N'},
        {"server", required_argument, 0, 's'},
        {"timeout", required_argument, 0, 't'},
        {"username", required_argument, 0, 'u'},
        {0, 0, 0, 0}
    };

    struct catalog_query *q;
    struct jx *j;
    int c;
    unsigned int i;
    time_t timeout = 60;
    char* catalog_host = NULL;
    
    char* username = NULL;
    char* project = NULL;
    
    char* server = NULL;
    
    while ((c = getopt_long(argc, argv, "N:t:u:w:s:h", long_options, NULL)) > -1) {
        switch (c) {
            case 'N':
                project = xxstrdup(optarg);
                break;
            case 't':
                timeout = string_time_parse(optarg);
                break;
            case 'u':
                username = xxstrdup(optarg);
                break;
            case 's':
                server = xxstrdup(optarg);
                break;
            case 'h':
            default:
                show_help(argv[0]);
                return 1;
        }
    }
    
    //setup address
    if(server==NULL){
        catalog_host = CATALOG_HOST;
    }

    //make query
    struct jx *jexpr = jx_operator(
        JX_OP_EQ,
        jx_symbol("type"),
        jx_string("makeflow")
    );

    if (project) {
        jexpr = jx_operator(
            JX_OP_AND,
            jexpr,
            jx_operator(
                JX_OP_EQ,
                jx_symbol("project"),
                jx_string(project)
            )
        );
    }

    if (username) {
        jexpr = jx_operator(
            JX_OP_AND,
            jexpr,
            jx_operator(
                JX_OP_EQ,
                jx_symbol("username"),
                jx_string(username)
            )
        );
    }

    time_t stoptime = time(0) + timeout;
    unsigned int count = 0;
    
    //create catalog_query from jx
    q = catalog_query_create(catalog_host, jexpr, stoptime);
    if (!q) {
        fprintf(stderr, "couldn't query catalog: %s\n", strerror(errno));
        return 1;
    }


    while ((j = catalog_query_read(q, stoptime))) {
        table[count++] = j;
    }
    
    catalog_query_delete(q);//all done with connection

    //sort
    qsort(table, count, sizeof(*table), (int (*)(const void *, const void *)) compare_entries);
    
    //print them out
    printf("%-10s %-18s %6s %6s %6s %6s %6s %6s %6s\n",
	   "OWNER", "PROJECT", "JOBS", "WAIT", "RUN", "COMP", "ABRT", "FAIL", "TYPE");
    for(i=0; i<count; i++){
        printf("%-10s %-18s %6" PRId64 " %6" PRId64 " %6" PRId64 " %6" PRId64 " %6" PRId64 " %6" PRId64 " %6s\n",
		jx_lookup_string(table[i], "owner"),
		jx_lookup_string(table[i], "project"),
		jx_lookup_integer(table[i], "total"),
		jx_lookup_integer(table[i], "waiting"),
		jx_lookup_integer(table[i], "running"),
		jx_lookup_integer(table[i], "completed"),
		jx_lookup_integer(table[i], "aborted"),
		jx_lookup_integer(table[i], "failed"),
		jx_lookup_string(table[i], "batch_type")
	);
    }
    printf("\n");//be polite
    
    //cleanup
    for(i=0;i<count;i++) {
	jx_delete(table[i]);
    }

    //done
    return (EXIT_SUCCESS);
}
예제 #9
0
CONFUGA_IAPI int confugaS_catalog_sync (confuga *C)
{
	static const char SQL[] =
		"SELECT COUNT(*) FROM Confuga.StorageNode WHERE strftime('%s', 'now', '-2 minutes') <= lastheardfrom;"
		"BEGIN IMMEDIATE TRANSACTION;"
		"UPDATE Confuga.StorageNode"
		"    SET address = ?, avail = ?, backend = ?, bytes_read = ?, bytes_written = ?, cpu = ?, cpus = ?, lastheardfrom = ?, load1 = ?, load5 = ?, load15 = ?, memory_avail = ?, memory_total = ?, minfree = ?, name = ?, opsys = ?, opsysversion = ?, owner = ?, port = ?, starttime = ?, total = ?, total_ops = ?, url = ?, version = ?"
		"    WHERE hostport = ? || ':' || ? OR"
		"          hostport = ? || ':' || ? OR"
		"          'chirp://' || hostport = ?;"
		"END TRANSACTION;";

	int rc;
	sqlite3 *db = C->db;
	sqlite3_stmt *stmt = NULL;
	const char *current = SQL;
	time_t stoptime = time(NULL)+15;
	struct catalog_query *Q = NULL;
	struct nvpair *nv = NULL;

	sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
	sqlcatchcode(sqlite3_step(stmt), SQLITE_ROW);
	if (sqlite3_column_int(stmt, 0) > 0) {
		rc = 0;
		goto out;
	}
	sqlcatch(sqlite3_finalize(stmt); stmt = NULL);

	debug(D_DEBUG|D_CONFUGA, "syncing with catalog");

	Q = catalog_query_create(C->catalog_host, C->catalog_port, stoptime);
	CATCH(Q == NULL ? errno : 0);

	/* FIXME sqlcatch is silent about EAGAIN, what should we do? */

	sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
	sqlcatchcode(sqlite3_step(stmt), SQLITE_DONE);
	sqlcatch(sqlite3_finalize(stmt); stmt = NULL);

	sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
	while ((nv = catalog_query_read(Q, stoptime))) {
		const char *type = nvpair_lookup_string(nv, "type");
		if (type && strcmp(type, "chirp") == 0) {
			int n = 1;
			/* UPDATE */
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "address"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "avail"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "backend"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "bytes_read"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "bytes_written"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "cpu"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "cpus"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "lastheardfrom"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "load1"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "load5"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "load15"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "memory_avail"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "memory_total"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "minfree"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "name"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "opsys"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "opsysversion"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "owner"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "port"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "starttime"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "total"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "total_ops"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "url"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "version"), -1, SQLITE_TRANSIENT));
			/* WHERE hostport = ? */
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "name"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "port"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "address"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "port"), -1, SQLITE_TRANSIENT));
			sqlcatch(sqlite3_bind_text(stmt, n++, nvpair_lookup_string(nv, "url"), -1, SQLITE_TRANSIENT));
			sqlcatchcode(sqlite3_step(stmt), SQLITE_DONE);
			sqlcatch(sqlite3_reset(stmt));
			sqlcatch(sqlite3_clear_bindings(stmt));
		}
	}
	sqlcatch(sqlite3_finalize(stmt); stmt = NULL);

	sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
	sqlcatchcode(sqlite3_step(stmt), SQLITE_DONE);
	sqlcatch(sqlite3_finalize(stmt); stmt = NULL);

	rc = 0;
	goto out;
out:
	if (Q)
		catalog_query_delete(Q);
	sqlite3_finalize(stmt);
	sqlend(db);
	return rc;
}