/* * Example callback that returns a list of forms. */ static enum conflate_mgmt_cb_result process_ping_test(void *opaque, conflate_handle_t *handle, const char *cmd, bool direct, kvpair_t *form, conflate_form_result *r) { kvpair_t *servers_p = find_kvpair(form, "servers"); if (!servers_p) { return RV_BADARG; } char **servers = servers_p->values; for (int i = 0; servers[i]; i++) { /* For each result we wish to send back, we begin a field set */ conflate_next_fieldset(r); /* All fields added now fall within the current fieldset */ conflate_add_field(r, "-set-", servers[i]); const char *vals[3] = { "val1", "val2", NULL }; conflate_add_field_multi(r, "test1", vals); conflate_add_field(r, "test2", "some val"); } return RV_OK; }
static void ping_server(char *server_name, struct ping_test_recipe *recipes, proxy_behavior *behavior, conflate_form_result *r) { #ifdef MOXI_USE_LIBMEMCACHED assert(server_name); assert(behavior); assert(r); if (strlen(behavior->host) <= 0 || behavior->port <= 0) return; memcached_st mst; memcached_server_st *mservers; struct timeval timing; conflate_next_fieldset(r); conflate_add_field(r, "-set-", server_name); char buf[300] = { 0x00 }; #define dbl_report(name, dval) \ snprintf(buf, sizeof(buf), "%f", dval); \ conflate_add_field(r, name, buf); #define int_report(name, ival) \ snprintf(buf, sizeof(buf), "%d", ival); \ conflate_add_field(r, name, buf); #define tv_report(name, mark, val) \ timeval_subtract(&timing, &val, &mark); \ dbl_report(name, timeval_to_double(timing)); #define stat_report(buf, buflen, name, type, dval) \ snprintf(buf, buflen, "%s_%s", name, type); \ dbl_report(buf, dval); if (memcached_create(&mst) != NULL) { memcached_behavior_set(&mst, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); memcached_behavior_set(&mst, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); snprintf(buf, sizeof(buf), "%s:%u", behavior->host, behavior->port); mservers = memcached_servers_parse(buf); if (mservers != NULL) { memcached_server_push(&mst, mservers); memcached_server_list_free(mservers); mservers = NULL; int nconns = memcached_server_count(&mst); bool connected = false; for (int i = 0; i < nconns; i++) { if (settings.verbose > 1) moxi_log_write("ping_test connecting %d\n", i); struct timeval start; gettimeofday(&start, NULL); mcs_server_st *st = mcs_server_index((void *) &mst, i); mcs_return rc = mcs_server_st_connect(st, NULL, true); if (rc == MCS_SUCCESS) { struct timeval tv_conn; gettimeofday(&tv_conn, NULL); tv_report("conn", start, tv_conn); if (cproxy_auth_downstream(st, behavior, mcs_server_st_fd(st)) && cproxy_bucket_downstream(st, behavior, mcs_server_st_fd(st))) { struct timeval tv_auth; gettimeofday(&tv_auth, NULL); tv_report("auth", tv_conn, tv_auth); // Flag whether to proceed if we connected connected = true; } } } if (connected) { for (int j = 0; recipes[j].name; j++) { struct moxi_stats recipe_stats = { .min = 0.0 }; int failures = 0; perform_ping_test(recipes[j], &mst, &recipe_stats, &failures); int vlen = strlen(recipes[j].name) + 8; char val_name[vlen]; stat_report(val_name, vlen, recipes[j].name, "min", recipe_stats.min); stat_report(val_name, vlen, recipes[j].name, "avg", recipe_stats.avg); stat_report(val_name, vlen, recipes[j].name, "max", recipe_stats.max); stat_report(val_name, vlen, recipes[j].name, "stddev", recipe_stats.stddev); stat_report(val_name, vlen, recipes[j].name, "95th", recipe_stats.ninetyfifth); snprintf(val_name, vlen, "%s_fail", recipes[j].name); int_report(val_name, failures); } } } else {