Permalink
Browse files

Add DTrace probes for Solaris/etc.

  • Loading branch information...
1 parent 5da8dba commit 6895721413f37518140681872dd5d102253f8e42 Trond Norbye committed with dormando Jul 23, 2008
Showing with 715 additions and 51 deletions.
  1. +16 −2 Makefile.am
  2. +16 −6 assoc.c
  3. +21 −1 configure.ac
  4. +6 −0 items.c
  5. +59 −17 memcached.c
  6. +5 −2 memcached.h
  7. +274 −0 memcached_dtrace.d
  8. +276 −0 memcached_dtrace.h
  9. +37 −21 slabs.c
  10. +5 −2 thread.c
View
@@ -4,8 +4,22 @@ pkginclude_HEADERS = protocol_binary.h
memcached_SOURCES = memcached.c slabs.c slabs.h items.c items.h assoc.c assoc.h memcached.h thread.c stats.c stats.h
memcached_debug_SOURCES = $(memcached_SOURCES)
memcached_CPPFLAGS = -DNDEBUG
-memcached_LDADD = @LIBOBJS@
-memcached_debug_LDADD = $(memcached_LDADD)
+memcached_LDADD = @DTRACE_OBJ@ @DAEMON_OBJ@
+memcached_debug_LDADD = @DTRACE_DEBUG_OBJ@ @DAEMON_OBJ@
+memcached_DEPENDENCIES = @DTRACE_OBJ@ @DAEMON_OBJ@
+memcached_debug_DEPENDENCIES = @DTRACE_DEBUG_OBJ@ @DAEMON_OBJ@
+
+memcached_dtrace.h:
+ ${DTRACE} -h -s memcached_dtrace.d
+ sed -e s,_DTRACE_VERSION,ENABLE_DTRACE,g memcached_dtrace.h | \
+ tr '\t' ' ' | grep -v unistd.h > memcached_dtrace.tmp
+ mv memcached_dtrace.tmp memcached_dtrace.h
+
+memcached_dtrace.o: $(memcached_OBJECTS)
+ $(DTRACE) $(DTRACEFLAGS) -G -o memcached_dtrace.o -s ${srcdir}/memcached_dtrace.d $(memcached_OBJECTS)
+
+memcached_debug_dtrace.o: $(memcached_debug_OBJECTS)
+ $(DTRACE) $(DTRACEFLAGS) -G -o memcached_debug_dtrace.o -s ${srcdir}/memcached_dtrace.d $(memcached_debug_OBJECTS)
SUBDIRS = doc
DIST_DIRS = scripts
View
22 assoc.c
@@ -496,14 +496,18 @@ item *assoc_find(const char *key, const size_t nkey) {
it = primary_hashtable[hv & hashmask(hashpower)];
}
+ item *ret = NULL;
+ int depth = 0;
while (it) {
- if ((nkey == it->nkey) &&
- (memcmp(key, ITEM_key(it), nkey) == 0)) {
- return it;
+ if ((nkey == it->nkey) && (memcmp(key, ITEM_key(it), nkey) == 0)) {
+ ret = it;
+ break;
}
it = it->h_next;
+ ++depth;
}
- return 0;
+ MEMCACHED_ASSOC_FIND(key, depth);
+ return ret;
}
/* returns the address of the item pointer before the key. if *item == 0,
@@ -595,17 +599,23 @@ int assoc_insert(item *it) {
assoc_expand();
}
+ MEMCACHED_ASSOC_INSERT(ITEM_key(it), hash_items);
return 1;
}
void assoc_delete(const char *key, const size_t nkey) {
item **before = _hashitem_before(key, nkey);
if (*before) {
- item *nxt = (*before)->h_next;
+ item *nxt;
+ hash_items--;
+ /* The DTrace probe cannot be triggered as the last instruction
+ * due to possible tail-optimization by the compiler
+ */
+ MEMCACHED_ASSOC_DELETE(key, hash_items);
+ nxt = (*before)->h_next;
(*before)->h_next = 0; /* probably pointless, but whatever. */
*before = nxt;
- hash_items--;
return;
}
/* Note: we never actually get here. the callers don't delete things
View
@@ -9,6 +9,25 @@ AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_INSTALL
+AC_ARG_ENABLE(dtrace,
+ [AS_HELP_STRING([--enable-dtrace],[Enable dtrace probes])])
+if test "x$enable_dtrace" == "xyes"; then
+ AC_PATH_PROG([DTRACE], [dtrace], "no", [/usr/sbin:$PATH])
+ if test "x$DTRACE" != "xno"; then
+ AC_DEFINE([ENABLE_DTRACE],1,[Set to nonzero if you want to include DTRACE])
+ DTRACE_OBJ=memcached_dtrace.o
+ DTRACE_DEBUG_OBJ=memcached_debug_dtrace.o
+ else
+ AC_MSG_ERROR([Need dtrace binary and OS support.])
+ fi
+else
+ AC_DEFINE([ENABLE_DTRACE],0,[Set to nonzero if you want to include DTRACE])
+fi
+AC_SUBST(DTRACE)
+AC_SUBST(DTRACE_OBJ)
+AC_SUBST(DTRACE_DEBUG_OBJ)
+AC_SUBST(DTRACEFLAGS)
+
AC_ARG_ENABLE(64bit,
[AS_HELP_STRING([--enable-64bit],[build 64bit verison])])
if test "x$enable_64bit" == "xyes"
@@ -113,7 +132,8 @@ AC_SEARCH_LIBS(socket, socket)
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(mallinfo, malloc)
-AC_CHECK_FUNC(daemon,AC_DEFINE([HAVE_DAEMON],,[Define this if you have daemon()]),[AC_LIBOBJ(daemon)])
+AC_CHECK_FUNC(daemon,AC_DEFINE([HAVE_DAEMON],,[Define this if you have daemon()]),[DAEMON_OBJ=daemon.o])
+AC_SUBST(DAEMON_OBJ)
AC_HEADER_STDBOOL
AC_C_CONST
View
@@ -228,6 +228,7 @@ static void item_unlink_q(item *it) {
}
int do_item_link(item *it) {
+ MEMCACHED_ITEM_LINK(ITEM_key(it), it->nbytes);
assert((it->it_flags & (ITEM_LINKED|ITEM_SLABBED)) == 0);
assert(it->nbytes < (1024 * 1024)); /* 1MB max size */
it->it_flags |= ITEM_LINKED;
@@ -249,6 +250,7 @@ int do_item_link(item *it) {
}
void do_item_unlink(item *it) {
+ MEMCACHED_ITEM_UNLINK(ITEM_key(it), it->nbytes);
if ((it->it_flags & ITEM_LINKED) != 0) {
it->it_flags &= ~ITEM_LINKED;
STATS_LOCK();
@@ -262,6 +264,7 @@ void do_item_unlink(item *it) {
}
void do_item_remove(item *it) {
+ MEMCACHED_ITEM_REMOVE(ITEM_key(it), it->nbytes);
assert((it->it_flags & ITEM_SLABBED) == 0);
if (it->refcount != 0) {
it->refcount--;
@@ -274,6 +277,7 @@ void do_item_remove(item *it) {
}
void do_item_update(item *it) {
+ MEMCACHED_ITEM_UPDATE(ITEM_key(it), it->nbytes);
if (it->time < current_time - ITEM_UPDATE_INTERVAL) {
assert((it->it_flags & ITEM_SLABBED) == 0);
@@ -286,6 +290,8 @@ void do_item_update(item *it) {
}
int do_item_replace(item *it, item *new_it) {
+ MEMCACHED_ITEM_REPLACE(ITEM_key(it), it->nbytes,
+ ITEM_key(new_it), new_it->nbytes);
assert((it->it_flags & ITEM_SLABBED) == 0);
do_item_unlink(it);
View
@@ -317,6 +317,8 @@ conn *conn_new(const int sfd, enum conn_states init_state,
fprintf(stderr, "calloc()\n");
return NULL;
}
+ MEMCACHED_CONN_CREATE(c);
+
c->rbuf = c->wbuf = 0;
c->ilist = 0;
c->suffixlist = 0;
@@ -341,13 +343,7 @@ conn *conn_new(const int sfd, enum conn_states init_state,
if (c->rbuf == 0 || c->wbuf == 0 || c->ilist == 0 || c->iov == 0 ||
c->msglist == 0 || c->suffixlist == 0) {
- if (c->rbuf != 0) free(c->rbuf);
- if (c->wbuf != 0) free(c->wbuf);
- if (c->ilist != 0) free(c->ilist);
- if (c->suffixlist != 0) free(c->suffixlist);
- if (c->iov != 0) free(c->iov);
- if (c->msglist != 0) free(c->msglist);
- free(c);
+ conn_free(c);
fprintf(stderr, "malloc()\n");
return NULL;
}
@@ -424,6 +420,8 @@ conn *conn_new(const int sfd, enum conn_states init_state,
stats.total_conns++;
STATS_UNLOCK();
+ MEMCACHED_CONN_ALLOCATE(c->sfd);
+
return c;
}
@@ -460,6 +458,7 @@ static void conn_cleanup(conn *c) {
*/
void conn_free(conn *c) {
if (c) {
+ MEMCACHED_CONN_DESTROY(c);
if (c->hdrbuf)
free(c->hdrbuf);
if (c->msglist)
@@ -487,6 +486,7 @@ static void conn_close(conn *c) {
if (settings.verbose > 1)
fprintf(stderr, "<%d connection closed.\n", c->sfd);
+ MEMCACHED_CONN_RELEASE(c->sfd);
close(c->sfd);
accept_new_conns(true);
conn_cleanup(c);
@@ -595,6 +595,10 @@ static void conn_set_state(conn *c, enum conn_states state) {
}
c->state = state;
+
+ if (state == conn_write) {
+ MEMCACHED_PROCESS_COMMAND_END(c->sfd, c->wbuf, c->wbytes);
+ }
}
}
@@ -835,9 +839,32 @@ static void complete_nread_ascii(conn *c) {
out_string(c, "CLIENT_ERROR bad data chunk");
} else {
ret = store_item(it, comm, c);
- if (ret == 1)
+ if (ret == 1) {
out_string(c, "STORED");
- else if(ret == 2)
+#ifdef HAVE_DTRACE
+ switch (comm) {
+ case NREAD_ADD:
+ MEMCACHED_COMMAND_ADD(c->sfd, ITEM_key(it), it->nbytes);
+ break;
+ case NREAD_REPLACE:
+ MEMCACHED_COMMAND_REPLACE(c->sfd, ITEM_key(it), it->nbytes);
+ break;
+ case NREAD_APPEND:
+ MEMCACHED_COMMAND_APPEND(c->sfd, ITEM_key(it), it->nbytes);
+ break;
+ case NREAD_PREPEND:
+ MEMCACHED_COMMAND_PREPEND(c->sfd, ITEM_key(it), it->nbytes);
+ break;
+ case NREAD_SET:
+ MEMCACHED_COMMAND_SET(c->sfd, ITEM_key(it), it->nbytes);
+ break;
+ case NREAD_CAS:
+ MEMCACHED_COMMAND_CAS(c->sfd, ITEM_key(it), it->nbytes,
+ it->cas_id);
+ break;
+ }
+#endif
+ } else if(ret == 2)
out_string(c, "EXISTS");
else if(ret == 3)
out_string(c, "NOT_FOUND");
@@ -1024,7 +1051,7 @@ static void complete_incr_bin(conn *c) {
/* Weird magic in add_delta forces me to pad here */
char tmpbuf[INCR_MAX_STORAGE_LEN];
uint64_t l = 0;
- add_delta(it, c->cmd == PROTOCOL_BINARY_CMD_INCREMENT,
+ add_delta(c, it, c->cmd == PROTOCOL_BINARY_CMD_INCREMENT,
req->message.body.delta, tmpbuf);
rsp->message.body.value = swap64(strtoull(tmpbuf, NULL, 10));
c->cas = it->cas_id;
@@ -2153,6 +2180,8 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
if (return_cas)
{
+ MEMCACHED_COMMAND_GETS(c->sfd, ITEM_key(it), it->nbytes,
+ it->cas_id);
/* Goofy mid-flight realloc. */
if (i >= c->suffixsize) {
char **new_suffix_list = realloc(c->suffixlist,
@@ -2186,6 +2215,8 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
}
else
{
+ MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nbytes);
+
if (add_iov(c, "VALUE ", 6) != 0 ||
add_iov(c, ITEM_key(it), it->nkey) != 0 ||
add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes) != 0)
@@ -2206,6 +2237,11 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
} else {
stats_get_misses++;
+ if (return_cas) {
+ MEMCACHED_COMMAND_GETS(c->sfd, key, -1, 0);
+ } else {
+ MEMCACHED_COMMAND_GET(c->sfd, key, -1);
+ }
}
key_token++;
@@ -2373,21 +2409,22 @@ static void process_arithmetic_command(conn *c, token_t *tokens, const size_t nt
return;
}
- out_string(c, add_delta(it, incr, delta, temp));
+ out_string(c, add_delta(c, it, incr, delta, temp));
item_remove(it); /* release our reference */
}
/*
* adds a delta value to a numeric item.
*
+ * c connection requesting the operation
* it item to adjust
* incr true to increment value, false to decrement
* delta amount to adjust value by
* buf buffer for response string
*
* returns a response string to send back to the client.
*/
-char *do_add_delta(item *it, const bool incr, const int64_t delta, char *buf) {
+char *do_add_delta(conn *c, item *it, const bool incr, const int64_t delta, char *buf) {
char *ptr;
int64_t value;
int res;
@@ -2401,13 +2438,15 @@ char *do_add_delta(item *it, const bool incr, const int64_t delta, char *buf) {
return "CLIENT_ERROR cannot increment or decrement non-numeric value";
}
- if (incr)
+ if (incr) {
value += delta;
- else {
+ MEMCACHED_COMMAND_INCR(c->sfd, ITEM_key(it), value);
+ } else {
value -= delta;
- }
- if(value < 0) {
- value = 0;
+ if(value < 0) {
+ value = 0;
+ }
+ MEMCACHED_COMMAND_DECR(c->sfd, ITEM_key(it), value);
}
sprintf(buf, "%llu", value);
res = strlen(buf);
@@ -2465,6 +2504,7 @@ static void process_delete_command(conn *c, token_t *tokens, const size_t ntoken
it = item_get(key, nkey);
if (it) {
+ MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes);
item_unlink(it);
item_remove(it); /* release our reference */
out_string(c, "DELETED");
@@ -2494,6 +2534,8 @@ static void process_command(conn *c, char *command) {
assert(c != NULL);
+ MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes);
+
if (settings.verbose > 1)
fprintf(stderr, "<%d %s\n", c->sfd, command);
View
@@ -281,7 +281,8 @@ conn *do_conn_from_freelist();
bool do_conn_add_to_freelist(conn *c);
char *do_suffix_from_freelist();
bool do_suffix_add_to_freelist(char *s);
-char *do_add_delta(item *item, const bool incr, const int64_t delta, char *buf);
+char *do_add_delta(conn *c, item *item, const bool incr, const int64_t delta,
+ char *buf);
int do_store_item(item *item, int comm, conn* c);
conn *conn_new(const int sfd, const enum conn_states init_state, const int event_flags, const int read_buffer_size, enum protocol prot, struct event_base *base);
@@ -290,6 +291,7 @@ conn *conn_new(const int sfd, const enum conn_states init_state, const int event
#include "slabs.h"
#include "assoc.h"
#include "items.h"
+#include "memcached_dtrace.h"
/*
@@ -304,7 +306,8 @@ int dispatch_event_add(int thread, conn *c);
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags, int read_buffer_size, enum protocol prot);
/* Lock wrappers for cache functions that are called from main loop. */
-char *add_delta(item *item, const int incr, const int64_t delta, char *buf);
+char *add_delta(conn *c, item *item, const int incr, const int64_t delta,
+ char *buf);
void assoc_move_next_bucket(void);
conn *conn_from_freelist(void);
bool conn_add_to_freelist(conn *c);
Oops, something went wrong.

0 comments on commit 6895721

Please sign in to comment.