Updated to latest memcached
authorBrian Aker <brian@tangent.org>
Fri, 3 Aug 2012 11:11:58 +0000 (07:11 -0400)
committerBrian Aker <brian@tangent.org>
Fri, 3 Aug 2012 11:11:58 +0000 (07:11 -0400)
25 files changed:
configure.ac
libtest/cmdline.cc
memcached/README [deleted file]
memcached/README.md [new file with mode: 0644]
memcached/assoc.c
memcached/autogen.sh
memcached/cache.c
memcached/daemon.c
memcached/devtools/clean-whitespace.pl
memcached/doc/protocol.txt
memcached/hash.c
memcached/items.c
memcached/memcached.c
memcached/memcached.h
memcached/memcached.spec.in
memcached/memcached_dtrace.d
memcached/slabs.c
memcached/slabs.h
memcached/t/binary.t
memcached/t/slabs_reassign.t
memcached/t/whitespace.t
memcached/testapp.c
memcached/thread.c
memcached/util.c
memcached/version.m4 [deleted file]

index bcb2d32064666219281cf23c26eb85af75a0eb65..7b6127a078cd9d9c6c2ca32a1378a282ada65c0e 100644 (file)
@@ -69,7 +69,6 @@ m4_include([libtest/yatl.m4])
 m4_include([m4/memcached_sasl.m4])
 m4_include([m4/gearmand.m4])
 m4_include([m4/libgearman.m4])
-m4_include([memcached/version.m4])
 
 AM_CONDITIONAL(BUILDING_LIBMEMCACHED, true)
 AM_CONDITIONAL(HAVE_LIBMEMCACHED, false)
index 3179d1928c89a07c101a57d2b5ce16172018deff..f43b1c28b72ca970d679e0b274ca5faa7ddc7628 100644 (file)
@@ -82,7 +82,6 @@ extern "C" {
 
 namespace {
 
-#if 0
   std::string print_argv(libtest::vchar_ptr_t& built_argv)
   {
     std::stringstream arg_buffer;
@@ -96,8 +95,8 @@ namespace {
 
     return arg_buffer.str();
   }
-#endif
 
+#if 0
   std::string print_argv(char** argv)
   {
     std::stringstream arg_buffer;
@@ -109,6 +108,8 @@ namespace {
 
     return arg_buffer.str();
   }
+#endif
+
 
   static Application::error_t int_to_error_t(int arg)
   {
@@ -458,6 +459,7 @@ Application::error_t Application::wait(bool nohang)
   if (exit_code == Application::INVALID)
   {
     Error << print_argv(built_argv, _argc);
+    /
   }
 #endif
 
@@ -514,13 +516,11 @@ Application::error_t Application::join()
 
   slurp();
 
-#if 0
   if (exit_code == Application::INVALID)
   {
-    Error << print_argv(built_argv, _argc);
+    Error << print_argv(built_argv);
   }
-#endif
-
+;
   return exit_code;
 }
 
diff --git a/memcached/README b/memcached/README
deleted file mode 100644 (file)
index f20dd8c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Dependencies:
-
-   -- libevent, http://www.monkey.org/~provos/libevent/ (libevent-dev)
-
-If using Linux, you need a kernel with epoll.  Sure, libevent will
-work with normal select, but it sucks.
-
-epoll isn't in Linux 2.4, but there's a backport at:
-
-    http://www.xmailserver.org/linux-patches/nio-improve.html
-
-You want the epoll-lt patch (level-triggered).
-
-If you're using MacOS, you'll want libevent 1.1 or higher to deal with
-a kqueue bug.
-
-Also, be warned that the -k (mlockall) option to memcached might be
-dangerous when using a large cache.  Just make sure the memcached machines
-don't swap.  memcached does non-blocking network I/O, but not disk.  (it
-should never go to disk, or you've lost the whole point of it)
-
-The memcached website is at:
-
-    http://www.memcached.org
-
-Want to contribute?  Up-to-date pointers should be at:
-
-    http://contributing.appspot.com/memcached
diff --git a/memcached/README.md b/memcached/README.md
new file mode 100644 (file)
index 0000000..27a6896
--- /dev/null
@@ -0,0 +1,38 @@
+# Memcached
+
+## Dependencies
+
+* libevent, http://www.monkey.org/~provos/libevent/ (libevent-dev)
+
+## Environment
+
+### Linux
+
+If using Linux, you need a kernel with epoll.  Sure, libevent will
+work with normal select, but it sucks.
+
+epoll isn't in Linux 2.4, but there's a backport at:
+
+    http://www.xmailserver.org/linux-patches/nio-improve.html
+
+You want the epoll-lt patch (level-triggered).
+
+### Mac OS X
+
+If you're using MacOS, you'll want libevent 1.1 or higher to deal with
+a kqueue bug.
+
+Also, be warned that the -k (mlockall) option to memcached might be
+dangerous when using a large cache.  Just make sure the memcached machines
+don't swap.  memcached does non-blocking network I/O, but not disk.  (it
+should never go to disk, or you've lost the whole point of it)
+
+## Website
+
+* http://www.memcached.org
+
+## Contributing
+
+Want to contribute?  Up-to-date pointers should be at:
+
+* http://contributing.appspot.com/memcached
index f14d85d80a20168420f907924c5a505cd49f420f..bcaf6f2692e4b4785b4580b07ba034a2f31c089f 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include "memcached.h"
-
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/signal.h>
 
 static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
 
 typedef  unsigned long  int  ub4;   /* unsigned 4-byte quantities */
 typedef  unsigned       char ub1;   /* unsigned 1-byte quantities */
@@ -243,7 +235,7 @@ static void *assoc_maintenance_thread(void *arg) {
             pthread_cond_wait(&maintenance_cond, &cache_lock);
         }
 
-        pthread_mutex_unlock(&cache_lock);
+        mutex_unlock(&cache_lock);
     }
     return NULL;
 }
@@ -271,7 +263,7 @@ void stop_assoc_maintenance_thread() {
     mutex_lock(&cache_lock);
     do_run_maintenance_thread = 0;
     pthread_cond_signal(&maintenance_cond);
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 
     /* Wait for the maintenance thread to stop */
     pthread_join(maintenance_tid, NULL);
index c735394da8bb20c135d01bf86ecd03b5b4e0e1c6..a3a97672f82149af95e47871b0339877804b121b 100755 (executable)
@@ -39,7 +39,7 @@ $AUTOHEADER || exit 1
 
 echo "automake..."
 if test x$AUTOMAKE = x; then
-  AUTOMAKE=`locate_binary automake-1.11 automake-1.10 automake-1.9 automake-1.7`
+  AUTOMAKE=`locate_binary automake-1.12 automake-1.11 automake-1.10 automake-1.9 automake-1.7`
   if test x$AUTOMAKE = x; then
     die "Did not find a supported automake"
   fi
index 7dcf2fbb4468136ab79b4288a0b2e42216aeee7c..fcb3d2bfe1fd32083ec5401f11864df42a0e41bb 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#include "memcached.h"
+#include <config.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -68,6 +68,7 @@ void cache_destroy(cache_t *cache) {
     free(cache->name);
     free(cache->ptr);
     pthread_mutex_destroy(&cache->mutex);
+    free(cache);
 }
 
 void* cache_alloc(cache_t *cache) {
index 2f189157633069fc8d4e2a0432e080bf631f979b..d42e5b08778df0810f4aa6cf6ef536fb534e711f 100644 (file)
  * SUCH DAMAGE.
  */
 
+#include <config.h>
+
 #if defined __SUNPRO_C || defined __DECC || defined __HP_cc
 # pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $"
 # pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $"
 #endif
 
-#include "memcached.h"
-
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "memcached.h"
+
 int daemonize(int nochdir, int noclose)
 {
     int fd;
index 95481ef401bcfb1825b6032622698b8d59a09d89..fe0580673ca95b87a051f9e450c1a742dea3f212 100755 (executable)
@@ -3,7 +3,7 @@ use strict;
 use FindBin qw($Bin);
 chdir "$Bin/.." or die;
 
-my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am);
+my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am README README.md);
 push(@exempted, glob("doc/*.xml"));
 push(@exempted, glob("doc/xml2rfc/*.xsl"));
 push(@exempted, glob("m4/*backport*m4"));
index 1a844f0aaa539b33d8488cc8df2f406fdf75a0c3..b26d9625dfb3a6ab76088ce584c0d48b60a422b1 100644 (file)
@@ -354,6 +354,8 @@ slabs reassign <source class> <dest class>\r\n
 
 - <source class> is an id number for the slab class to steal a page from
 
+A source class id of -1 means "pick from any valid class"
+
 - <dest class> is an id number for the slab class to move a page to
 
 The response line could be one of:
@@ -385,12 +387,20 @@ more details.
 
 The automover can be enabled or disabled at runtime with this command.
 
-slabs automove <1|0>
+slabs automove <0|1>
 
-- 1|0 is the indicator on whether to enable the slabs automover or not.
+- 0|1|2 is the indicator on whether to enable the slabs automover or not.
 
 The response should always be "OK\r\n"
 
+- <0> means to set the thread on standby
+
+- <1> means to run the builtin slow algorithm to choose pages to move
+
+- <2> is a highly aggressive mode which causes pages to be moved every time
+  there is an eviction. It is not recommended to run for very long in this
+  mode unless your access patterns are very well understood.
+
 Statistics
 ----------
 
@@ -406,7 +416,7 @@ settings, documented below.  In the other form it has some arguments:
 stats <args>\r\n
 
 Depending on <args>, various internal data is sent by the server. The
-kinds of arguments and the data sent are not documented in this vesion
+kinds of arguments and the data sent are not documented in this version
 of the protocol, and are subject to change for the convenience of
 memcache developers.
 
index 6c9b9b6aa5b9861e0fe207446fc0d89a003ef914..fcfc1ffcd321ed6658323fe3635b3123b6ad4a35 100644 (file)
  * whether it's big or little-endian. ENDIAN_LITTLE and ENDIAN_BIG
  * are set in the configure script.
  */
-#if defined(ENDIAN_BIG) && ENDIAN_BIG == 1
+#if ENDIAN_BIG == 1
 # define HASH_LITTLE_ENDIAN 0
 # define HASH_BIG_ENDIAN 1
 #else
-# if defined(ENDIAN_LITTLE) && ENDIAN_LITTLE == 1
+# if ENDIAN_LITTLE == 1
 #  define HASH_LITTLE_ENDIAN 1
 #  define HASH_BIG_ENDIAN 0
 # else
@@ -178,8 +178,6 @@ uint32_t hash(
     case 2 : a+=k[0]&0xffff; break;
     case 1 : a+=k[0]&0xff; break;
     case 0 : return c;  /* zero length strings require no mixing */
-    default:
-             abort();
     }
 
 #else /* make valgrind happy */
@@ -249,8 +247,6 @@ uint32_t hash(
     case 1 : a+=k8[0];
              break;
     case 0 : return c;  /* zero length strings require no mixing */
-    default:
-             abort();
     }
 
   } else {                        /* need to read the key one byte at a time */
@@ -293,8 +289,6 @@ uint32_t hash(
     case 1 : a+=k[0];
              break;
     case 0 : return c;  /* zero length strings require no mixing */
-    default:
-             abort();
     }
   }
 
index 58fc871787aae955ca21243b50c5ab26a3db5310..84011c4402a39f71eba3b097e11e6799b6f31b0a 100644 (file)
@@ -44,7 +44,7 @@ static unsigned int sizes[LARGEST_ID];
 void item_stats_reset(void) {
     mutex_lock(&cache_lock);
     memset(itemstats, 0, sizeof(itemstats));
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 
@@ -125,7 +125,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
         } else if ((it = slabs_alloc(ntotal, id)) == NULL) {
             if (settings.evict_to_free == 0) {
                 itemstats[id].outofmemory++;
-                pthread_mutex_unlock(&cache_lock);
+                mutex_unlock(&cache_lock);
                 return NULL;
             }
             itemstats[id].evicted++;
@@ -146,6 +146,16 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
             do_item_unlink_nolock(it, hash(ITEM_key(it), it->nkey, 0));
             /* Initialize the item block: */
             it->slabs_clsid = 0;
+
+            /* If we've just evicted an item, and the automover is set to
+             * angry bird mode, attempt to rip memory into this slab class.
+             * TODO: Move valid object detection into a function, and on a
+             * "successful" memory pull, look behind and see if the next alloc
+             * would be an eviction. Then kick off the slab mover before the
+             * eviction happens.
+             */
+            if (settings.slab_automove == 2)
+                slabs_reassign(-1, id);
         } else {
             refcount_decr(&search->refcount);
         }
@@ -171,7 +181,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
             search->refcount = 1;
             do_item_unlink_nolock(search, hash(ITEM_key(search), search->nkey, 0));
         }
-        pthread_mutex_unlock(&cache_lock);
+        mutex_unlock(&cache_lock);
         return NULL;
     }
 
@@ -182,7 +192,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
      * been removed from the slab LRU.
      */
     it->refcount = 1;     /* the caller will have a reference */
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
     it->next = it->prev = it->h_next = 0;
     it->slabs_clsid = id;
 
@@ -288,7 +298,7 @@ int do_item_link(item *it, const uint32_t hv) {
     assoc_insert(it, hv);
     item_link_q(it);
     refcount_incr(&it->refcount);
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 
     return 1;
 }
@@ -306,7 +316,7 @@ void do_item_unlink(item *it, const uint32_t hv) {
         item_unlink_q(it);
         do_item_remove(it);
     }
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 /* FIXME: Is it necessary to keep this copy/pasted code? */
@@ -344,7 +354,7 @@ void do_item_update(item *it) {
             it->time = current_time;
             item_link_q(it);
         }
-        pthread_mutex_unlock(&cache_lock);
+        mutex_unlock(&cache_lock);
     }
 }
 
@@ -357,10 +367,6 @@ int do_item_replace(item *it, item *new_it, const uint32_t hv) {
     return do_item_link(new_it, hv);
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wshadow"
-#endif
-
 /*@null@*/
 char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, unsigned int *bytes) {
     unsigned int memlimit = 2 * 1024 * 1024;   /* 2MB max response size */
@@ -407,7 +413,7 @@ void item_stats_evictions(uint64_t *evicted) {
     for (i = 0; i < LARGEST_ID; i++) {
         evicted[i] = itemstats[i].evicted;
     }
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 void do_item_stats(ADD_STAT add_stats, void *c) {
@@ -499,7 +505,7 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
             it = NULL;
         }
     }
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
     int was_found = 0;
 
     if (settings.verbose > 2) {
index 10374421c39f8b068e8cc221a39c7ef8e9ba125e..2cb0b2069028f91e62473a3869e0699ffe0d59bb 100644 (file)
@@ -125,9 +125,6 @@ static enum transmit_result transmit(conn *c);
  */
 static volatile bool allow_new_conns = true;
 static struct event maxconnsevent;
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
 static void maxconns_handler(const int fd, const short which, void *arg) {
     struct timeval t = {.tv_sec = 0, .tv_usec = 10000};
 
@@ -227,7 +224,7 @@ static void settings_init(void) {
     settings.maxconns_fast = false;
     settings.hashpower_init = 0;
     settings.slab_reassign = false;
-    settings.slab_automove = false;
+    settings.slab_automove = 0;
 }
 
 /*
@@ -336,7 +333,7 @@ bool conn_add_to_freelist(conn *c) {
 }
 
 static const char *prot_text(enum protocol prot) {
-    const char *rv = "unknown";
+    char *rv = "unknown";
     switch(prot) {
         case ascii_prot:
             rv = "ascii";
@@ -347,8 +344,6 @@ static const char *prot_text(enum protocol prot) {
         case negotiating_prot:
             rv = "auto-negotiate";
             break;
-        default:
-            abort();
     }
     return rv;
 }
@@ -639,9 +634,6 @@ static const char *state_text(enum conn_states state) {
     return statenames[state];
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wtype-limits"
-#endif
 /*
  * Sets a connection's current state in the state machine. Any special
  * processing that needs to happen on certain state transitions can
@@ -791,9 +783,6 @@ static int build_udp_headers(conn *c) {
 }
 
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#endif
 static void out_string(conn *c, const char *str) {
     size_t len;
 
@@ -1000,10 +989,6 @@ static void write_bin_error(conn *c, protocol_binary_response_status err, int sw
     case PROTOCOL_BINARY_RESPONSE_AUTH_ERROR:
         errstr = "Auth failure.";
         break;
-    case PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE:
-        assert(false);
-    case PROTOCOL_BINARY_RESPONSE_SUCCESS:
-        assert(false);
     default:
         assert(false);
         errstr = "UNHANDLED ERROR";
@@ -1029,7 +1014,7 @@ static void write_bin_error(conn *c, protocol_binary_response_status err, int sw
 }
 
 /* Form and send a response to a command over the binary protocol */
-static void write_bin_response(conn *c, const void *d, int hlen, int keylen, int dlen) {
+static void write_bin_response(conn *c, void *d, int hlen, int keylen, int dlen) {
     if (!c->noreply || c->cmd == PROTOCOL_BINARY_CMD_GET ||
         c->cmd == PROTOCOL_BINARY_CMD_GETK) {
         add_bin_header(c, 0, hlen, keylen, dlen);
@@ -1133,10 +1118,6 @@ static void complete_incr_bin(conn *c) {
     case DELTA_ITEM_CAS_MISMATCH:
         write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS, 0);
         break;
-
-    default:
-        assert(0);
-        abort();
     }
 }
 
@@ -1204,9 +1185,6 @@ static void complete_update_bin(conn *c) {
             eno = PROTOCOL_BINARY_RESPONSE_NOT_STORED;
         }
         write_bin_error(c, eno, 0);
-    default:
-        assert(false);
-        abort();
     }
 
     item_remove(c->item);       /* release the c->item reference */
@@ -1219,8 +1197,8 @@ static void process_bin_touch(conn *c) {
     protocol_binary_response_get* rsp = (protocol_binary_response_get*)c->wbuf;
     char* key = binary_get_key(c);
     size_t nkey = c->binary_header.request.keylen;
-    protocol_binary_request_touch *t = (void *)&c->binary_header;
-    uint32_t exptime = ntohl(t->message.body.expiration);
+    protocol_binary_request_touch *t = binary_get_request(c);
+    time_t exptime = ntohl(t->message.body.expiration);
 
     if (settings.verbose > 1) {
         int ii;
@@ -1387,9 +1365,6 @@ static void process_bin_get(conn *c) {
     }
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-#endif
 static void append_bin_stats(const char *key, const uint16_t klen,
                              const char *val, const uint32_t vlen,
                              conn *c) {
@@ -1397,14 +1372,11 @@ static void append_bin_stats(const char *key, const uint16_t klen,
     uint32_t bodylen = klen + vlen;
     protocol_binary_response_header header = {
         .response.magic = (uint8_t)PROTOCOL_BINARY_RES,
-        .response.opcode = (uint8_t)PROTOCOL_BINARY_CMD_STAT,
+        .response.opcode = PROTOCOL_BINARY_CMD_STAT,
         .response.keylen = (uint16_t)htons(klen),
-        .response.extlen = (uint8_t)0,
         .response.datatype = (uint8_t)PROTOCOL_BINARY_RAW_BYTES,
-        .response.status = (uint16_t)0,
         .response.bodylen = htonl(bodylen),
-        .response.opaque = c->opaque,
-        .response.cas = (uint64_t)0
+        .response.opaque = c->opaque
     };
 
     memcpy(buf, header.bytes, sizeof(header.response));
@@ -1887,7 +1859,7 @@ static void dispatch_bin_command(conn *c) {
     switch (c->cmd) {
         case PROTOCOL_BINARY_CMD_VERSION:
             if (extlen == 0 && keylen == 0 && bodylen == 0) {
-                write_bin_response(c, RVERSION, 0, 0, strlen(RVERSION));
+                write_bin_response(c, VERSION, 0, 0, strlen(VERSION));
             } else {
                 protocol_error = 1;
             }
@@ -2246,10 +2218,6 @@ static void complete_nread_binary(conn *c) {
     case bin_reading_sasl_auth_data:
         process_bin_complete_sasl_auth(c);
         break;
-    case bin_reading_cas_header:
-        assert(0);
-    case bin_no_state:
-        assert(0);
     default:
         fprintf(stderr, "Not handling substate %d\n", c->substate);
         assert(0);
@@ -2568,7 +2536,7 @@ static void server_stats(ADD_STAT add_stats, conn *c) {
     APPEND_STAT("pid", "%lu", (long)pid);
     APPEND_STAT("uptime", "%u", now);
     APPEND_STAT("time", "%ld", now + (long)process_started);
-    APPEND_STAT("version", "%s", RVERSION);
+    APPEND_STAT("version", "%s", VERSION);
     APPEND_STAT("libevent", "%s", event_get_version());
     APPEND_STAT("pointer_size", "%d", (int)(8 * sizeof(void *)));
 
@@ -2656,7 +2624,7 @@ static void process_stat_settings(ADD_STAT add_stats, void *c) {
     APPEND_STAT("maxconns_fast", "%s", settings.maxconns_fast ? "yes" : "no");
     APPEND_STAT("hashpower_init", "%d", settings.hashpower_init);
     APPEND_STAT("slab_reassign", "%s", settings.slab_reassign ? "yes" : "no");
-    APPEND_STAT("slab_automove", "%s", settings.slab_automove ? "yes" : "no");
+    APPEND_STAT("slab_automove", "%d", settings.slab_automove);
 }
 
 static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
@@ -2735,9 +2703,6 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
     }
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
-#endif
 /* ntokens is overwritten here... shrug.. */
 static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas) {
     char *key;
@@ -3072,9 +3037,6 @@ static void process_arithmetic_command(conn *c, token_t *tokens, const size_t nt
         break;
     case DELTA_ITEM_CAS_MISMATCH:
         break; /* Should never get here */
-    default:
-        assert(false);
-        abort();
     }
 }
 
@@ -3156,7 +3118,7 @@ enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
            need to update the CAS on the existing item. */
         mutex_lock(&cache_lock); /* FIXME */
         ITEM_set_cas(it, (settings.use_cas) ? get_cas_id() : 0);
-        pthread_mutex_unlock(&cache_lock);
+        mutex_unlock(&cache_lock);
 
         memcpy(ITEM_data(it), buf, res);
         memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2);
@@ -3244,9 +3206,9 @@ static void process_slabs_automove_command(conn *c, token_t *tokens, const size_
 
     level = strtoul(tokens[2].value, NULL, 10);
     if (level == 0) {
-        settings.slab_automove = false;
-    } else if (level == 1) {
-        settings.slab_automove = true;
+        settings.slab_automove = 0;
+    } else if (level == 1 || level == 2) {
+        settings.slab_automove = level;
     } else {
         out_string(c, "ERROR");
         return;
@@ -3363,7 +3325,7 @@ static void process_command(conn *c, char *command) {
 
     } else if (ntokens == 2 && (strcmp(tokens[COMMAND_TOKEN].value, "version") == 0)) {
 
-        out_string(c, "VERSION " RVERSION);
+        out_string(c, "VERSION " VERSION);
 
     } else if (ntokens == 2 && (strcmp(tokens[COMMAND_TOKEN].value, "quit") == 0)) {
 
@@ -3400,18 +3362,9 @@ static void process_command(conn *c, char *command) {
             case REASSIGN_NOSPARE:
                 out_string(c, "NOSPARE source class has no spare pages");
                 break;
-            case REASSIGN_DEST_NOT_FULL:
-                out_string(c, "NOTFULL dest class has spare memory");
-                break;
-            case REASSIGN_SRC_NOT_SAFE:
-                out_string(c, "UNSAFE src class is in an unsafe state");
-                break;
             case REASSIGN_SRC_DST_SAME:
                 out_string(c, "SAME src and dst class are identical");
                 break;
-            default:
-                assert(false);
-                abort();
             }
             return;
         } else if (ntokens == 4 &&
@@ -3866,9 +3819,6 @@ static void drive_machine(conn *c) {
             case READ_MEMORY_ERROR: /* Failed to allocate more memory */
                 /* State already set by try_read_network */
                 break;
-            default:
-                assert(false);
-                abort();
             }
             break;
 
@@ -4078,9 +4028,6 @@ static void drive_machine(conn *c) {
             case TRANSMIT_SOFT_ERROR:
                 stop = true;
                 break;
-            default:
-                assert(false);
-                abort();
             }
             break;
 
@@ -4095,9 +4042,6 @@ static void drive_machine(conn *c) {
         case conn_max_state:
             assert(false);
             break;
-        default:
-            assert(false);
-            abort();
         }
     }
 
@@ -4242,12 +4186,7 @@ static int server_socket(const char *interface,
         }
 #endif
 
-        error = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
-        if (error != 0)
-        {
-          perror("setsockopt(SO_REUSEADDR)");
-        }
-
+        setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
         if (IS_UDP(transport)) {
             maximize_sndbuf(sfd);
         } else {
@@ -4504,7 +4443,7 @@ static void clock_handler(const int fd, const short which, void *arg) {
 }
 
 static void usage(void) {
-    printf(RPACKAGE " " RVERSION "\n");
+    printf(PACKAGE " " VERSION "\n");
     printf("-p <num>      TCP port number to listen on (default: 11211)\n"
            "-U <num>      UDP port number to listen on (default: 11211, 0 is off)\n"
            "-s <file>     UNIX socket path to listen on (disables network support)\n"
@@ -4569,7 +4508,7 @@ static void usage(void) {
 }
 
 static void usage_license(void) {
-    printf(RPACKAGE " " RVERSION "\n\n");
+    printf(PACKAGE " " VERSION "\n\n");
     printf(
     "Copyright (c) 2003, Danga Interactive, Inc. <http://www.danga.com/>\n"
     "All rights reserved.\n"
@@ -4731,7 +4670,7 @@ static int enable_large_pages(void) {
 
     return ret;
 #else
-    return 0;
+    return -1;
 #endif
 }
 
@@ -4788,10 +4727,10 @@ int main (int argc, char **argv) {
         SLAB_AUTOMOVE
     };
     char *const subopts_tokens[] = {
-        [MAXCONNS_FAST] = (char*)"maxconns_fast",
-        [HASHPOWER_INIT] = (char*)"hashpower",
-        [SLAB_REASSIGN] = (char*)"slab_reassign",
-        [SLAB_AUTOMOVE] = (char*)"slab_automove",
+        [MAXCONNS_FAST] = "maxconns_fast",
+        [HASHPOWER_INIT] = "hashpower",
+        [SLAB_REASSIGN] = "slab_reassign",
+        [SLAB_AUTOMOVE] = "slab_automove",
         NULL
     };
 
@@ -4952,6 +4891,10 @@ int main (int argc, char **argv) {
         case 'L' :
             if (enable_large_pages() == 0) {
                 preallocate = true;
+            } else {
+                fprintf(stderr, "Cannot enable large pages on this system\n"
+                    "(There is no Linux support as of this version)\n");
+                return 1;
             }
             break;
         case 'C' :
@@ -5041,7 +4984,15 @@ int main (int argc, char **argv) {
                 settings.slab_reassign = true;
                 break;
             case SLAB_AUTOMOVE:
-                settings.slab_automove = true;
+                if (subopts_value == NULL) {
+                    settings.slab_automove = 1;
+                    break;
+                }
+                settings.slab_automove = atoi(subopts_value);
+                if (settings.slab_automove < 0 || settings.slab_automove > 2) {
+                    fprintf(stderr, "slab_automove must be between 0 and 2\n");
+                    return 1;
+                }
                 break;
             default:
                 printf("Illegal suboption \"%s\"\n", subopts_value);
@@ -5283,10 +5234,8 @@ int main (int argc, char **argv) {
     stop_assoc_maintenance_thread();
 
     /* remove the PID file if we're a daemon */
-#if 0
     if (do_daemonize)
         remove_pidfile(pid_file);
-#endif
     /* Clean up strdup() call for bind() address */
     if (settings.inter)
       free(settings.inter);
index d070502c023c70c8d99e8b44032afe715c84659f..edd7fcf8cfefbbc42dbcb732785a0778524f18f6 100644 (file)
@@ -10,7 +10,6 @@
 #endif
 
 #include <stdbool.h>
-#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/time.h>
@@ -74,7 +73,6 @@
 #define POWER_SMALLEST 1
 #define POWER_LARGEST  200
 #define CHUNK_ALIGN_BYTES 8
-#define DONT_PREALLOC_SLABS
 #define MAX_NUMBER_OF_SLAB_CLASSES (POWER_LARGEST + 1)
 
 /** How long an object can reasonably be assumed to be locked before
@@ -303,13 +301,10 @@ struct settings {
     bool sasl;              /* SASL on/off */
     bool maxconns_fast;     /* Whether or not to early close connections */
     bool slab_reassign;     /* Whether or not slab reassignment is allowed */
-    bool slab_automove;     /* Whether or not to automatically move slabs */
+    int slab_automove;     /* Whether or not to automatically move slabs */
     int hashpower_init;     /* Starting hash power level */
 };
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wshadow"
-#endif
 extern struct stats stats;
 extern time_t process_started;
 extern struct settings settings;
@@ -322,9 +317,6 @@ extern struct settings settings;
 
 #define ITEM_FETCHED 8
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wshadow"
-#endif
 /**
  * Structure for storing items within memcached.
  */
@@ -556,7 +548,7 @@ void append_stat(const char *name, ADD_STAT add_stats, conn *c,
 
 enum store_item_type store_item(item *item, int comm, conn *c);
 
-#if defined(HAVE_DROP_PRIVILEGES) && HAVE_DROP_PRIVILEGES
+#if HAVE_DROP_PRIVILEGES
 extern void drop_privileges(void);
 #else
 #define drop_privileges()
index f473d8fa3ad01ff3d3646205fba492070c75024f..678be90a633767645bffbef618688c3f0055df88 100644 (file)
@@ -83,7 +83,7 @@ exit 0
 
 %files
 %defattr(-,root,root,-)
-%doc AUTHORS ChangeLog COPYING NEWS README doc/CONTRIBUTORS doc/*.txt
+%doc AUTHORS ChangeLog COPYING NEWS README.md doc/CONTRIBUTORS doc/*.txt
 %config(noreplace) %{_sysconfdir}/sysconfig/%{name}
 
 %dir %attr(750,nobody,nobody) %{_localstatedir}/run/memcached
index eeffb6f3e67bc9ba8e1a99e044333c1cf31d9ab1..0fe132c442933393504b242bb64bb82322b5e77e 100644 (file)
@@ -250,6 +250,17 @@ provider memcached {
     */
    probe command__append(int connid, const char *key, int keylen, int size, int64_t casid);
 
+   /**
+    * Fired for an touch-command.
+    * @param connid connection id
+    * @param key requested key
+    * @param keylen length of the key
+    * @param size the new size of the key's data (or signed int -1 if
+    *             not found)
+    * @param casid the casid for the item
+    */
+   probe command__touch(int connid, const char *key, int keylen, int size, int64_t casid);
+
    /**
     * Fired for a cas-command.
     * @param connid connection id
index 7cffe43474927aa1bfb953e23611455214fac6d0..b74617e25de9ebc2c814e0515c8a63bb0315d358 100644 (file)
@@ -30,9 +30,6 @@ typedef struct {
     void *slots;           /* list of item ptrs */
     unsigned int sl_curr;   /* total free items in list */
 
-    void *end_page_ptr;         /* pointer to next free item at end of page, or 0 */
-    unsigned int end_page_free; /* number of items remaining at end of last alloced page */
-
     unsigned int slabs;     /* how many slabs were allocated for this class */
 
     void **slab_list;       /* array of slab pointers */
@@ -55,14 +52,15 @@ static size_t mem_avail = 0;
  * Access to the slab allocator is protected by this lock
  */
 static pthread_mutex_t slabs_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t slabs_rebalance_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /*
  * Forward Declarations
  */
 static int do_slabs_newslab(const unsigned int id);
 static void *memory_allocate(size_t size);
+static void do_slabs_free(void *ptr, const size_t size, unsigned int id);
 
-#ifndef DONT_PREALLOC_SLABS
 /* Preallocate as many slab pages as possible (called from slabs_init)
    on start-up, so users don't get confused out-of-memory errors when
    they do have free (in-slab) space, but no space to make new slabs.
@@ -70,7 +68,6 @@ static void *memory_allocate(size_t size);
    slab types can be made.  if max memory is less than 18 MB, only the
    smaller ones will be made.  */
 static void slabs_preallocate (const unsigned int maxslabs);
-#endif
 
 /*
  * Figures out which slab class (chunk size) is required to store an item of
@@ -146,18 +143,11 @@ void slabs_init(const size_t limit, const double factor, const bool prealloc) {
 
     }
 
-#ifndef DONT_PREALLOC_SLABS
-    {
-        char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC");
-
-        if (pre_alloc == NULL || atoi(pre_alloc) != 0) {
-            slabs_preallocate(power_largest);
-        }
+    if (prealloc) {
+        slabs_preallocate(power_largest);
     }
-#endif
 }
 
-#ifndef DONT_PREALLOC_SLABS
 static void slabs_preallocate (const unsigned int maxslabs) {
     int i;
     unsigned int prealloc = 0;
@@ -171,11 +161,15 @@ static void slabs_preallocate (const unsigned int maxslabs) {
     for (i = POWER_SMALLEST; i <= POWER_LARGEST; i++) {
         if (++prealloc > maxslabs)
             return;
-        do_slabs_newslab(i);
+        if (do_slabs_newslab(i) == 0) {
+            fprintf(stderr, "Error while preallocating slab memory!\n"
+                "If using -L or other prealloc options, max memory must be "
+                "at least %d megabytes.\n", power_largest);
+            exit(1);
+        }
     }
 
 }
-#endif
 
 static int grow_slab_list (const unsigned int id) {
     slabclass_t *p = &slabclass[id];
@@ -189,9 +183,14 @@ static int grow_slab_list (const unsigned int id) {
     return 1;
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#endif
+static void split_slab_page_into_freelist(char *ptr, const unsigned int id) {
+    slabclass_t *p = &slabclass[id];
+    int x;
+    for (x = 0; x < p->perslab; x++) {
+        do_slabs_free(ptr, 0, id);
+        ptr += p->size;
+    }
+}
 
 static int do_slabs_newslab(const unsigned int id) {
     slabclass_t *p = &slabclass[id];
@@ -208,8 +207,7 @@ static int do_slabs_newslab(const unsigned int id) {
     }
 
     memset(ptr, 0, (size_t)len);
-    p->end_page_ptr = ptr;
-    p->end_page_free = p->perslab;
+    split_slab_page_into_freelist(ptr, id);
 
     p->slab_list[p->slabs++] = ptr;
     mem_malloced += len;
@@ -232,21 +230,9 @@ static void *do_slabs_alloc(const size_t size, unsigned int id) {
     p = &slabclass[id];
     assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);
 
-#ifdef USE_SYSTEM_MALLOC
-    if (mem_limit && mem_malloced + size > mem_limit) {
-        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
-        return 0;
-    }
-    mem_malloced += size;
-    ret = malloc(size);
-    MEMCACHED_SLABS_ALLOCATE(size, id, 0, ret);
-    return ret;
-#endif
-
     /* fail unless we have space at the end of a recently allocated page,
        we have something on our freelist, or we could allocate a new page */
-    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 ||
-           do_slabs_newslab(id) != 0)) {
+    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
         /* We don't have more memory available */
         ret = NULL;
     } else if (p->sl_curr != 0) {
@@ -256,15 +242,6 @@ static void *do_slabs_alloc(const size_t size, unsigned int id) {
         if (it->next) it->next->prev = 0;
         p->sl_curr--;
         ret = (void *)it;
-    } else {
-        /* if we recently allocated a whole page, return from that */
-        assert(p->end_page_ptr != NULL);
-        ret = p->end_page_ptr;
-        if (--p->end_page_free != 0) {
-            p->end_page_ptr = ((caddr_t)p->end_page_ptr) + p->size;
-        } else {
-            p->end_page_ptr = 0;
-        }
     }
 
     if (ret) {
@@ -289,12 +266,6 @@ static void do_slabs_free(void *ptr, const size_t size, unsigned int id) {
     MEMCACHED_SLABS_FREE(size, id, ptr);
     p = &slabclass[id];
 
-#ifdef USE_SYSTEM_MALLOC
-    mem_malloced -= size;
-    free(ptr);
-    return;
-#endif
-
     it = (item *)ptr;
     it->it_flags |= ITEM_SLABBED;
     it->prev = 0;
@@ -367,9 +338,10 @@ static void do_slabs_stats(ADD_STAT add_stats, void *c) {
             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);
+                            slabs*perslab - p->sl_curr);
             APPEND_NUM_STAT(i, "free_chunks", "%u", p->sl_curr);
-            APPEND_NUM_STAT(i, "free_chunks_end", "%u", p->end_page_free);
+            /* 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",
@@ -464,14 +436,15 @@ void slabs_adjust_mem_requested(unsigned int id, size_t old, size_t ntotal)
 }
 
 static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t slab_rebalance_cond = PTHREAD_COND_INITIALIZER;
 static volatile int do_run_slab_thread = 1;
+static volatile int do_run_slab_rebalance_thread = 1;
 
 #define DEFAULT_SLAB_BULK_CHECK 1
 int slab_bulk_check = DEFAULT_SLAB_BULK_CHECK;
 
 static int slab_rebalance_start(void) {
     slabclass_t *s_cls;
-    slabclass_t *d_cls;
     int no_go = 0;
 
     pthread_mutex_lock(&cache_lock);
@@ -485,10 +458,8 @@ static int slab_rebalance_start(void) {
         no_go = -2;
 
     s_cls = &slabclass[slab_rebal.s_clsid];
-    d_cls = &slabclass[slab_rebal.d_clsid];
 
-    if (d_cls->end_page_ptr || s_cls->end_page_ptr ||
-        !grow_slab_list(slab_rebal.d_clsid)) {
+    if (!grow_slab_list(slab_rebal.d_clsid)) {
         no_go = -1;
     }
 
@@ -597,9 +568,6 @@ static int slab_rebalance_move(void) {
                 break;
             case MOVE_PASS:
                 break;
-            default:
-                assert(false);
-                abort();
         }
 
         slab_rebal.slab_pos = (char *)slab_rebal.slab_pos + s_cls->size;
@@ -642,8 +610,8 @@ static void slab_rebalance_finish(void) {
     memset(slab_rebal.slab_start, 0, (size_t)settings.item_size_max);
 
     d_cls->slab_list[d_cls->slabs++] = slab_rebal.slab_start;
-    d_cls->end_page_ptr = slab_rebal.slab_start;
-    d_cls->end_page_free = d_cls->perslab;
+    split_slab_page_into_freelist(slab_rebal.slab_start,
+        slab_rebal.d_clsid);
 
     slab_rebal.done       = 0;
     slab_rebal.s_clsid    = 0;
@@ -735,43 +703,83 @@ static int slab_automove_decision(int *src, int *dst) {
     return 0;
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
 /* Slab rebalancer thread.
  * Does not use spinlocks since it is not timing sensitive. Burn less CPU and
  * go to sleep if locks are contended
  */
 static void *slab_maintenance_thread(void *arg) {
-    int was_busy = 0;
     int src, dest;
 
     while (do_run_slab_thread) {
+        if (settings.slab_automove == 1) {
+            if (slab_automove_decision(&src, &dest) == 1) {
+                /* Blind to the return codes. It will retry on its own */
+                slabs_reassign(src, dest);
+            }
+            sleep(1);
+        } else {
+            /* Don't wake as often if we're not enabled.
+             * This is lazier than setting up a condition right now. */
+            sleep(5);
+        }
+    }
+    return NULL;
+}
+
+/* Slab mover thread.
+ * Sits waiting for a condition to jump off and shovel some memory about
+ */
+static void *slab_rebalance_thread(void *arg) {
+    int was_busy = 0;
+
+    while (do_run_slab_rebalance_thread) {
         if (slab_rebalance_signal == 1) {
             if (slab_rebalance_start() < 0) {
                 /* Handle errors with more specifity as required. */
                 slab_rebalance_signal = 0;
             }
 
+            was_busy = 0;
         } else if (slab_rebalance_signal && slab_rebal.slab_start != NULL) {
-            /* If we have a decision to continue, continue it */
             was_busy = slab_rebalance_move();
-        } else if (settings.slab_automove && slab_automove_decision(&src, &dest) == 1) {
-            /* Blind to the return codes. It will retry on its own */
-            slabs_reassign(src, dest);
         }
 
         if (slab_rebal.done) {
             slab_rebalance_finish();
+        } else if (was_busy) {
+            /* Stuck waiting for some items to unlock, so slow down a bit
+             * to give them a chance to free up */
+            usleep(50);
         }
 
-        /* Sleep a bit if no work to do, or waiting on busy objects */
-        if (was_busy || !slab_rebalance_signal)
-            sleep(1);
+        if (slab_rebalance_signal == 0) {
+            /* always hold this lock while we're running */
+            pthread_cond_wait(&slab_rebalance_cond, &slabs_rebalance_lock);
+        }
     }
     return NULL;
 }
 
+/* Iterate at most once through the slab classes and pick a "random" source.
+ * I like this better than calling rand() since rand() is slow enough that we
+ * can just check all of the classes once instead.
+ */
+static int slabs_reassign_pick_any(int dst) {
+    static int cur = POWER_SMALLEST - 1;
+    int tries = power_largest - POWER_SMALLEST + 1;
+    for (; tries > 0; tries--) {
+        cur++;
+        if (cur > power_largest)
+            cur = POWER_SMALLEST;
+        if (cur == dst)
+            continue;
+        if (slabclass[cur].slabs > 1) {
+            return cur;
+        }
+    }
+    return -1;
+}
+
 static enum reassign_result_type do_slabs_reassign(int src, int dst) {
     if (slab_rebalance_signal != 0)
         return REASSIGN_RUNNING;
@@ -779,6 +787,12 @@ static enum reassign_result_type do_slabs_reassign(int src, int dst) {
     if (src == dst)
         return REASSIGN_SRC_DST_SAME;
 
+    /* Special indicator to choose ourselves. */
+    if (src == -1) {
+        src = slabs_reassign_pick_any(dst);
+        /* TODO: If we end up back at -1, return a new error type */
+    }
+
     if (src < POWER_SMALLEST || src > power_largest ||
         dst < POWER_SMALLEST || dst > power_largest)
         return REASSIGN_BADCLASS;
@@ -786,29 +800,27 @@ static enum reassign_result_type do_slabs_reassign(int src, int dst) {
     if (slabclass[src].slabs < 2)
         return REASSIGN_NOSPARE;
 
-    if (slabclass[dst].end_page_ptr)
-        return REASSIGN_DEST_NOT_FULL;
-
-    if (slabclass[src].end_page_ptr)
-        return REASSIGN_SRC_NOT_SAFE;
-
     slab_rebal.s_clsid = src;
     slab_rebal.d_clsid = dst;
 
     slab_rebalance_signal = 1;
+    pthread_cond_signal(&slab_rebalance_cond);
 
     return REASSIGN_OK;
 }
 
 enum reassign_result_type slabs_reassign(int src, int dst) {
     enum reassign_result_type ret;
-    mutex_lock(&slabs_lock);
+    if (pthread_mutex_trylock(&slabs_rebalance_lock) != 0) {
+        return REASSIGN_RUNNING;
+    }
     ret = do_slabs_reassign(src, dst);
-    pthread_mutex_unlock(&slabs_lock);
+    pthread_mutex_unlock(&slabs_rebalance_lock);
     return ret;
 }
 
 static pthread_t maintenance_tid;
+static pthread_t rebalance_tid;
 
 int start_slab_maintenance_thread(void) {
     int ret;
@@ -821,9 +833,21 @@ int start_slab_maintenance_thread(void) {
             slab_bulk_check = DEFAULT_SLAB_BULK_CHECK;
         }
     }
+
+    if (pthread_cond_init(&slab_rebalance_cond, NULL) != 0) {
+        fprintf(stderr, "Can't intiialize rebalance condition\n");
+        return -1;
+    }
+    pthread_mutex_init(&slabs_rebalance_lock, NULL);
+
     if ((ret = pthread_create(&maintenance_tid, NULL,
                               slab_maintenance_thread, NULL)) != 0) {
-        fprintf(stderr, "Can't create thread: %s\n", strerror(ret));
+        fprintf(stderr, "Can't create slab maint thread: %s\n", strerror(ret));
+        return -1;
+    }
+    if ((ret = pthread_create(&rebalance_tid, NULL,
+                              slab_rebalance_thread, NULL)) != 0) {
+        fprintf(stderr, "Can't create rebal thread: %s\n", strerror(ret));
         return -1;
     }
     return 0;
@@ -832,9 +856,11 @@ int start_slab_maintenance_thread(void) {
 void stop_slab_maintenance_thread(void) {
     mutex_lock(&cache_lock);
     do_run_slab_thread = 0;
+    do_run_slab_rebalance_thread = 0;
     pthread_cond_signal(&maintenance_cond);
     pthread_mutex_unlock(&cache_lock);
 
     /* Wait for the maintenance thread to stop */
     pthread_join(maintenance_tid, NULL);
+    pthread_join(rebalance_tid, NULL);
 }
index 90e2bd820fd601876887dfd35df08571597c7289..7c6140b2b40458fe58d83b84ad70007f0589385d 100644 (file)
@@ -16,9 +16,6 @@ void slabs_init(const size_t limit, const double factor, const bool prealloc);
  * 0 means error: can't store such a large object
  */
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wshadow"
-#endif
 unsigned int slabs_clsid(const size_t size);
 
 /** Allocate object of given length. 0 on error */ /*@null@*/
@@ -41,7 +38,7 @@ void stop_slab_maintenance_thread(void);
 
 enum reassign_result_type {
     REASSIGN_OK=0, REASSIGN_RUNNING, REASSIGN_BADCLASS, REASSIGN_NOSPARE,
-    REASSIGN_DEST_NOT_FULL, REASSIGN_SRC_NOT_SAFE, REASSIGN_SRC_DST_SAME
+    REASSIGN_SRC_DST_SAME
 };
 
 enum reassign_result_type slabs_reassign(int src, int dst);
index 504ddef1d7b6076801b4a15cc22ba46d433cc0fe..3eb8e0b243139e3c59bcf6e5126c89ab0db3392f 100755 (executable)
@@ -2,7 +2,7 @@
 
 use strict;
 use warnings;
-use Test::More tests => 3539;
+use Test::More tests => 3549;
 use FindBin qw($Bin);
 use lib "$Bin/lib";
 use MemcachedTest;
@@ -273,6 +273,10 @@ is($mc->decr("x", 211), 0, "Floor is zero");
     $check->("totouch", 0, "toast2");
 
     # Test miss as well
+    $mc->set("totouch", "toast3", 0, 1);
+    $res = $mc->touch("totouch", 1);
+    sleep 3;
+    $empty->("totouch");
 }
 
 # diag "Silent set.";
index cf4b6f8d927a76fceafb6d8261bee2e21b38b65e..ae5ddce31232350d9df14cc3beed9d8ce6105df8 100644 (file)
@@ -2,7 +2,7 @@
 
 use strict;
 use warnings;
-use Test::More tests => 131;
+use Test::More tests => 130;
 use FindBin qw($Bin);
 use lib "$Bin/lib";
 use MemcachedTest;
@@ -52,14 +52,16 @@ ok($slabs_before->{"31:total_pages"} != $slabs_after->{"31:total_pages"},
 ok($slabs_before->{"25:total_pages"} != $slabs_after->{"25:total_pages"},
     "slab 25 pagecount changed");
 
-# Try to move another slab, see that it complains
+# Try to move another slab, see that you can move two in a row
 print $sock "slabs reassign 31 25\r\n";
-like(scalar <$sock>, qr/^NOTFULL/, "Cannot re-run against class with empty space");
+like(scalar <$sock>, qr/^OK/, "Cannot re-run against class with empty space");
 
 # Try to move a page backwards. Should complain that source class isn't "safe"
 # to move from.
-print $sock "slabs reassign 25 31\r\n";
-like(scalar <$sock>, qr/^UNSAFE/, "Cannot move an unsafe slab back");
+# TODO: Wait until the above command completes, then try to move it back?
+# Seems pointless...
+#print $sock "slabs reassign 25 31\r\n";
+#like(scalar <$sock>, qr/^UNSAFE/, "Cannot move an unsafe slab back");
 
 # Try to insert items into both slabs
 print $sock "set bfoo51 0 0 70000\r\n", $bigdata, "\r\n";
index 22c610cbda2563d813b9258db1dfa61ce730491e..7d5d91691341f64ccfd38da9df77df4e165f53c5 100755 (executable)
@@ -6,10 +6,11 @@ our @files;
 BEGIN {
     chdir "$Bin/.." or die;
 
-    my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am);
+    my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am README README.md);
     push(@exempted, glob("doc/*.xml"));
     push(@exempted, glob("doc/xml2rfc/*.xsl"));
     push(@exempted, glob("m4/*backport*m4"));
+    push(@exempted, glob("*.orig"));
     my %exempted_hash = map { $_ => 1 } @exempted;
 
     my @stuff = split /\0/, `git ls-files -z -c -m -o --exclude-standard`;
@@ -29,7 +30,7 @@ BEGIN {
 use Test::More tests => scalar(@files);
 
 foreach my $f (@files) {
-    open(my $fh, $f) or die;
+    open(my $fh, $f) or die "Cannot open file $f: $!";
     my $before = do { local $/; <$fh>; };
     close ($fh);
     my $after = $before;
index aba0b90519b78d9726be67ebaf1a1083ecae4bb8..9faccf4e11cc2fe0e59600a31d82cb490ce2481a 100644 (file)
@@ -382,8 +382,8 @@ static pid_t start_server(in_port_t *port_out, bool daemon, int timeout) {
     if (daemon) {
         /* loop and wait for the pid file.. There is a potential race
          * condition that the server just created the file but isn't
-         * finished writing the content, but I'll take the chance....
-         */
+         * finished writing the content, so we loop a few times
+         * reading as well */
         while (access(pid_file, F_OK) == -1) {
             usleep(10);
         }
@@ -394,7 +394,11 @@ static pid_t start_server(in_port_t *port_out, bool daemon, int timeout) {
                     strerror(errno));
             assert(false);
         }
-        assert(fgets(buffer, sizeof(buffer), fp) != NULL);
+
+        /* Avoid race by retrying 20 times */
+        for (int x = 0; x < 20 && fgets(buffer, sizeof(buffer), fp) == NULL; x++) {
+            usleep(10);
+        }
         fclose(fp);
 
         int32_t val;
index e362249733d47674f39b683898a85da0c880bf38..f4bbe1e78d4e5ed8ff90ca80933239adc7e9fbc6 100644 (file)
@@ -88,7 +88,7 @@ unsigned short refcount_incr(unsigned short *refcount) {
     mutex_lock(&atomics_mutex);
     (*refcount)++;
     res = *refcount;
-    pthread_mutex_unlock(&atomics_mutex);
+    mutex_unlock(&atomics_mutex);
     return res;
 #endif
 }
@@ -103,7 +103,7 @@ unsigned short refcount_decr(unsigned short *refcount) {
     mutex_lock(&atomics_mutex);
     (*refcount)--;
     res = *refcount;
-    pthread_mutex_unlock(&atomics_mutex);
+    mutex_unlock(&atomics_mutex);
     return res;
 #endif
 }
@@ -113,7 +113,7 @@ void item_lock(uint32_t hv) {
 }
 
 void item_unlock(uint32_t hv) {
-    pthread_mutex_unlock(&item_locks[hv & item_lock_mask]);
+    mutex_unlock(&item_locks[hv & item_lock_mask]);
 }
 
 /*
@@ -299,9 +299,6 @@ static void *worker_libevent(void *arg) {
 }
 
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
 /*
  * Processes an incoming "handle a new connection" item. This is called when
  * input arrives on the libevent wakeup pipe.
@@ -508,7 +505,7 @@ enum store_item_type store_item(item *item, int comm, conn* c) {
 void item_flush_expired() {
     mutex_lock(&cache_lock);
     do_item_flush_expired();
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 /*
@@ -519,7 +516,7 @@ char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int
 
     mutex_lock(&cache_lock);
     ret = do_item_cachedump(slabs_clsid, limit, bytes);
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
     return ret;
 }
 
@@ -529,7 +526,7 @@ char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int
 void  item_stats(ADD_STAT add_stats, void *c) {
     mutex_lock(&cache_lock);
     do_item_stats(add_stats, c);
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 /*
@@ -538,7 +535,7 @@ void  item_stats(ADD_STAT add_stats, void *c) {
 void  item_stats_sizes(ADD_STAT add_stats, void *c) {
     mutex_lock(&cache_lock);
     do_item_stats_sizes(add_stats, c);
-    pthread_mutex_unlock(&cache_lock);
+    mutex_unlock(&cache_lock);
 }
 
 /******************************* GLOBAL STATS ******************************/
@@ -658,9 +655,6 @@ void slab_stats_aggregate(struct thread_stats *stats, struct slab_stats *out) {
     }
 }
 
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#endif
 /*
  * Initializes the thread subsystem, creating various worker threads.
  *
index d92e6212b8846d38d6401b73dd34b1b241c9a6b3..ee1605c52900e915aaafdb5c0649eca3fa19c166 100644 (file)
@@ -1,4 +1,4 @@
-#include "memcached.h"
+#include <config.h>
 
 #include <stdio.h>
 #include <assert.h>
@@ -8,6 +8,8 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
+#include "memcached.h"
+
 /* Avoid warnings on solaris, where isspace() is an index into an array, and gcc uses signed chars */
 #define xisspace(c) isspace((unsigned char)c)
 
diff --git a/memcached/version.m4 b/memcached/version.m4
deleted file mode 100644 (file)
index 5914292..0000000
+++ /dev/null
@@ -1 +0,0 @@
-m4_define([VERSION_NUMBER], [1.4.13])