Skip to content

Commit 7dca8e4

Browse files
hnlzq163adutra
andcommitted
JAVA-2910: Add a configuration option to support strong values for prepared statements cache
Co-authored-by: Alexandre Dutra <[email protected]>
1 parent 9f4939c commit 7dca8e4

File tree

6 files changed

+101
-3
lines changed

6 files changed

+101
-3
lines changed

changelog/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
<!-- Note: contrary to 3.x, insert new entries *first* in their section -->
44

5-
### 4.11.1
5+
### 4.11.1 (in progress)
66

7+
- [bug] JAVA-2910: Add a configuration option to support strong values for prepared statements cache
78
- [bug] JAVA-2936: Support Protocol V6
89
- [bug] JAVA-2934: Handle empty non-final pages in ReactiveResultSetSubscription
910

core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,13 @@ public enum DefaultDriverOption implements DriverOption {
902902
* <p>Value-type: List of {@link java.time.Duration Duration}
903903
*/
904904
METRICS_NODE_CQL_MESSAGES_SLO("advanced.metrics.node.cql-messages.slo"),
905+
906+
/**
907+
* Whether the prepared statements cache use weak values.
908+
*
909+
* <p>Value-type: boolean
910+
*/
911+
PREPARED_CACHE_WEAK_VALUES("advanced.prepared-statements.prepared-cache.weak-values"),
905912
;
906913

907914
private final String path;

core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ public String toString() {
521521
/** The request timeout when repreparing. */
522522
public static final TypedDriverOption<Duration> REPREPARE_TIMEOUT =
523523
new TypedDriverOption<>(DefaultDriverOption.REPREPARE_TIMEOUT, GenericType.DURATION);
524+
/** Whether the prepared statements cache use weak values. */
525+
public static final TypedDriverOption<Boolean> PREPARED_CACHE_WEAK_VALUES =
526+
new TypedDriverOption<>(DefaultDriverOption.PREPARED_CACHE_WEAK_VALUES, GenericType.BOOLEAN);
524527
/** The number of threads in the I/O group. */
525528
public static final TypedDriverOption<Integer> NETTY_IO_SIZE =
526529
new TypedDriverOption<>(DefaultDriverOption.NETTY_IO_SIZE, GenericType.INTEGER);

core/src/main/java/com/datastax/oss/driver/internal/core/session/PoolManager.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ public class PoolManager implements AsyncAutoCloseable {
8282
// (e.g. DefaultPreparedStatement) which are handled at the protocol level (e.g.
8383
// CqlPrepareAsyncProcessor). We keep the two separate to avoid introducing a dependency from the
8484
// session to a particular processor implementation.
85-
private final ConcurrentMap<ByteBuffer, RepreparePayload> repreparePayloads =
86-
new MapMaker().weakValues().makeMap();
85+
private final ConcurrentMap<ByteBuffer, RepreparePayload> repreparePayloads;
8786

8887
private final String logPrefix;
8988
private final EventExecutor adminExecutor;
@@ -95,6 +94,14 @@ public PoolManager(InternalDriverContext context) {
9594
this.adminExecutor = context.getNettyOptions().adminEventExecutorGroup().next();
9695
this.config = context.getConfig().getDefaultProfile();
9796
this.singleThreaded = new SingleThreaded(context);
97+
98+
if (config.getBoolean(DefaultDriverOption.PREPARED_CACHE_WEAK_VALUES, true)) {
99+
LOG.debug("[{}] Prepared statements cache configured to use weak values", logPrefix);
100+
this.repreparePayloads = new MapMaker().weakValues().makeMap();
101+
} else {
102+
LOG.debug("[{}] Prepared statements cache configured to use strong values", logPrefix);
103+
this.repreparePayloads = new MapMaker().makeMap();
104+
}
98105
}
99106

100107
public CompletionStage<Void> init(CqlIdentifier keyspace) {

core/src/main/resources/reference.conf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,18 @@ datastax-java-driver {
21612161
# Overridable in a profile: no
21622162
timeout = ${datastax-java-driver.advanced.connection.init-query-timeout}
21632163
}
2164+
2165+
# How to build the cache of prepared statements.
2166+
prepared-cache {
2167+
# Whether to use weak references for the prepared statements cache values.
2168+
#
2169+
# If this option is absent, weak references will be used.
2170+
#
2171+
# Required: no
2172+
# Modifiable at runtime: no
2173+
# Overridable in a profile: no
2174+
// weak-values = true
2175+
}
21642176
}
21652177

21662178
# Options related to the Netty event loop groups used internally by the driver.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright DataStax, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.oss.driver.internal.core.session;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.mockito.Mockito.when;
20+
21+
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
22+
import com.datastax.oss.driver.api.core.config.DriverConfig;
23+
import com.datastax.oss.driver.api.core.config.DriverExecutionProfile;
24+
import com.datastax.oss.driver.internal.core.context.EventBus;
25+
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
26+
import com.datastax.oss.driver.internal.core.context.NettyOptions;
27+
import io.netty.channel.DefaultEventLoopGroup;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
import org.mockito.Mock;
32+
import org.mockito.MockitoAnnotations;
33+
34+
public class PoolManagerTest {
35+
@Mock private InternalDriverContext context;
36+
@Mock private NettyOptions nettyOptions;
37+
@Mock private DriverConfig config;
38+
@Mock private DriverExecutionProfile defaultProfile;
39+
40+
@Before
41+
public void setup() {
42+
MockitoAnnotations.initMocks(this);
43+
44+
DefaultEventLoopGroup adminEventLoopGroup = new DefaultEventLoopGroup(1);
45+
when(nettyOptions.adminEventExecutorGroup()).thenReturn(adminEventLoopGroup);
46+
when(context.getNettyOptions()).thenReturn(nettyOptions);
47+
when(context.getEventBus()).thenReturn(new EventBus("test"));
48+
when(config.getDefaultProfile()).thenReturn(defaultProfile);
49+
when(context.getConfig()).thenReturn(config);
50+
}
51+
52+
@Test
53+
public void should_use_weak_values_if_config_is_true_or_undefined() {
54+
when(defaultProfile.getBoolean(DefaultDriverOption.PREPARED_CACHE_WEAK_VALUES, true))
55+
.thenReturn(true);
56+
// As weak values map class is MapMakerInternalMap
57+
assertThat(new PoolManager(context).getRepreparePayloads())
58+
.isNotInstanceOf(ConcurrentHashMap.class);
59+
}
60+
61+
@Test
62+
public void should_not_use_weak_values_if_config_is_false() {
63+
when(defaultProfile.getBoolean(DefaultDriverOption.PREPARED_CACHE_WEAK_VALUES, true))
64+
.thenReturn(false);
65+
assertThat(new PoolManager(context).getRepreparePayloads())
66+
.isInstanceOf(ConcurrentHashMap.class);
67+
}
68+
}

0 commit comments

Comments
 (0)