https://issues.shibboleth.net/jira/browse/SSPCPP-225
authorScott Cantor <cantor.2@osu.edu>
Mon, 27 Jul 2009 01:38:48 +0000 (01:38 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 27 Jul 2009 01:38:48 +0000 (01:38 +0000)
memcache-store/memcache-store.cpp

index c6ef7f2..c208108 100644 (file)
@@ -35,6 +35,8 @@
 #endif\r
 \r
 #include <xmltooling/base.h>\r
+\r
+#include <iostream> \r
 #include <libmemcached/memcached.h>\r
 #include <xercesc/util/XMLUniDefs.hpp>\r
 \r
@@ -107,7 +109,7 @@ namespace xmltooling {
     memcached_st *memc;\r
     string m_memcacheHosts;\r
     string m_prefix;\r
-    \r
+    Mutex* m_lock;\r
   };\r
   \r
   class MemcacheStorageService : public StorageService, public MemcacheBase {\r
@@ -158,7 +160,7 @@ bool MemcacheBase::addLock(string what, bool use_prefix) {
   string set_val = "1";\r
   unsigned tries = 5;\r
   while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {\r
-    if (tries-- < 0) {\r
+    if (tries-- == 0) {\r
       log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());\r
       return false;\r
     }\r
@@ -275,7 +277,6 @@ bool MemcacheBase::deleteMemcache(const char *key,
                                   bool use_prefix) {\r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -284,24 +285,25 @@ bool MemcacheBase::deleteMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  memset(&clone, 0 , sizeof(memcached_st));\r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::deleteMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_delete(&clone, (char *)final_key.c_str(), final_key.length(), timeout);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTFOUND) {\r
     // Key wasn't there... No biggie.\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
-    log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     // shouldn't be here\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -313,7 +315,6 @@ bool MemcacheBase::getMemcache(const char *key,
   size_t len;\r
   char *result;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
   \r
   if (use_prefix) {\r
@@ -322,12 +323,10 @@ bool MemcacheBase::getMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  memset(&clone, 0 , sizeof(memcached_st));\r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::getMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
+  m_lock->unlock();\r
 \r
-  result = memcached_get(&clone, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     dest = result;\r
     free(result);\r
@@ -335,12 +334,15 @@ bool MemcacheBase::getMemcache(const char *key,
   } else if (rv == MEMCACHED_NOTFOUND) {\r
     log.debug("Key %s not found in memcache...", key);\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
-    log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -352,7 +354,6 @@ bool MemcacheBase::addMemcache(const char *key,
 \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -361,24 +362,25 @@ bool MemcacheBase::addMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  memset(&clone, 0 , sizeof(memcached_st));\r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::addMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_add(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTSTORED) {\r
     // already there\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -390,7 +392,6 @@ bool MemcacheBase::setMemcache(const char *key,
 \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -399,21 +400,22 @@ bool MemcacheBase::setMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  memset(&clone, 0 , sizeof(memcached_st));\r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::setMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_set(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -425,7 +427,6 @@ bool MemcacheBase::replaceMemcache(const char *key,
   \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -434,24 +435,25 @@ bool MemcacheBase::replaceMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  memset(&clone, 0 , sizeof(memcached_st));\r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::replaceMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_replace(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTSTORED) {\r
     // not there\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -472,6 +474,9 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
   log.debug("INIT: GOT Hosts: %s", h.get());\r
   m_memcacheHosts = h.get();\r
 \r
+  m_lock = Mutex::create();\r
+  log.debug("Lock created");\r
+\r
   memc = memcached_create(NULL);\r
   if (memc == NULL) {\r
     throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");\r
@@ -479,10 +484,23 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
 \r
   log.debug("Memcache created");\r
 \r
-  unsigned int set = MEMCACHED_HASH_CRC;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, set);\r
+  unsigned int hash = MEMCACHED_HASH_CRC;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);\r
   log.debug("CRC hash set");\r
 \r
+  int32_t timeout = 1000000;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout);\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout);\r
+\r
+  int32_t poll_timeout = 1000;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);\r
+\r
+  int32_t fail_limit = 5;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);\r
+\r
+  int32_t retry_timeout = 30;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);\r
+\r
   memcached_server_st *servers;\r
   servers = memcached_servers_parse((char *)m_memcacheHosts.c_str());\r
   log.debug("Got %u hosts.",  memcached_server_list_count(servers));\r
@@ -496,6 +514,7 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
 \r
 MemcacheBase::~MemcacheBase() {\r
   memcached_free(memc);\r
+  delete m_lock;\r
   log.debug("Base object destroyed");\r
 }\r
 \r
@@ -580,6 +599,19 @@ int MemcacheStorageService::readString(const char* context, const char* key, str
   uint32_t rec_version;\r
   string value;\r
 \r
+  if (m_buildMap) {\r
+    log.debug("Checking context");\r
+\r
+    string map_name = context;\r
+    string ser_arr;\r
+    uint32_t flags;\r
+    bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);\r
+\r
+    if (!ctx_found) {\r
+      return 0;\r
+    }\r
+  }\r
+\r
   bool found = getMemcache(final_key.c_str(), value, &rec_version);\r
   if (!found) {\r
     return 0;\r
@@ -661,12 +693,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
   }\r
 \r
   string map_name = context;\r
-  \r
-  if (! addLock(map_name)) {\r
-    log.error("Unable to get lock for context %s!", context);\r
-    return;\r
-  }\r
-  \r
   string ser_arr;\r
   uint32_t flags;\r
   bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
@@ -697,8 +723,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
     replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);\r
   }\r
   \r
-  deleteLock(map_name);\r
-  \r
 }\r
 \r
 void MemcacheStorageService::deleteContext(const char* context) {\r
@@ -711,12 +735,6 @@ void MemcacheStorageService::deleteContext(const char* context) {
   }\r
 \r
   string map_name = context;\r
-  \r
-  if (! addLock(map_name)) {\r
-    log.error("Unable to get lock for context %s!", context);\r
-    return;\r
-  }\r
-  \r
   string ser_arr;\r
   uint32_t flags;\r
   bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
@@ -739,8 +757,6 @@ void MemcacheStorageService::deleteContext(const char* context) {
     deleteMemcache(map_name.c_str(), 0);\r
   }\r
   \r
-  deleteLock(map_name);\r
-\r
 }\r
 \r
 extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {\r