You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by rg...@apache.org on 2015/09/27 04:25:17 UTC

svn commit: r1705505 - in /zookeeper/branches/branch-3.4: CHANGES.txt src/c/src/zookeeper.c src/c/tests/TestOperations.cc

Author: rgs
Date: Sun Sep 27 02:25:16 2015
New Revision: 1705505

URL: http://svn.apache.org/viewvc?rev=1705505&view=rev
Log:
ZOOKEEPER-2253: C asserts ordering of ping requests, while Java client does not
(Chris Chen via rgs)

Modified:
    zookeeper/branches/branch-3.4/CHANGES.txt
    zookeeper/branches/branch-3.4/src/c/src/zookeeper.c
    zookeeper/branches/branch-3.4/src/c/tests/TestOperations.cc

Modified: zookeeper/branches/branch-3.4/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/CHANGES.txt?rev=1705505&r1=1705504&r2=1705505&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/CHANGES.txt (original)
+++ zookeeper/branches/branch-3.4/CHANGES.txt Sun Sep 27 02:25:16 2015
@@ -126,6 +126,9 @@ BUGFIXES:
   ZOOKEEPER-1803: Add description for pzxid in programmer's guide
   (Arshad Mohammad via rakeshr)
 
+  ZOOKEEPER-2253: C asserts ordering of ping requests, while Java client does not
+  (Chris Chen via rgs)
+
 IMPROVEMENTS:
 
   ZOOKEEPER-1575. adding .gitattributes to prevent CRLF and LF mismatches for

Modified: zookeeper/branches/branch-3.4/src/c/src/zookeeper.c
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/c/src/zookeeper.c?rev=1705505&r1=1705504&r2=1705505&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/src/c/src/zookeeper.c (original)
+++ zookeeper/branches/branch-3.4/src/c/src/zookeeper.c Sun Sep 27 02:25:16 2015
@@ -1167,25 +1167,20 @@ void free_completions(zhandle_t *zh,int
             zh->outstanding_sync--;
             destroy_completion_entry(cptr);
         } else if (callCompletion) {
-            if(cptr->xid == PING_XID){
-                // Nothing to do with a ping response
-                destroy_completion_entry(cptr);
-            } else {
-                // Fake the response
-                buffer_list_t *bptr;
-                h.xid = cptr->xid;
-                h.zxid = -1;
-                h.err = reason;
-                oa = create_buffer_oarchive();
-                serialize_ReplyHeader(oa, "header", &h);
-                bptr = calloc(sizeof(*bptr), 1);
-                assert(bptr);
-                bptr->len = get_buffer_len(oa);
-                bptr->buffer = get_buffer(oa);
-                close_buffer_oarchive(&oa, 0);
-                cptr->buffer = bptr;
-                queue_completion(&zh->completions_to_process, cptr, 0);
-            }
+            // Fake the response
+            buffer_list_t *bptr;
+            h.xid = cptr->xid;
+            h.zxid = -1;
+            h.err = reason;
+            oa = create_buffer_oarchive();
+            serialize_ReplyHeader(oa, "header", &h);
+            bptr = calloc(sizeof(*bptr), 1);
+            assert(bptr);
+            bptr->len = get_buffer_len(oa);
+            bptr->buffer = get_buffer(oa);
+            close_buffer_oarchive(&oa, 0);
+            cptr->buffer = bptr;
+            queue_completion(&zh->completions_to_process, cptr, 0);
         }
     }
     a_list.completion = NULL;
@@ -1526,7 +1521,6 @@ static struct timeval get_timeval(int in
     rc = serialize_RequestHeader(oa, "header", &h);
     enter_critical(zh);
     gettimeofday(&zh->last_ping, 0);
-    rc = rc < 0 ? rc : add_void_completion(zh, h.xid, 0, 0);
     rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
             get_buffer_len(oa));
     leave_critical(zh);
@@ -2079,12 +2073,8 @@ static void deserialize_response(int typ
     case COMPLETION_VOID:
         LOG_DEBUG(("Calling COMPLETION_VOID for xid=%#x failed=%d rc=%d",
                     cptr->xid, failed, rc));
-        if (xid == PING_XID) {
-            // We want to skip the ping
-        } else {
-            assert(cptr->c.void_result);
-            cptr->c.void_result(rc, cptr->data);
-        }
+        assert(cptr->c.void_result);
+        cptr->c.void_result(rc, cptr->data);
         break;
     case COMPLETION_MULTI:
         LOG_DEBUG(("Calling COMPLETION_MULTI for xid=%#x failed=%d rc=%d",
@@ -2200,7 +2190,15 @@ int zookeeper_process(zhandle_t *zh, int
             // fprintf(stderr, "Got %#x for %#x\n", hdr.zxid, hdr.xid);
         }
 
-        if (hdr.xid == WATCHER_EVENT_XID) {
+        if (hdr.xid == PING_XID) {
+            // Ping replies can arrive out-of-order
+            int elapsed = 0;
+            struct timeval now;
+            gettimeofday(&now, 0);
+            elapsed = calculate_interval(&zh->last_ping, &now);
+            LOG_DEBUG(LOGCALLBACK(zh), "Got ping response in %d ms", elapsed);
+            free_buffer(bptr);
+        } else if (hdr.xid == WATCHER_EVENT_XID) {
             struct WatcherEvent evt;
             int type = 0;
             char *path = NULL;
@@ -2267,22 +2265,9 @@ int zookeeper_process(zhandle_t *zh, int
             activateWatcher(zh, cptr->watcher, rc);
 
             if (cptr->c.void_result != SYNCHRONOUS_MARKER) {
-                if(hdr.xid == PING_XID){
-                    int elapsed = 0;
-                    struct timeval now;
-                    gettimeofday(&now, 0);
-                    elapsed = calculate_interval(&zh->last_ping, &now);
-                    LOG_DEBUG(("Got ping response in %d ms", elapsed));
-
-                    // Nothing to do with a ping response
-                    free_buffer(bptr);
-                    destroy_completion_entry(cptr);
-                } else {
-                    LOG_DEBUG(("Queueing asynchronous response"));
-
-                    cptr->buffer = bptr;
-                    queue_completion(&zh->completions_to_process, cptr, 0);
-                }
+                LOG_DEBUG(LOGCALLBACK(zh), "Queueing asynchronous response");
+                cptr->buffer = bptr;
+                queue_completion(&zh->completions_to_process, cptr, 0);
             } else {
                 struct sync_completion
                         *sc = (struct sync_completion*)cptr->data;

Modified: zookeeper/branches/branch-3.4/src/c/tests/TestOperations.cc
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/c/tests/TestOperations.cc?rev=1705505&r1=1705504&r2=1705505&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/src/c/tests/TestOperations.cc (original)
+++ zookeeper/branches/branch-3.4/src/c/tests/TestOperations.cc Sun Sep 27 02:25:16 2015
@@ -29,6 +29,7 @@ class Zookeeper_operations : public CPPU
     CPPUNIT_TEST_SUITE(Zookeeper_operations);
 #ifndef THREADED
     CPPUNIT_TEST(testPing);
+    CPPUNIT_TEST(testUnsolicitedPing);
     CPPUNIT_TEST(testTimeoutCausedByWatches1);
     CPPUNIT_TEST(testTimeoutCausedByWatches2);
 #else    
@@ -305,6 +306,40 @@ public:
         CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
     }
 
+    // ZOOKEEPER-2253: Permit unsolicited pings
+    void testUnsolicitedPing()
+    {
+        const int TIMEOUT=9; // timeout in secs
+        Mock_gettimeofday timeMock;
+        PingCountingServer zkServer;
+        // must call zookeeper_close() while all the mocks are in scope
+        CloseFinally guard(&zh);
+
+        // receive timeout is in milliseconds
+        zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
+        CPPUNIT_ASSERT(zh!=0);
+        // simulate connected state
+        forceConnected(zh);
+
+        int fd=0;
+        int interest=0;
+        timeval tv;
+
+        int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+        CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+        // verify no ping sent
+        CPPUNIT_ASSERT(zkServer.pingCount_==0);
+
+        // we're going to receive a unsolicited PING response; ensure
+        // that the client has updated its last_recv timestamp
+        timeMock.tick(tv);
+        zkServer.addRecvResponse(new PingResponse);
+        rc=zookeeper_process(zh,interest);
+        CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+        CPPUNIT_ASSERT(timeMock==zh->last_recv);
+    }
+
     // simulate a watch arriving right before a ping is due
     // assert the ping is sent nevertheless
     void testTimeoutCausedByWatches1()