bool get_stats(const char *stat_type, int nkey, ADD_STAT add_stats, void *c) { bool ret = true; if (add_stats != NULL) { if (!stat_type) { /* prepare general statistics for the engine */ STATS_LOCK(); APPEND_STAT("bytes", "%llu", (unsigned long long)stats.curr_bytes); APPEND_STAT("curr_items", "%u", stats.curr_items); APPEND_STAT("total_items", "%u", stats.total_items); APPEND_STAT("evictions", "%llu", (unsigned long long)stats.evictions); APPEND_STAT("reclaimed", "%llu", (unsigned long long)stats.reclaimed); STATS_UNLOCK(); } else if (nz_strcmp(nkey, stat_type, "items") == 0) { item_stats(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "slabs") == 0) { slabs_stats(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "sizes") == 0) { item_stats_sizes(add_stats, c); } else { ret = false; } } else { ret = false; } return ret; }
/** * mc_get_stats() - get a datum for stats in binary protocol * @stat_type : * @nkey : * @f : * @c : * * Return 0 on success, otherwise errno. */ int mc_get_stats(const char *stat_type, int nkey, add_stat_fn f, void *c) { int ret = 0; if (f) { if (!stat_type) { /* prepare general statistics for the engine */ u32 curr_items; u32 total_items; u64 curr_bytes; curr_items = ATOMIC32_READ(stats.curr_items); curr_bytes = ATOMIC64_READ(stats.curr_bytes); total_items= ATOMIC32_READ(stats.total_items); APPEND_STAT("bytes", "%llu", (unsigned long long)curr_bytes); APPEND_STAT("curr_items", "%u", curr_items); APPEND_STAT("total_items", "%u", total_items); mc_item_stats_totals(f, c); } else if (nz_strcmp(nkey, stat_type, "items") == 0) { mc_item_stats(f, c); } else if (nz_strcmp(nkey, stat_type, "slabs") == 0) { mc_slabs_stats(f, c); } else if (nz_strcmp(nkey, stat_type, "sizes") == 0) { mc_item_stats_sizes(f, c); } else { ret = -EFAULT; } } else { ret = -EFAULT; } return ret; }
static void mc_do_slabs_stats(add_stat_fn f, void *c) { static struct thread_stats thread_stats; int i, total; mc_threadlocal_stats_aggregate(&thread_stats); total = 0; for(i = POWER_SMALLEST; i <= power_largest; i++) { slabclass_t *p = &slabclass[i]; if (p->slabs != 0) { int klen = 0, vlen = 0; char key_str[STAT_KEY_LEN]; char val_str[STAT_VAL_LEN]; u32 perslab, slabs; slabs = p->slabs; perslab = p->perslab; APPEND_NUM_STAT(i, "chunk_size", "%u", p->size); APPEND_NUM_STAT(i, "chunks_per_page", "%u", perslab); APPEND_NUM_STAT(i, "total_pages", "%u", slabs); APPEND_NUM_STAT(i, "total_chunks", "%u", slabs * perslab); APPEND_NUM_STAT(i, "used_chunks", "%u", slabs*perslab - p->sl_curr); APPEND_NUM_STAT(i, "free_chunks", "%u", p->sl_curr); /* Stat is dead, but displaying zero instead of removing it. */ APPEND_NUM_STAT(i, "free_chunks_end", "%u", 0); APPEND_NUM_STAT(i, "mem_requested", "%llu", (unsigned long long)p->requested); APPEND_NUM_STAT(i, "get_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].get_hits); APPEND_NUM_STAT(i, "cmd_set", "%llu", (unsigned long long)thread_stats.slab_stats[i].set_cmds); APPEND_NUM_STAT(i, "delete_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].delete_hits); APPEND_NUM_STAT(i, "incr_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].incr_hits); APPEND_NUM_STAT(i, "decr_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].decr_hits); APPEND_NUM_STAT(i, "cas_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].cas_hits); APPEND_NUM_STAT(i, "cas_badval", "%llu", (unsigned long long)thread_stats.slab_stats[i].cas_badval); APPEND_NUM_STAT(i, "touch_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].touch_hits); total++; } } /* add overall slab stats and append terminator */ APPEND_STAT("active_slabs", "%d", total); APPEND_STAT("total_malloced", "%llu", (unsigned long long)mem_malloced); f(NULL, 0, NULL, 0, c); }
/*@null@*/ static void do_slabs_stats(ADD_STAT add_stats, void *c) { int i, total; /* Get the per-thread stats which contain some interesting aggregates */ struct thread_stats thread_stats; threadlocal_stats_aggregate(&thread_stats); total = 0; for(i = POWER_SMALLEST; i <= power_largest; i++) { slabclass_t *p = &slabclass[i]; if (p->slabs != 0) { uint32_t perslab, slabs; slabs = p->slabs; perslab = p->perslab; char key_str[STAT_KEY_LEN]; char val_str[STAT_VAL_LEN]; int klen = 0, vlen = 0; APPEND_NUM_STAT(i, "chunk_size", "%u", p->size); APPEND_NUM_STAT(i, "chunks_per_page", "%u", perslab); APPEND_NUM_STAT(i, "total_pages", "%u", slabs); APPEND_NUM_STAT(i, "total_chunks", "%u", slabs * perslab); APPEND_NUM_STAT(i, "used_chunks", "%u", slabs*perslab - p->sl_curr - p->end_page_free); APPEND_NUM_STAT(i, "free_chunks", "%u", p->sl_curr); APPEND_NUM_STAT(i, "free_chunks_end", "%u", p->end_page_free); APPEND_NUM_STAT(i, "mem_requested", "%llu", (unsigned long long)p->requested); APPEND_NUM_STAT(i, "get_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].get_hits); APPEND_NUM_STAT(i, "cmd_set", "%llu", (unsigned long long)thread_stats.slab_stats[i].set_cmds); APPEND_NUM_STAT(i, "delete_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].delete_hits); APPEND_NUM_STAT(i, "incr_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].incr_hits); APPEND_NUM_STAT(i, "decr_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].decr_hits); APPEND_NUM_STAT(i, "cas_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].cas_hits); APPEND_NUM_STAT(i, "cas_badval", "%llu", (unsigned long long)thread_stats.slab_stats[i].cas_badval); APPEND_NUM_STAT(i, "touch_hits", "%llu", (unsigned long long)thread_stats.slab_stats[i].touch_hits); total++; } } /* add overall slab stats and append terminator */ APPEND_STAT("active_slabs", "%d", total); APPEND_STAT("total_malloced", "%llu", (unsigned long long)mem_malloced); add_stats(NULL, 0, NULL, 0, c); }
/*@null@*/ void do_item_stats_sizes(ADD_STAT add_stats, void *c) { /* max 1MB object, divided into 32 bytes size buckets */ const int num_buckets = 32768; unsigned int *histogram = calloc(num_buckets, sizeof(int)); if (histogram != NULL) { int i; /* build the histogram */ for (i = 0; i < LARGEST_ID; i++) { item *iter = heads[i]; while (iter) { int ntotal = ITEM_ntotal(iter); int bucket = ntotal / 32; if ((ntotal % 32) != 0) bucket++; if (bucket < num_buckets) histogram[bucket]++; iter = iter->next; } } /* write the buffer */ for (i = 0; i < num_buckets; i++) { if (histogram[i] != 0) { char key[8]; int klen = 0; klen = snprintf(key, sizeof(key), "%d", i * 32); assert(klen < sizeof(key)); APPEND_STAT(key, "%u", histogram[i]); } } free(histogram); } add_stats(NULL, 0, NULL, 0, c); }
void item_stats_sizes_disable(ADD_STAT add_stats, void *c) { mutex_lock(&stats_sizes_lock); if (stats_sizes_hist != NULL) { free(stats_sizes_hist); stats_sizes_hist = NULL; } APPEND_STAT("sizes_status", "disabled", ""); mutex_unlock(&stats_sizes_lock); }
void do_item_stats_totals(ADD_STAT add_stats, void *c) { itemstats_t totals; memset(&totals, 0, sizeof(itemstats_t)); int i; for (i = 0; i < LARGEST_ID; i++) { totals.expired_unfetched += itemstats[i].expired_unfetched; totals.evicted_unfetched += itemstats[i].evicted_unfetched; totals.evicted += itemstats[i].evicted; totals.reclaimed += itemstats[i].reclaimed; } APPEND_STAT("expired_unfetched", "%llu", (unsigned long long)totals.expired_unfetched); APPEND_STAT("evicted_unfetched", "%llu", (unsigned long long)totals.evicted_unfetched); APPEND_STAT("evictions", "%llu", (unsigned long long)totals.evicted); APPEND_STAT("reclaimed", "%llu", (unsigned long long)totals.reclaimed); }
/* Locks are correct based on a technicality. Holds LRU lock while doing the * work, so items can't go invalid, and it's only looking at header sizes * which don't change. */ void item_stats_sizes(ADD_STAT add_stats, void *c) { mutex_lock(&stats_sizes_lock); if (stats_sizes_hist != NULL) { int i; for (i = 0; i < stats_sizes_buckets; i++) { if (stats_sizes_hist[i] != 0) { char key[8]; snprintf(key, sizeof(key), "%d", i * 32); APPEND_STAT(key, "%u", stats_sizes_hist[i]); } } } else { APPEND_STAT("sizes_status", "disabled", ""); } add_stats(NULL, 0, NULL, 0, c); mutex_unlock(&stats_sizes_lock); }
static void json_out_stat(TSRecordType rec_type ATS_UNUSED, void *edata, int registered ATS_UNUSED, const char *name, TSRecordDataType data_type, TSRecordData *datum) { stats_state *my_state = edata; switch(data_type) { case TS_RECORDDATATYPE_COUNTER: APPEND_STAT(name, "%" PRIu64, datum->rec_counter); break; case TS_RECORDDATATYPE_INT: APPEND_STAT(name, "%" PRIu64, datum->rec_int); break; case TS_RECORDDATATYPE_FLOAT: APPEND_STAT(name, "%f", datum->rec_float); break; case TS_RECORDDATATYPE_STRING: APPEND_STAT(name, "%s", datum->rec_string); break; default: TSDebug("istats", "unknown type for %s: %d", name, data_type); break; } }
void do_item_stats_totals(ADD_STAT add_stats, void *c) { syslog(LOG_INFO, "[%s:%s:%d]", __FILE__, __func__, __LINE__); itemstats_t totals; memset(&totals, 0, sizeof(itemstats_t)); int i; for (i = 0; i < LARGEST_ID; i++) { totals.expired_unfetched += itemstats[i].expired_unfetched; totals.evicted_unfetched += itemstats[i].evicted_unfetched; totals.evicted += itemstats[i].evicted; totals.reclaimed += itemstats[i].reclaimed; } APPEND_STAT("expired_unfetched", "%llu", (unsigned long long)totals.expired_unfetched); APPEND_STAT("evicted_unfetched", "%llu", (unsigned long long)totals.evicted_unfetched); APPEND_STAT("evictions", "%llu", (unsigned long long)totals.evicted); APPEND_STAT("reclaimed", "%llu", (unsigned long long)totals.reclaimed); }
bool get_stats(const char *stat_type, int nkey, ADD_STAT add_stats, void *c) { bool ret = true; if (add_stats != NULL) { if (!stat_type) { /* prepare general statistics for the engine */ STATS_LOCK(); APPEND_STAT("bytes", "%llu", (unsigned long long)stats_state.curr_bytes); APPEND_STAT("curr_items", "%llu", (unsigned long long)stats_state.curr_items); APPEND_STAT("total_items", "%llu", (unsigned long long)stats.total_items); STATS_UNLOCK(); if (settings.slab_automove > 0) { pthread_mutex_lock(&slabs_lock); APPEND_STAT("slab_global_page_pool", "%u", slabclass[SLAB_GLOBAL_PAGE_POOL].slabs); pthread_mutex_unlock(&slabs_lock); } item_stats_totals(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "items") == 0) { item_stats(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "slabs") == 0) { slabs_stats(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "sizes") == 0) { item_stats_sizes(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "sizes_enable") == 0) { item_stats_sizes_enable(add_stats, c); } else if (nz_strcmp(nkey, stat_type, "sizes_disable") == 0) { item_stats_sizes_disable(add_stats, c); } else { ret = false; } } else { ret = false; } return ret; }
void item_stats_sizes_enable(ADD_STAT add_stats, void *c) { mutex_lock(&stats_sizes_lock); if (!settings.use_cas) { APPEND_STAT("sizes_status", "error", ""); APPEND_STAT("sizes_error", "cas_support_disabled", ""); } else if (stats_sizes_hist == NULL) { item_stats_sizes_init(); if (stats_sizes_hist != NULL) { APPEND_STAT("sizes_status", "enabled", ""); } else { APPEND_STAT("sizes_status", "error", ""); APPEND_STAT("sizes_error", "no_memory", ""); } } else { APPEND_STAT("sizes_status", "enabled", ""); } mutex_unlock(&stats_sizes_lock); }
static void json_out_stat(TSRecordType rec_type ATS_UNUSED, void *edata, int registered ATS_UNUSED, const char *name, TSRecordDataType data_type, TSRecordData *datum) { stats_state *my_state = edata; unsigned long long int value = 0; switch(data_type) { case TS_RECORDDATATYPE_COUNTER: value = datum->rec_counter ; APPEND_STAT_NUMERIC(name, "%llu", value); break; case TS_RECORDDATATYPE_INT: value = datum->rec_int; if ( value > 9223372036854775807) value = 0 ; APPEND_STAT_NUMERIC(name, "%llu", value); break; case TS_RECORDDATATYPE_FLOAT: APPEND_STAT_NUMERIC(name, "%f", datum->rec_float); break; case TS_RECORDDATATYPE_STRING: APPEND_STAT(name, "%s", datum->rec_string); break; default: TSDebug("istats", "unknown type for %s: %d", name, data_type); break; } }
void item_stats_totals(ADD_STAT add_stats, void *c) { itemstats_t totals; memset(&totals, 0, sizeof(itemstats_t)); int n; for (n = 0; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) { int x; int i; for (x = 0; x < 4; x++) { i = n | lru_type_map[x]; pthread_mutex_lock(&lru_locks[i]); totals.expired_unfetched += itemstats[i].expired_unfetched; totals.evicted_unfetched += itemstats[i].evicted_unfetched; totals.evicted += itemstats[i].evicted; totals.reclaimed += itemstats[i].reclaimed; totals.crawler_reclaimed += itemstats[i].crawler_reclaimed; totals.crawler_items_checked += itemstats[i].crawler_items_checked; totals.lrutail_reflocked += itemstats[i].lrutail_reflocked; totals.moves_to_cold += itemstats[i].moves_to_cold; totals.moves_to_warm += itemstats[i].moves_to_warm; totals.moves_within_lru += itemstats[i].moves_within_lru; totals.direct_reclaims += itemstats[i].direct_reclaims; pthread_mutex_unlock(&lru_locks[i]); } } APPEND_STAT("expired_unfetched", "%llu", (unsigned long long)totals.expired_unfetched); APPEND_STAT("evicted_unfetched", "%llu", (unsigned long long)totals.evicted_unfetched); APPEND_STAT("evictions", "%llu", (unsigned long long)totals.evicted); APPEND_STAT("reclaimed", "%llu", (unsigned long long)totals.reclaimed); APPEND_STAT("crawler_reclaimed", "%llu", (unsigned long long)totals.crawler_reclaimed); APPEND_STAT("crawler_items_checked", "%llu", (unsigned long long)totals.crawler_items_checked); APPEND_STAT("lrutail_reflocked", "%llu", (unsigned long long)totals.lrutail_reflocked); if (settings.lru_maintainer_thread) { APPEND_STAT("moves_to_cold", "%llu", (unsigned long long)totals.moves_to_cold); APPEND_STAT("moves_to_warm", "%llu", (unsigned long long)totals.moves_to_warm); APPEND_STAT("moves_within_lru", "%llu", (unsigned long long)totals.moves_within_lru); APPEND_STAT("direct_reclaims", "%llu", (unsigned long long)totals.direct_reclaims); } }