fix #95
authorMichael Wallner <mike@php.net>
Tue, 27 Oct 2020 16:36:26 +0000 (17:36 +0100)
committerMichael Wallner <mike@php.net>
Tue, 27 Oct 2020 16:36:26 +0000 (17:36 +0100)
ChangeLog-1.1.md
src/libmemcached/get.cc
test/fixtures/callbacks.hpp
test/lib/ReturnMatcher.cpp
test/lib/ReturnMatcher.hpp
test/tests/memcached/callbacks.cpp

index 46540555ac26edde426dfab511e70ab3fa24e213..6cd72b1f06f1c33a1e1fe9560011e74b4166df1a 100644 (file)
@@ -100,6 +100,8 @@ was incremented due to the following changes:
   [gh #64](https://github.com/m6w6/libmemcached/issues/64) and
   [gh #21](https://github.com/m6w6/libmemcached/issues/21):
   clarify documentation on replication.
+* Fix [gh #95](https://github.com/m6w6/libmemcached/issues/95):
+  MEMCACHED_CALLBACK_GET_FAILURE and MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
 
 ---
 
index 93330f450b51a991d049bafa2f23319a73df69db..4dd88061fc682a14a5092cc10ad801fb5cc567e9 100644 (file)
@@ -98,8 +98,12 @@ char *memcached_get_by_key(memcached_st *shell, const char *group_key, size_t gr
 
         if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED) {
           *error = rc;
-          *value_length = memcached_result_length(result_ptr);
-          *flags = memcached_result_flags(result_ptr);
+          if (value_length) {
+            *value_length = memcached_result_length(result_ptr);
+          }
+          if (flags) {
+            *flags = memcached_result_flags(result_ptr);
+          }
           char *result_value = memcached_string_take_value(&result_ptr->value);
           memcached_result_free(result_ptr);
 
@@ -178,7 +182,7 @@ static memcached_return_t __mget_by_key_real(memcached_st *ptr, const char *grou
     if (instance->response_count()) {
       char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
 
-      if (ptr->flags.no_block) {
+      if (ptr->flags.no_block || ptr->flags.buffer_requests) {
         memcached_io_write(instance);
       }
 
index 5e01c4b467c7a72dad03507814de224796264ebb..6ccb4ff8f416e1873334ef243ded79104c450a29 100644 (file)
@@ -49,7 +49,7 @@ static inline memcached_return_t delete_trigger(memcached_st *, const char *, si
   return MEMCACHED_SUCCESS;
 }
 
-static inline memcached_return_t read_through_trigger(memcached_st *, char *, size_t,
+static inline memcached_return_t get_failure(memcached_st *, char *, size_t,
                                                       memcached_result_st *result) {
   return memcached_result_set_value(result, S("updated by read through trigger"));
 }
index cbc9a95bc4607fc0f9e9ee4618c5ebef7bbc94b3..926214e74a829a998e9106e18708af7860c92650 100644 (file)
@@ -1,7 +1,13 @@
 #include "ReturnMatcher.hpp"
 
 bool ReturnMatcher::match(const memcached_return_t &arg) const {
-  return arg == expected;
+  if (arg != expected) {
+    if (expected == MEMCACHED_SUCCESS && arg == MEMCACHED_BUFFERED && memc) {
+      return memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
+    }
+    return false;
+  }
+  return true;
 }
 
 ReturnMatcher ReturnMatcher::success() {
index f50212c4d67d768f1d7ceb78a0a79235cea11667..f95eb2f3ecae9c03324cea0c08e8fa5c86cf11c1 100644 (file)
@@ -19,7 +19,7 @@
 
 class ReturnMatcher : public Catch::MatcherBase<memcached_return_t> {
 public:
-  explicit ReturnMatcher(const memcached_st *memc_,
+  explicit ReturnMatcher(memcached_st *memc_,
                          memcached_return_t expected_ = MEMCACHED_SUCCESS)
   : memc{memc_}
   , expected{expected_} {}
@@ -35,13 +35,13 @@ protected:
   string describe() const override;
 
 private:
-  const memcached_st *memc;
+  memcached_st *memc;
   memcached_return_t expected{MEMCACHED_SUCCESS};
 };
 
 class LoneReturnMatcher {
 public:
   ReturnMatcher returns;
-  explicit LoneReturnMatcher(const memcached_st *memc)
+  explicit LoneReturnMatcher(memcached_st *memc)
   : returns{memc} {}
 };
index 1fc20ef618544606594b8b629b2f6642f5d407c2..625698b6bb7d38e279780946e24357fee7a3bbae 100644 (file)
@@ -30,25 +30,37 @@ TEST_CASE("memcached_callbacks") {
   }
 
   SECTION("get_failure callback") {
-    void *gptr = reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&read_through_trigger));
+    void *gptr = reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&get_failure));
     Malloced empty(memcached_get(memc, S(__func__), nullptr, nullptr, &rc));
     REQUIRE_FALSE(*empty);
     REQUIRE_RC(MEMCACHED_NOTFOUND, rc);
 
-    REQUIRE_SUCCESS(memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, gptr));
-    REQUIRE(gptr == memcached_callback_get(memc, MEMCACHED_CALLBACK_GET_FAILURE, &rc));
-    REQUIRE_SUCCESS(rc);
+    uint64_t buffering = GENERATE(0, 1);
+
+    DYNAMIC_SECTION("buffering: " << buffering) {
+      REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, buffering));
+      REQUIRE_SUCCESS(memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, gptr));
+      REQUIRE(gptr == memcached_callback_get(memc, MEMCACHED_CALLBACK_GET_FAILURE, &rc));
+      REQUIRE_SUCCESS(rc);
 
-    for (int twice = 0; twice < 2; ++twice) {
-      uint32_t flags;
-      size_t len;
-      Malloced val(memcached_get(memc, S(__func__), &len, &flags, &rc));
+      for (int twice = 0; twice < 2; ++twice) {
+        uint32_t flags;
+        size_t len;
+        Malloced val(memcached_get(memc, S(__func__), &len, &flags, &rc));
 
+        REQUIRE_SUCCESS(rc);
+        REQUIRE(string("updated by read through trigger") == string(*val, len));
+        REQUIRE_FALSE((*val)[len]);
+      }
+
+      REQUIRE_SUCCESS(memcached_set(memc, S(__func__), S("changed"), 0, 0));
+      memcached_quit(memc);
+      Malloced val(memcached_get(memc, S(__func__), nullptr, nullptr, &rc));
       REQUIRE_SUCCESS(rc);
-      REQUIRE(string("updated by read through trigger") == string(*val, len));
-      REQUIRE_FALSE((*val)[len]);
+      REQUIRE("changed"s == *val);
     }
   }
+
   SECTION("clone callback") {
     void *cptr = reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&clone_callback));