summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2015-11-25 15:43:01 -0800
committerdormando <dormando@rydia.net>2016-06-08 10:17:55 -0700
commitbb55beb20c3c692a0e77e2ef368d5831318b33d0 (patch)
tree13b4956706a9b85572544bfa0b35cae21b8c5b8b
parent1af3c22bba5abfd38b49840c63237a9a59cbbc4e (diff)
downloadmemcached-bb55beb20c3c692a0e77e2ef368d5831318b33d0.tar.gz
manage logger watcher flags.
very temporary user control. allows to watch either fetchers or evictions, but not both, and always with timestamps.
-rw-r--r--items.c2
-rw-r--r--logger.c50
-rw-r--r--logger.h25
-rw-r--r--memcached.c19
-rw-r--r--thread.c2
5 files changed, 78 insertions, 20 deletions
diff --git a/items.c b/items.c
index 0586313..ef73815 100644
--- a/items.c
+++ b/items.c
@@ -854,7 +854,7 @@ static int lru_pull_tail(const int orig_id, const int cur_lru,
if ((search->it_flags & ITEM_FETCHED) == 0) {
itemstats[id].evicted_unfetched++;
}
- if (l->log_evictions)
+ if (l->f.log_evictions)
logger_log(l, LOGGER_EVICTION, search);
do_item_unlink_nolock(search, hv);
removed++;
diff --git a/logger.c b/logger.c
index 8888b1e..48ee48d 100644
--- a/logger.c
+++ b/logger.c
@@ -204,6 +204,41 @@ static void logger_chunk_release(logger_chunk *lc) {
}
/* Called with logger stack locked.
+ * Iterates over every watcher collecting enabled flags.
+ */
+static void logger_set_flags(void) {
+ logger *l = NULL;
+ int x = 0;
+ struct logger_eflags f;
+ memset(&f, 0, sizeof(struct logger_eflags));
+
+ /* Would love to | the fields together, but bitfields have intederminate
+ * sizing. Could use a union and some startup asserts to sniff out
+ * platforms where 8 bitfields take more than a uint64_t.. Some research
+ * is required though. For now an if/else tree will have to do.
+ */
+ for (x = 0; x < WATCHER_LIMIT; x++) {
+ logger_watcher *w = watchers[x];
+ if (w == NULL)
+ continue;
+
+ if (w->f.log_evictions)
+ f.log_evictions = 1;
+
+ if (w->f.log_fetchers)
+ f.log_fetchers = 1;
+
+ if (w->f.log_time)
+ f.log_time = 1;
+ }
+ for (l = logger_stack_head; l != NULL; l=l->next) {
+ /* lock logger, call function to manipulate it */
+ memcpy(&l->f, &f, sizeof(struct logger_eflags));
+ }
+ return;
+}
+
+/* Called with logger stack locked.
* Releases every chunk associated with a watcher and closes the connection.
* We can't presently send a connection back to the worker for further
* processing.
@@ -220,6 +255,7 @@ static void logger_close_watcher(logger_watcher *w) {
sidethread_conn_close(w->c);
watcher_count--;
free(w);
+ logger_set_flags();
}
/* Pick any number of "oldest" behind-watchers and kill them. */
@@ -502,11 +538,7 @@ logger *logger_create(void) {
return NULL;
}
- /* FIXME: hardcoded defaults for testing stage */
l->entry_map = default_entries;
- //l->log_fetchers = 1;
- l->log_evictions = 1;
- l->log_time = 1;
pthread_mutex_init(&l->mutex, NULL);
pthread_setspecific(logger_key, l);
@@ -518,8 +550,11 @@ logger *logger_create(void) {
#define SET_LOGGER_TIME() \
do { \
- if (l->log_time) { \
+ if (l->f.log_time) { \
gettimeofday(&e->tv, NULL); \
+ } else { \
+ e->tv.tv_sec = 0; \
+ e->tv.tv_usec = 0; \
} \
} while (0)
@@ -597,7 +632,7 @@ enum logger_ret_type logger_log(logger *l, const enum log_entry_type event, cons
* logger thread. Caller *must* event_del() the client before handing it over.
* Presently there's no way to hand the client back to the worker thread.
*/
-enum logger_add_watcher_ret logger_add_watcher(void *c, int sfd) {
+enum logger_add_watcher_ret logger_add_watcher(void *c, const int sfd, const struct logger_eflags f) {
int x;
logger_watcher *w = NULL;
pthread_mutex_lock(&logger_stack_lock);
@@ -621,6 +656,7 @@ enum logger_add_watcher_ret logger_add_watcher(void *c, int sfd) {
w->t = LOGGER_WATCHER_CLIENT;
}
w->id = x;
+ memcpy(&w->f, &f, sizeof(struct logger_eflags));
/* Attach to an existing log chunk if there is one */
if (logger_thread_last_lc && !logger_thread_last_lc->filled) {
logger_chunk *lc = logger_thread_last_lc;
@@ -631,6 +667,8 @@ enum logger_add_watcher_ret logger_add_watcher(void *c, int sfd) {
}
watchers[x] = w;
watcher_count++;
+ /* Update what flags the global logs will watch */
+ logger_set_flags();
pthread_mutex_unlock(&logger_stack_lock);
return LOGGER_ADD_WATCHER_OK;
diff --git a/logger.h b/logger.h
index 3756f0f..c4279ac 100644
--- a/logger.h
+++ b/logger.h
@@ -48,15 +48,7 @@ typedef struct _logentry {
} data[];
} logentry;
-typedef struct _logger {
- struct _logger *prev;
- struct _logger *next;
- pthread_mutex_t mutex; /* guard for this + *buf */
- uint64_t logged; /* entries written to the buffer */
- uint64_t dropped; /* entries dropped */
- uint64_t blocked; /* times blocked instead of dropped */
- uint16_t fetcher_ratio; /* log one out of every N fetches */
- uint16_t mutation_ratio; /* log one out of every N mutations */
+struct logger_eflags {
unsigned int log_sysevents :1; /* threads start/stop/working */
unsigned int log_fetchers :1; /* get/gets/etc */
unsigned int log_mutations :1; /* set/append/incr/etc */
@@ -66,6 +58,18 @@ typedef struct _logger {
unsigned int log_evictions :1; /* log details of evicted items */
unsigned int log_strict :1; /* block instead of drop */
unsigned int log_time :1; /* log the time the entry is created */
+};
+
+typedef struct _logger {
+ struct _logger *prev;
+ struct _logger *next;
+ pthread_mutex_t mutex; /* guard for this + *buf */
+ uint64_t logged; /* entries written to the buffer */
+ uint64_t dropped; /* entries dropped */
+ uint64_t blocked; /* times blocked instead of dropped */
+ uint16_t fetcher_ratio; /* log one out of every N fetches */
+ uint16_t mutation_ratio; /* log one out of every N mutations */
+ struct logger_eflags f; /* flags this logger should log */
bipbuf_t *buf;
const entry_details *entry_map;
} logger;
@@ -92,6 +96,7 @@ typedef struct {
int flushed; /* backlog data flushed so far from active chunk */
int id; /* id number for watcher list */
enum logger_watcher_type t; /* stderr, client, syslog, etc */
+ struct logger_eflags f; /* flags we are interested in */
} logger_watcher;
extern pthread_key_t logger_key;
@@ -109,6 +114,6 @@ enum logger_add_watcher_ret {
LOGGER_ADD_WATCHER_FAILED
};
-enum logger_add_watcher_ret logger_add_watcher(void *c, int sfd);
+enum logger_add_watcher_ret logger_add_watcher(void *c, const int sfd, const struct logger_eflags);
#endif
diff --git a/memcached.c b/memcached.c
index 0125075..d4906ca 100644
--- a/memcached.c
+++ b/memcached.c
@@ -3445,7 +3445,7 @@ static void process_command(conn *c, char *command) {
MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes);
- if (c->thread->l->log_fetchers)
+ if (c->thread->l->f.log_fetchers)
logger_log(c->thread->l, LOGGER_ASCII_CMD, NULL, c->sfd, command);
/*
@@ -3677,8 +3677,23 @@ static void process_command(conn *c, char *command) {
out_string(c, "ERROR");
}
} else if (ntokens > 1 && strcmp(tokens[COMMAND_TOKEN].value, "watch") == 0) {
+ struct logger_eflags f;
+ memset(&f, 0, sizeof(struct logger_eflags));
/* TODO: pass to function for full argument processing. */
- switch(logger_add_watcher(c, c->sfd)) {
+ /* This is very temporary... need to decide on a real flag parser. */
+ if (ntokens == 3) {
+ if ((strcmp(tokens[COMMAND_TOKEN + 1].value, "fetchers") == 0)) {
+ f.log_fetchers = 1;
+ } else if ((strcmp(tokens[COMMAND_TOKEN + 1].value, "evictions") == 0)) {
+ f.log_evictions = 1;
+ } else {
+ out_string(c, "ERROR");
+ }
+ } else {
+ f.log_fetchers = 1;
+ }
+ f.log_time = 1; /* not optional yet */
+ switch(logger_add_watcher(c, c->sfd, f)) {
case LOGGER_ADD_WATCHER_TOO_MANY:
out_string(c, "WATCHER_TOO_MANY log watcher limit reached");
break;
diff --git a/thread.c b/thread.c
index 2113dcc..df8e33b 100644
--- a/thread.c
+++ b/thread.c
@@ -488,7 +488,7 @@ void redispatch_conn(conn *c) {
}
LIBEVENT_THREAD *thread = c->thread;
item->sfd = sfd;
- /* pass in the state somehow?
+ /* pass in the state somehow?
item->init_state = conn_closing; */
item->event_flags = c->event_flags;
item->conn = c;