-
Type: Bug
-
Resolution: Done
-
Priority: Major - P3
-
Affects Version/s: 3.0.0
-
Component/s: Write Operations
-
None
-
Environment:Reproduced against server 3.2.11 and 3.4.1.
JDK 1.8.0_121.
Linux Mint and Amazon Linux.
The following test hangs:
import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.MongoClient; import java.util.Collections; import org.testng.annotations.Test; public final class MongoTest { @Test public void testEmptyAndNonemptyListInsertion() { try (MongoClient client = new MongoClient()) { /* * This issue was found while using Jongo, which relies on this deprecated method. See * https://github.com/bguerout/jongo/issues/254 */ @SuppressWarnings("deprecation") DB db = client.getDB("test"); DBCollection collection = db.getCollection("foo"); try { collection.insert(Collections.emptyList()); } catch (final IllegalArgumentException e) { /* * This is "java.lang.IllegalArgumentException: state should be: count". * For the purposes of this demo it's important that we proceed. */ e.printStackTrace(); } /* This call hangs! */ collection.insert(new BasicDBObject()); } } }
The exception associated with the empty insert is:
java.lang.IllegalArgumentException: state should be: count at com.mongodb.assertions.Assertions.isTrueArgument(Assertions.java:99) at com.mongodb.internal.connection.IndexMap$RangeBased.<init>(IndexMap.java:106) at com.mongodb.internal.connection.IndexMap.create(IndexMap.java:52) at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:103) at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:67) at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37) at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168) at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289) at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:118) at com.mongodb.operation.InsertOperation.executeCommandProtocol(InsertOperation.java:76) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:139) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:133) at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:422) at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:413) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:133) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:60) at com.mongodb.Mongo.execute(Mongo.java:845) at com.mongodb.Mongo$2.execute(Mongo.java:828) at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:342) at com.mongodb.DBCollection.insert(DBCollection.java:337) at com.mongodb.DBCollection.insert(DBCollection.java:328) at com.mongodb.DBCollection.insert(DBCollection.java:298) at com.mongodb.DBCollection.insert(DBCollection.java:264) at com.mongodb.DBCollection.insert(DBCollection.java:248) at com.exampe.MongoTest.testEmptyAndNonemptyListInsertion(MongoTest.java:22)
(I'd argue that an empty insert should just be a NO-OP, but I noticed that MongoCollection#insertMany also throws an IllegalArgumentException on empty input. At the very least the documentation should be clearer on this point. But this is not the primary topic of this ticket.)
The second insertion hangs indefinitely. Associated jstack thread dump:
"pool-1-thread-1" #12 prio=5 os_prio=0 tid=0x00007f96807bb000 nid=0x61a3 waiting on condition [0x00007f96663ac000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076d293b28> (a java.util.concurrent.CountDownLatch$Sync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231) at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:252) at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:96) at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:440) at com.mongodb.connection.WriteCommandProtocol.receiveMessage(WriteCommandProtocol.java:262) at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:104) at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:67) at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37) at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168) at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289) at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:118) at com.mongodb.operation.InsertOperation.executeCommandProtocol(InsertOperation.java:76) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:139) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:133) at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:422) at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:413) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:133) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:60) at com.mongodb.Mongo.execute(Mongo.java:845) at com.mongodb.Mongo$2.execute(Mongo.java:828) at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:342) at com.mongodb.DBCollection.insert(DBCollection.java:337) at com.mongodb.DBCollection.insert(DBCollection.java:328) at com.mongodb.DBCollection.insert(DBCollection.java:298) at com.mongodb.DBCollection.insert(DBCollection.java:264) at com.mongodb.DBCollection.insert(DBCollection.java:201) at com.example.MongoTest.testEmptyAndNonemptyListInsertion(MongoTest.java:32)
This issue looks similar to JAVA-2260, but that ticket lacks the content necessary to be sure (for a non-expert like myself).