diff options
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/memcached.c | 119 | ||||
-rw-r--r-- | daemon/memcached.h | 10 | ||||
-rw-r--r-- | daemon/topkeys.c | 180 | ||||
-rw-r--r-- | daemon/topkeys.h | 56 |
4 files changed, 42 insertions, 323 deletions
diff --git a/daemon/memcached.c b/daemon/memcached.c index 226fa1c..cd7ec33 100644 --- a/daemon/memcached.c +++ b/daemon/memcached.c @@ -51,15 +51,12 @@ static inline void item_set_cas(const void *cookie, item *it, uint64_t cas) { SLAB_GUTS(conn, thread_stats, slab_op, thread_op) \ THREAD_GUTS(conn, thread_stats, slab_op, thread_op) -#define STATS_INCR1(GUTS, conn, slab_op, thread_op, key, nkey) { \ - struct independent_stats *independent_stats = get_independent_stats(conn); \ - struct thread_stats *thread_stats = \ - &independent_stats->thread_stats[conn->thread->index]; \ - topkeys_t *topkeys = independent_stats->topkeys; \ +#define STATS_INCR1(GUTS, conn, slab_op, thread_op, key, nkey) \ +{ \ + struct thread_stats *thread_stats = get_thread_stats(conn); \ pthread_mutex_lock(&thread_stats->mutex); \ GUTS(conn, thread_stats, slab_op, thread_op); \ pthread_mutex_unlock(&thread_stats->mutex); \ - TK(topkeys, slab_op, key, nkey, current_time); \ } #define STATS_INCR(conn, op, key, nkey) \ @@ -122,7 +119,6 @@ volatile rel_time_t current_time; */ static SOCKET new_socket(struct addrinfo *ai); static int try_read_command(conn *c); -static inline struct independent_stats *get_independent_stats(conn *c); static inline struct thread_stats *get_thread_stats(conn *c); static void register_callback(ENGINE_HANDLE *eh, ENGINE_EVENT_TYPE type, @@ -165,7 +161,7 @@ static time_t process_started; /* when the process was started */ /** file scope variables **/ static conn *listen_conn = NULL; static struct event_base *main_base; -static struct independent_stats *default_independent_stats; +static struct thread_stats *default_thread_stats; static struct engine_event_handler *engine_event_handlers[MAX_ENGINE_EVENT_TYPE + 1]; @@ -238,7 +234,7 @@ static void stats_reset(const void *cookie) { stats.total_conns = 0; stats_prefix_clear(); STATS_UNLOCK(); - threadlocal_stats_reset(get_independent_stats(conn)->thread_stats); + threadlocal_stats_reset(get_thread_stats(conn)); settings.engine.v1->reset_stats(settings.engine.v0, cookie); } @@ -266,7 +262,6 @@ static void settings_init(void) { settings.backlog = 1024; settings.binding_protocol = negotiating_prot; settings.item_size_max = 1024 * 1024; /* The famous 1MB upper limit. */ - settings.topkeys = 0; settings.require_sasl = false; settings.extensions.logger = get_stderr_logger(); } @@ -1950,14 +1945,6 @@ static void process_bin_stat(conn *c) { } } else if (strncmp(subcommand, "aggregate", 9) == 0) { server_stats(&append_stats, c, true); - } else if (strncmp(subcommand, "topkeys", 7) == 0) { - topkeys_t *tk = get_independent_stats(c)->topkeys; - if (tk != NULL) { - topkeys_stats(tk, c, current_time, append_stats); - } else { - write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, 0); - return; - } } else { ret = settings.engine.v1->get_stats(settings.engine.v0, c, subcommand, nkey, @@ -3676,10 +3663,7 @@ inline static void process_stats_detail(conn *c, const char *command) { } static void aggregate_callback(void *in, void *out) { - struct thread_stats *out_thread_stats = out; - struct independent_stats *in_independent_stats = in; - threadlocal_stats_aggregate(in_independent_stats->thread_stats, - out_thread_stats); + threadlocal_stats_aggregate(in, out); } /* return server specific stats only */ @@ -3696,7 +3680,7 @@ static void server_stats(ADD_STAT add_stats, conn *c, bool aggregate) { aggregate_callback, &thread_stats); } else { - threadlocal_stats_aggregate(get_independent_stats(c)->thread_stats, + threadlocal_stats_aggregate(get_thread_stats(c), &thread_stats); } @@ -3859,7 +3843,6 @@ static void process_stat_settings(ADD_STAT add_stats, void *c) { #endif APPEND_STAT("auth_required_sasl", "%s", settings.require_sasl ? "yes" : "no"); APPEND_STAT("item_size_max", "%d", settings.item_size_max); - APPEND_STAT("topkeys", "%d", settings.topkeys); for (EXTENSION_DAEMON_DESCRIPTOR *ptr = settings.extensions.daemons; ptr != NULL; @@ -3941,14 +3924,6 @@ static char *process_stat(conn *c, token_t *tokens, const size_t ntokens) { return NULL; } else if (strcmp(subcommand, "aggregate") == 0) { server_stats(&append_stats, c, true); - } else if (strcmp(subcommand, "topkeys") == 0) { - topkeys_t *tk = get_independent_stats(c)->topkeys; - if (tk != NULL) { - topkeys_stats(tk, c, current_time, append_stats); - } else { - out_string(c, "ERROR"); - return NULL; - } } else { /* getting here means that the subcommand is either engine specific or is invalid. query the engine and see. */ @@ -6154,7 +6129,6 @@ static void usage(void) { printf("-e config Pass config as configuration options to the storage engine\n"); printf("\nEnvironment variables:\n" "MEMCACHED_PORT_FILENAME File to write port information to\n" - "MEMCACHED_TOP_KEYS Number of top keys to keep track of\n" "MEMCACHED_REQS_TAP_EVENT Similar to -R but for tap_ship_log\n"); } @@ -6373,48 +6347,46 @@ static ENGINE_ERROR_CODE release_cookie(const void *cookie) { return ENGINE_SUCCESS; } -static int num_independent_stats(void) { +static inline int num_thread_stats(void) { return settings.num_threads + 1; } -static void *new_independent_stats(void) { - int ii; - int nrecords = num_independent_stats(); - struct independent_stats *independent_stats = calloc(sizeof(independent_stats) + sizeof(struct thread_stats) * nrecords, 1); - if (settings.topkeys > 0) - independent_stats->topkeys = topkeys_init(settings.topkeys); - for (ii = 0; ii < nrecords; ii++) - pthread_mutex_init(&independent_stats->thread_stats[ii].mutex, NULL); - return independent_stats; +static void *new_thread_stats(void) { + int nrecords = num_thread_stats(); + + struct thread_stats *ts = calloc(nrecords, sizeof(*ts)); + if (ts != NULL) { + for (int ii = 0; ii < nrecords; ii++) { + pthread_mutex_init(&ts[ii].mutex, NULL); + } + } + return ts; } -static void release_independent_stats(void *stats) { - int ii; - int nrecords = num_independent_stats(); - struct independent_stats *independent_stats = stats; - if (independent_stats->topkeys) - topkeys_free(independent_stats->topkeys); - for (ii = 0; ii < nrecords; ii++) - pthread_mutex_destroy(&independent_stats->thread_stats[ii].mutex); - free(independent_stats); +static void release_thread_stats(void *stats) { + struct thread_stats *ts = stats; + if (ts != NULL) { + int nrecords = num_thread_stats(); + for (int ii = 0; ii < nrecords; ii++) { + pthread_mutex_destroy(&ts[ii].mutex); + } + free(ts); + } } -static inline struct independent_stats *get_independent_stats(conn *c) { - struct independent_stats *independent_stats; +static inline struct thread_stats *get_thread_stats(conn *c) { + struct thread_stats *ts; if (settings.engine.v1->get_stats_struct != NULL) { - independent_stats = settings.engine.v1->get_stats_struct(settings.engine.v0, (const void *)c); - if (independent_stats == NULL) - independent_stats = default_independent_stats; + ts = settings.engine.v1->get_stats_struct(settings.engine.v0, c); + if (ts == NULL) { + ts = default_thread_stats; + } } else { - independent_stats = default_independent_stats; + ts = default_thread_stats; } - return independent_stats; -} -static inline struct thread_stats *get_thread_stats(conn *c) { - struct independent_stats *independent_stats = get_independent_stats(c); - assert(c->thread->index < num_independent_stats()); - return &independent_stats->thread_stats[c->thread->index]; + assert(c->thread->index < num_thread_stats()); + return &ts[c->thread->index]; } static void register_callback(ENGINE_HANDLE *eh, @@ -6436,8 +6408,9 @@ static rel_time_t get_current_time(void) } static void count_eviction(const void *cookie, const void *key, const int nkey) { - topkeys_t *tk = get_independent_stats((conn*)cookie)->topkeys; - TK(tk, evictions, key, nkey, get_current_time()); + (void)cookie; + (void)key; + (void)nkey; } /** @@ -6814,8 +6787,8 @@ static SERVER_HANDLE_V1 *get_server_api(void) }; static SERVER_STAT_API server_stat_api = { - .new_stats = new_independent_stats, - .release_stats = release_independent_stats, + .new_stats = new_thread_stats, + .release_stats = release_thread_stats, .evicting = count_eviction }; @@ -7261,14 +7234,6 @@ int main (int argc, char **argv) { exit(EXIT_FAILURE); } - char *topkeys_env = getenv("MEMCACHED_TOP_KEYS"); - if (topkeys_env != NULL) { - settings.topkeys = atoi(topkeys_env); - if (settings.topkeys < 0) { - settings.topkeys = 0; - } - } - if (settings.require_sasl) { if (!protocol_specified) { settings.binding_protocol = binary_prot; @@ -7469,7 +7434,7 @@ int main (int argc, char **argv) { exit(EXIT_FAILURE); } - default_independent_stats = new_independent_stats(); + default_thread_stats = new_thread_stats(); #ifndef __WIN32__ /* diff --git a/daemon/memcached.h b/daemon/memcached.h index 9b1e184..625b841 100644 --- a/daemon/memcached.h +++ b/daemon/memcached.h @@ -14,7 +14,6 @@ #include <memcached/extension.h> #include "cache.h" -#include "topkeys.h" #include "sasl_defs.h" @@ -143,15 +142,6 @@ struct thread_stats { struct slab_stats slab_stats[MAX_NUMBER_OF_SLAB_CLASSES]; }; - -/** - * The stats structure the engine keeps track of - */ -struct independent_stats { - topkeys_t *topkeys; - struct thread_stats thread_stats[]; -}; - /** * Global stats. */ diff --git a/daemon/topkeys.c b/daemon/topkeys.c deleted file mode 100644 index 3dc3e1d..0000000 --- a/daemon/topkeys.c +++ /dev/null @@ -1,180 +0,0 @@ -#include <sys/types.h> -#include <stdlib.h> -#include <assert.h> -#include <inttypes.h> -#include <string.h> -#include <pthread.h> -#include <memcached/genhash.h> -#include "topkeys.h" - -static topkey_item_t *topkey_item_init(const void *key, int nkey, rel_time_t ctime) { - topkey_item_t *item = calloc(sizeof(topkey_item_t) + nkey, 1); - assert(item); - assert(key); - assert(nkey > 0); - item->nkey = nkey; - item->ctime = ctime; - item->atime = ctime; - /* Copy the key into the part trailing the struct */ - memcpy(item->key, key, nkey); - return item; -} - -static inline size_t topkey_item_size(const topkey_item_t *item) { - return sizeof(topkey_item_t) + item->nkey; -} - -static inline topkey_item_t* topkeys_tail(topkeys_t *tk) { - return (topkey_item_t*)(tk->list.prev); -} - -static int my_hash_eq(const void *k1, size_t nkey1, - const void *k2, size_t nkey2) { - return nkey1 == nkey2 && memcmp(k1, k2, nkey1) == 0; -} - -topkeys_t *topkeys_init(int max_keys) { - topkeys_t *tk = calloc(sizeof(topkeys_t), 1); - if (tk == NULL) { - return NULL; - } - - pthread_mutex_init(&tk->mutex, NULL); - tk->max_keys = max_keys; - tk->list.next = &tk->list; - tk->list.prev = &tk->list; - - static struct hash_ops my_hash_ops = { - .hashfunc = genhash_string_hash, - .hasheq = my_hash_eq, - .dupKey = NULL, - .dupValue = NULL, - .freeKey = NULL, - .freeValue = NULL, - }; - - tk->hash = genhash_init(max_keys, my_hash_ops); - if (tk->hash == NULL) { - return NULL; - } - return tk; -} - -void topkeys_free(topkeys_t *tk) { - pthread_mutex_destroy(&tk->mutex); - genhash_free(tk->hash); - dlist_t *p = tk->list.next; - while (p != &tk->list) { - dlist_t *tmp = p->next; - free(p); - p = tmp; - } -} - -static inline void dlist_remove(dlist_t *list) { - assert(list->prev->next == list); - assert(list->next->prev == list); - list->prev->next = list->next; - list->next->prev = list->prev; -} - -static inline void dlist_insert_after(dlist_t *list, dlist_t *new) { - new->next = list->next; - new->prev = list; - list->next->prev = new; - list->next = new; -} - -static inline void dlist_iter(dlist_t *list, - void (*iterfunc)(dlist_t *item, void *arg), - void *arg) -{ - dlist_t *p = list; - while ((p = p->next) != list) { - iterfunc(p, arg); - } -} - -static inline void topkeys_item_delete(topkeys_t *tk, topkey_item_t *item) { - genhash_delete(tk->hash, item->key, item->nkey); - dlist_remove(&item->list); - --tk->nkeys; - free(item); -} - -topkey_item_t *topkeys_item_get_or_create(topkeys_t *tk, const void *key, size_t nkey, const rel_time_t ctime) { - topkey_item_t *item = genhash_find(tk->hash, key, nkey); - if (item == NULL) { - item = topkey_item_init(key, nkey, ctime); - if (item != NULL) { - if (++tk->nkeys > tk->max_keys) { - topkeys_item_delete(tk, topkeys_tail(tk)); - } - genhash_update(tk->hash, item->key, item->nkey, - item, topkey_item_size(item)); - } else { - return NULL; - } - } else { - dlist_remove(&item->list); - } - dlist_insert_after(&tk->list, &item->list); - return item; -} - -static inline void append_stat(const void *cookie, - const char *name, - size_t namelen, - const char *key, - size_t nkey, - int value, - ADD_STAT add_stats) { - char key_str[128]; - char val_str[128]; - int klen, vlen; - - klen = sizeof(key_str) - namelen - 2; - if (nkey < klen) { - klen = nkey; - } - memcpy(key_str, key, klen); - key_str[klen] = '.'; - memcpy(&key_str[klen+1], name, namelen + 1); - klen += namelen + 1; - vlen = snprintf(val_str, sizeof(val_str) - 1, "%d", value); - add_stats(key_str, klen, val_str, vlen, cookie); -} - -struct tk_context { - const void *cookie; - ADD_STAT add_stat; - rel_time_t current_time; -}; - -#define TK_FMT(name) #name "=%d," -#define TK_ARGS(name) item->name, - -static void tk_iterfunc(dlist_t *list, void *arg) { - struct tk_context *c = arg; - topkey_item_t *item = (topkey_item_t*)list; - char val_str[TK_MAX_VAL_LEN]; - /* This line is magical. The missing comma before item->ctime is because the TK_ARGS macro ends with a comma. */ - int vlen = snprintf(val_str, sizeof(val_str) - 1, TK_OPS(TK_FMT)"ctime=%"PRIu32",atime=%"PRIu32, TK_OPS(TK_ARGS) - c->current_time - item->ctime, c->current_time - item->atime); - c->add_stat(item->key, item->nkey, val_str, vlen, c->cookie); -} - -ENGINE_ERROR_CODE topkeys_stats(topkeys_t *tk, - const void *cookie, - const rel_time_t current_time, - ADD_STAT add_stat) { - struct tk_context context; - context.cookie = cookie; - context.add_stat = add_stat; - context.current_time = current_time; - assert(tk); - pthread_mutex_lock(&tk->mutex); - dlist_iter(&tk->list, tk_iterfunc, &context); - pthread_mutex_unlock(&tk->mutex); - return ENGINE_SUCCESS; -} diff --git a/daemon/topkeys.h b/daemon/topkeys.h deleted file mode 100644 index 35102ca..0000000 --- a/daemon/topkeys.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef TOPKEYS_H -#define TOPKEYS_H 1 - -#include <memcached/engine.h> -#include <memcached/genhash.h> - -/* A list of operations for which we have int stats */ -#define TK_OPS(C) C(get_hits) C(get_misses) C(cmd_set) C(incr_hits) \ - C(incr_misses) C(decr_hits) C(decr_misses) \ - C(delete_hits) C(delete_misses) C(evictions) \ - C(cas_hits) C(cas_badval) C(cas_misses) - -#define TK_MAX_VAL_LEN 250 - -/* Update the correct stat for a given operation */ -#define TK(tk, op, key, nkey, ctime) { \ - if (tk) { \ - assert(key); \ - assert(nkey > 0); \ - pthread_mutex_lock(&tk->mutex); \ - topkey_item_t *tmp = topkeys_item_get_or_create( \ - (tk), (key), (nkey), (ctime)); \ - tmp->op++; \ - pthread_mutex_unlock(&tk->mutex); \ - } \ -} - -typedef struct dlist { - struct dlist *next; - struct dlist *prev; -} dlist_t; - -typedef struct topkey_item { - dlist_t list; /* Must be at the beginning because we downcast! */ - int nkey; - rel_time_t ctime, atime; /* Time this item was created/last accessed */ -#define TK_CUR(name) int name; - TK_OPS(TK_CUR) -#undef TK_CUR - char key[]; /* A variable length array in the struct itself */ -} topkey_item_t; - -typedef struct topkeys { - dlist_t list; - pthread_mutex_t mutex; - genhash_t *hash; - int nkeys; - int max_keys; -} topkeys_t; - -topkeys_t *topkeys_init(int max_keys); -void topkeys_free(topkeys_t *topkeys); -topkey_item_t *topkeys_item_get_or_create(topkeys_t *tk, const void *key, size_t nkey, const rel_time_t ctime); -ENGINE_ERROR_CODE topkeys_stats(topkeys_t *tk, const void *cookie, const rel_time_t current_time, ADD_STAT add_stat); - -#endif |