Skip to content

Commit 3a27dff

Browse files
committed
MLE-26460 Preventing maxDocToUriBatchRatio value of -1
1 parent 1cf5789 commit 3a27dff

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/datamovement/impl/DataMovementServices.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ QueryConfig initConfig(String method, SearchQueryDefinition qdef) {
7171
logger.debug("initialized maxDocToUriBatchRatio to : {}", maxDocToUriBatchRatio);
7272
}
7373

74+
// Per GitHub bug 1872 and MLE-26460, the server may return -1 when there are fewer server threads than forests.
75+
// A value of -1 will cause later problems when constructing a LinkedBlockingQueue with a negative capacity.
76+
// So defaulting this to 1 to avoid later errors.
77+
if (maxDocToUriBatchRatio <= 0) {
78+
maxDocToUriBatchRatio = 1;
79+
}
80+
7481
JsonNode defaultDocBatchSizeNode = result.get("defaultDocBatchSize");
7582
int defaultDocBatchSize = -1;
7683
if (defaultDocBatchSizeNode != null && defaultDocBatchSizeNode.isInt()) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3+
*/
4+
package com.marklogic.client.datamovement;
5+
6+
import com.fasterxml.jackson.databind.node.ObjectNode;
7+
import com.marklogic.client.DatabaseClient;
8+
import com.marklogic.client.test.AbstractClientTest;
9+
import com.marklogic.client.test.Common;
10+
import com.marklogic.mgmt.ManageClient;
11+
import com.marklogic.mgmt.resource.appservers.ServerManager;
12+
import org.junit.jupiter.api.Test;
13+
14+
import java.util.concurrent.atomic.AtomicInteger;
15+
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
18+
class FewerServerThreadsThanForestsTest extends AbstractClientTest {
19+
20+
@Test
21+
void test() {
22+
DatabaseClient client = Common.newClient();
23+
final int forestCount = client.newDataMovementManager().readForestConfig().listForests().length;
24+
if (forestCount < 2) {
25+
logger.info("This test requires multiple forests so that the server thread count can be set to the " +
26+
"number of forests minus one; skipping test");
27+
return;
28+
}
29+
30+
adjustServerThreads(forestCount - 1);
31+
try {
32+
DataMovementManager dmm = client.newDataMovementManager();
33+
AtomicInteger uriCount = new AtomicInteger();
34+
QueryBatcher queryBatcher = dmm.newQueryBatcher(client.newQueryManager().newStructuredQueryBuilder().collection("/optic/test"))
35+
.withThreadCount(1)
36+
.onUrisReady(batch -> uriCount.addAndGet(batch.getItems().length));
37+
dmm.startJob(queryBatcher);
38+
queryBatcher.awaitCompletion();
39+
dmm.stopJob(queryBatcher);
40+
41+
assertEquals(4, uriCount.get(), "Verifies that the 4 test documents were found, and more importantly, " +
42+
"that the new default maxDocToUriBatchRatio of 1 was applied correctly when the number of " +
43+
"server threads is less than the number of forests. This is for bug 1872 in GitHub. Prior to this " +
44+
"fix, the maxDocToUriBatchRatio of -1 returned by the server caused an error when the " +
45+
"LinkedBlockingQueue was constructed with a negative capacity.");
46+
} finally {
47+
// We can safely use this number because we know the test-app doesn't change this.
48+
final int defaultServerThreadCount = 32;
49+
adjustServerThreads(defaultServerThreadCount);
50+
}
51+
}
52+
53+
private void adjustServerThreads(final int threads) {
54+
logger.info("Adjusting server threads to {}", threads);
55+
Common.newAdminManager().invokeActionRequiringRestart(() -> {
56+
ManageClient manageClient = Common.newManageClient();
57+
ObjectNode payload = Common.newServerPayload().put("threads", threads);
58+
new ServerManager(manageClient).save(payload.toString());
59+
return true;
60+
});
61+
}
62+
}

marklogic-client-api/src/test/java/com/marklogic/client/test/Common.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
2+
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
33
*/
44
package com.marklogic.client.test;
55

@@ -13,6 +13,8 @@
1313
import com.marklogic.client.io.DocumentMetadataHandle;
1414
import com.marklogic.mgmt.ManageClient;
1515
import com.marklogic.mgmt.ManageConfig;
16+
import com.marklogic.mgmt.admin.AdminConfig;
17+
import com.marklogic.mgmt.admin.AdminManager;
1618
import org.springframework.util.FileCopyUtils;
1719
import org.w3c.dom.DOMException;
1820
import org.w3c.dom.Document;
@@ -258,6 +260,10 @@ public static ManageClient newManageClient() {
258260
return new ManageClient(new ManageConfig(HOST, 8002, SERVER_ADMIN_USER, SERVER_ADMIN_PASS));
259261
}
260262

263+
public static AdminManager newAdminManager() {
264+
return new AdminManager(new AdminConfig(HOST, 8001, SERVER_ADMIN_USER, SERVER_ADMIN_PASS));
265+
}
266+
261267
public static ObjectNode newServerPayload() {
262268
ObjectNode payload = new ObjectMapper().createObjectNode();
263269
payload.put("server-name", SERVER_NAME);

0 commit comments

Comments
 (0)