zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sy...@apache.org
Subject [zookeeper] branch branch-3.6 updated: ZOOKEEPER-3895: Client side NullPointerException in case of empty Multi operation
Date Wed, 29 Jul 2020 17:13:06 GMT
This is an automated email from the ASF dual-hosted git repository.

symat pushed a commit to branch branch-3.6
in repository https://gitbox.apache.org/repos/asf/zookeeper.git


The following commit(s) were added to refs/heads/branch-3.6 by this push:
     new 3dbfdf9  ZOOKEEPER-3895: Client side NullPointerException in case of empty Multi
operation
3dbfdf9 is described below

commit 3dbfdf9b4414c79362a7a1426592fd9f082d45d2
Author: Enrico Olivelli <eolivelli@apache.org>
AuthorDate: Wed Jul 29 16:55:45 2020 +0000

    ZOOKEEPER-3895: Client side NullPointerException in case of empty Multi operation
    
    https://issues.apache.org/jira/browse/ZOOKEEPER-3895
    
    Author: Enrico Olivelli <eolivelli@apache.org>
    
    Reviewers: tison <wander4096@gmail.com>, Mate Szalay-Beko <symat@apache.org>
    
    Closes #1407 from eolivelli/fix/ZOOKEEPER-3895
    
    (cherry picked from commit ce523e01938e26ad92d613bd28b59501e9a853df)
    Signed-off-by: Mate Szalay-Beko <symat@apache.org>
---
 .../src/main/java/org/apache/zookeeper/ClientCnxn.java      | 13 +++++++++++++
 .../src/main/java/org/apache/zookeeper/ZooKeeper.java       | 10 ++++++++++
 .../java/org/apache/zookeeper/test/MultiOperationTest.java  |  9 +++++++++
 3 files changed, 32 insertions(+)

diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ClientCnxn.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ClientCnxn.java
index d3d8e85..cebf9a1 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ClientCnxn.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ClientCnxn.java
@@ -30,6 +30,7 @@ import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -475,6 +476,16 @@ public class ClientCnxn {
         return name + suffix;
     }
 
+    /**
+     * Tests that current thread is the main event loop.
+     * This method is useful only for tests inside ZooKeeper project
+     * it is not a public API intended for use by external applications.
+     * @return true if Thread.currentThread() is an EventThread.
+     */
+    public static boolean isInEventThread() {
+        return Thread.currentThread() instanceof EventThread;
+    }
+
     class EventThread extends ZooKeeperThread {
 
         private final LinkedBlockingQueue<Object> waitingEvents = new LinkedBlockingQueue<Object>();
@@ -596,6 +607,8 @@ public class ClientCnxn {
                         ((AsyncCallback.EphemeralsCallback) lcb.cb).processResult(lcb.rc,
lcb.ctx, null);
                     } else if (lcb.cb instanceof AsyncCallback.AllChildrenNumberCallback)
{
                         ((AsyncCallback.AllChildrenNumberCallback) lcb.cb).processResult(lcb.rc,
lcb.path, lcb.ctx, -1);
+                    } else if (lcb.cb instanceof AsyncCallback.MultiCallback) {
+                        ((AsyncCallback.MultiCallback) lcb.cb).processResult(lcb.rc, lcb.path,
lcb.ctx, Collections.emptyList());
                     } else {
                         ((VoidCallback) lcb.cb).processResult(lcb.rc, lcb.path, lcb.ctx);
                     }
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java
index f6f165d..7b53f9a 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java
@@ -24,6 +24,7 @@ import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -2101,6 +2102,11 @@ public class ZooKeeper implements AutoCloseable {
         MultiOperationRecord request,
         MultiCallback cb,
         Object ctx) throws IllegalArgumentException {
+        if (request.size() == 0) {
+            // nothing to do, early exit
+            cnxn.queueCallback(cb, KeeperException.Code.OK.intValue(), null, ctx);
+            return;
+        }
         RequestHeader h = new RequestHeader();
         switch (request.getOpKind()) {
         case TRANSACTION:
@@ -2119,6 +2125,10 @@ public class ZooKeeper implements AutoCloseable {
     protected List<OpResult> multiInternal(
         MultiOperationRecord request) throws InterruptedException, KeeperException, IllegalArgumentException
{
         RequestHeader h = new RequestHeader();
+        if (request.size() == 0) {
+            // nothing to do, early exit
+            return Collections.emptyList();
+        }
         switch (request.getOpKind()) {
         case TRANSACTION:
             h.setType(ZooDefs.OpCode.multi);
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/MultiOperationTest.java
b/zookeeper-server/src/test/java/org/apache/zookeeper/test/MultiOperationTest.java
index 6e23bd6..5dfd73e 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/test/MultiOperationTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/MultiOperationTest.java
@@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.AsyncCallback.MultiCallback;
+import org.apache.zookeeper.ClientCnxn;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Op;
@@ -107,6 +108,9 @@ public class MultiOperationTest extends ClientBase {
             zk.multi(ops, new MultiCallback() {
                 @Override
                 public void processResult(int rc, String path, Object ctx, List<OpResult>
opResults) {
+                    if (!ClientCnxn.isInEventThread()) {
+                        throw new RuntimeException("not in event thread");
+                    }
                     synchronized (res) {
                         res.rc = rc;
                         res.results = opResults;
@@ -443,6 +447,11 @@ public class MultiOperationTest extends ClientBase {
     }
 
     @Test
+    public void testEmpty() throws Exception {
+        multi(zk, Arrays.asList());
+    }
+
+    @Test
     public void testCreateDelete() throws Exception {
 
         multi(zk, Arrays.asList(


Mime
View raw message