// Query all counters except for memory counters. static void cmd_counters(ph_sock_t *sock) { #define NUM_SLOTS 64 #define NUM_COUNTERS 2048 struct counter_name_val counter_data[NUM_COUNTERS]; int64_t view_slots[NUM_SLOTS]; const char *view_names[NUM_SLOTS]; ph_counter_scope_iterator_t iter; uint32_t num_slots, i; uint32_t n_counters = 0; uint32_t longest_name = 0; char name[69]; // Collect all counter data; it is returned in an undefined order. // For the sake of testing we want to order it, so we collect the data // and then sort it ph_counter_scope_iterator_init(&iter); ph_counter_scope_t *iter_scope; while ((iter_scope = ph_counter_scope_iterator_next(&iter)) != NULL) { uint32_t slen; if (strncmp(ph_counter_scope_get_name(iter_scope), "memory/", 7) == 0) { ph_counter_scope_delref(iter_scope); continue; } slen = strlen(ph_counter_scope_get_name(iter_scope)); num_slots = ph_counter_scope_get_view(iter_scope, NUM_SLOTS, view_slots, view_names); for (i = 0; i < num_slots; i++) { uint32_t l = strlen(view_names[i]); longest_name = MAX(longest_name, l + slen + 1); counter_data[n_counters].scope_name = ph_counter_scope_get_name(iter_scope); counter_data[n_counters].name = view_names[i]; counter_data[n_counters].val = view_slots[i]; n_counters++; if (n_counters >= NUM_COUNTERS) { break; } } ph_counter_scope_delref(iter_scope); if (n_counters >= NUM_COUNTERS) { break; } } qsort(counter_data, n_counters, sizeof(struct counter_name_val), compare_counter_name_val); for (i = 0; i < n_counters; i++) { ph_snprintf(name, sizeof(name), "%s/%s", counter_data[i].scope_name, counter_data[i].name); ph_stm_printf(sock->stream, "%*s %16" PRIi64"\r\n", longest_name, name, counter_data[i].val); } if (n_counters >= NUM_COUNTERS) { ph_stm_printf(sock->stream, "WARNING: too many counters to sort, output truncated\r\n"); } }
static void basicCounterFunctionality(void) { ph_counter_scope_t *scope; scope = ph_counter_scope_define(NULL, "test1", 24); is_true(scope != NULL); is_string("test1", ph_counter_scope_get_name(scope)); uint8_t slot = ph_counter_scope_register_counter(scope, "dummy"); is(0, slot); ph_counter_scope_add(scope, slot, 1); is(1, ph_counter_scope_get(scope, slot)); ph_counter_scope_add(scope, slot, 1); is(2, ph_counter_scope_get(scope, slot)); ph_counter_scope_add(scope, slot, 3); is(5, ph_counter_scope_get(scope, slot)); /* register some more slots */ const char *names[2] = {"sent", "recd"}; is_true(ph_counter_scope_register_counter_block( scope, 2, slot + 1, names)); ph_counter_block_t *block = ph_counter_block_open(scope); is_true(block != NULL); ph_counter_block_add(block, slot + 1, 3); is(3, ph_counter_scope_get(scope, slot + 1)); // C++, clogging up code with casts since the last century uint8_t bulk_slots[2] = { (uint8_t)(slot + 1), (uint8_t)(slot + 2) }; int64_t values[2] = { 1, 5 }; ph_counter_block_bulk_add(block, 2, bulk_slots, values); is(4, ph_counter_scope_get(scope, slot + 1)); is(5, ph_counter_scope_get(scope, slot + 2)); uint8_t num_slots; int64_t view_slots[10]; const char *view_names[10]; num_slots = ph_counter_scope_get_view(scope, 10, view_slots, view_names); is(3, num_slots); is(5, view_slots[0]); is(4, view_slots[1]); is(5, view_slots[2]); is_string("dummy", view_names[0]); is_string("sent", view_names[1]); is_string("recd", view_names[2]); ph_counter_scope_t *kid_scope; // Verify that attempting to define the same scope twice fails kid_scope = ph_counter_scope_define(NULL, "test1", 24); is_true(kid_scope == NULL); // Get ourselves a real child kid_scope = ph_counter_scope_define(scope, "child", 8); is_true(kid_scope != NULL); is_string("test1.child", ph_counter_scope_get_name(kid_scope)); ph_counter_scope_t *resolved; resolved = ph_counter_scope_resolve(NULL, "test1"); is(scope, resolved); resolved = ph_counter_scope_resolve(NULL, "test1.child"); is(kid_scope, resolved); ph_counter_scope_register_counter(kid_scope, "w00t"); // Test iteration struct counter_name_val counter_data[16]; int n_counters = 0; ph_counter_scope_iterator_t iter; // Collect all counter data; it is returned in an undefined order. // For the sake of testing we want to order it, so we collect the data // and then sort it ph_counter_scope_iterator_init(&iter); ph_counter_scope_t *iter_scope; while ((iter_scope = ph_counter_scope_iterator_next(&iter)) != NULL) { int i; if (strncmp(ph_counter_scope_get_name(iter_scope), "test1", 5)) { continue; } num_slots = ph_counter_scope_get_view(iter_scope, 10, view_slots, view_names); for (i = 0; i < num_slots; i++) { counter_data[n_counters].scope_name = ph_counter_scope_get_name(iter_scope); counter_data[n_counters].name = view_names[i]; counter_data[n_counters].val = view_slots[i]; n_counters++; } ph_counter_scope_delref(iter_scope); } qsort(counter_data, n_counters, sizeof(struct counter_name_val), compare_counter_name_val); struct counter_name_val expected_data[] = { { "test1", "dummy", 5 }, { "test1", "recd", 5 }, { "test1", "sent", 4 }, { "test1.child", "w00t", 0 }, }; int num_expected = sizeof(expected_data) / sizeof(expected_data[0]); is_int(num_expected, n_counters); for (int i = 0; i < n_counters; i++) { is_string(expected_data[i].scope_name, counter_data[i].scope_name); is_string(expected_data[i].name, counter_data[i].name); is(expected_data[i].val, counter_data[i].val); diag("%s.%s = %" PRIi64, counter_data[i].scope_name, counter_data[i].name, counter_data[i].val); } }