Skip to content

Commit 083f236

Browse files
authored
IGNITE-25613 Cache storage path added to ClientCacheConfiguration (#12139)
1 parent da91e49 commit 083f236

File tree

10 files changed

+359
-5
lines changed

10 files changed

+359
-5
lines changed

modules/compatibility/src/test/java/org/apache/ignite/compatibility/clients/AbstractClientCompatibilityTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public abstract class AbstractClientCompatibilityTest extends IgniteCompatibilit
7878
/** Version 2.15.0. */
7979
protected static final IgniteProductVersion VER_2_15_0 = IgniteProductVersion.fromString("2.15.0");
8080

81+
/** Version 2.18.0. */
82+
protected static final IgniteProductVersion VER_2_18_0 = IgniteProductVersion.fromString("2.18.0");
83+
8184
/** Parameters. */
8285
@Parameterized.Parameters(name = "Version {0}")
8386
public static Iterable<Object[]> versions() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.compatibility.clients;
19+
20+
import java.io.File;
21+
import java.util.Arrays;
22+
import java.util.stream.IntStream;
23+
import org.apache.ignite.Ignition;
24+
import org.apache.ignite.client.ClientCache;
25+
import org.apache.ignite.client.ClientCacheConfiguration;
26+
import org.apache.ignite.client.IgniteClient;
27+
import org.apache.ignite.cluster.ClusterState;
28+
import org.apache.ignite.configuration.CacheConfiguration;
29+
import org.apache.ignite.configuration.ClientConfiguration;
30+
import org.apache.ignite.configuration.DataRegionConfiguration;
31+
import org.apache.ignite.configuration.DataStorageConfiguration;
32+
import org.apache.ignite.configuration.IgniteConfiguration;
33+
import org.apache.ignite.internal.util.typedef.internal.U;
34+
import org.apache.ignite.lang.IgniteProductVersion;
35+
import org.junit.Assume;
36+
37+
import static org.apache.ignite.compatibility.clients.JavaThinCompatibilityTest.ADDR;
38+
import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
39+
40+
/**
41+
* Tests java thin client compatibility. This test only checks that thin client can perform basic operations with
42+
* different client and server versions. Whole API not checked, corner cases not checked.
43+
*/
44+
public class JavaThinCompatibilityStoragePathTest extends AbstractClientCompatibilityTest {
45+
/** */
46+
private static final String[] STORAGE_PATH = {"two", "three"};
47+
48+
/** {@inheritDoc} */
49+
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
50+
return super.getConfiguration(igniteInstanceName)
51+
.setPeerClassLoadingEnabled(false)
52+
.setCacheConfiguration(new CacheConfiguration<>("nodeCache").setIndexPath("one").setStoragePaths(STORAGE_PATH))
53+
.setDataStorageConfiguration(new DataStorageConfiguration()
54+
.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setPersistenceEnabled(true))
55+
.setExtraStoragePaths("one", "two", "three"));
56+
}
57+
58+
/** {@inheritDoc} */
59+
@Override protected void processRemoteConfiguration(IgniteConfiguration cfg) {
60+
super.processRemoteConfiguration(cfg);
61+
62+
cfg.setCacheConfiguration(new CacheConfiguration<>("nodeCache"))
63+
.setDataStorageConfiguration(new DataStorageConfiguration()
64+
.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setPersistenceEnabled(true)));
65+
}
66+
67+
/** {@inheritDoc} */
68+
@Override protected void afterTest() throws Exception {
69+
U.delete(new File(U.defaultWorkDirectory()));
70+
super.afterTest();
71+
}
72+
73+
/** {@inheritDoc} */
74+
@Override public void testOldClientToCurrentServer() throws Exception {
75+
Assume.assumeTrue("Cluster state API exists only from 2.9.0 release", ver.compareTo(VER_2_9_0) >= 0);
76+
77+
super.testOldClientToCurrentServer();
78+
}
79+
80+
/** {@inheritDoc} */
81+
@Override public void testCurrentClientToOldServer() throws Exception {
82+
Assume.assumeTrue("Cluster state API exists only from 2.9.0 release", ver.compareTo(VER_2_9_0) >= 0);
83+
84+
super.testCurrentClientToOldServer();
85+
}
86+
87+
88+
/** {@inheritDoc} */
89+
@Override protected void testClient(IgniteProductVersion clientVer, IgniteProductVersion serverVer) throws Exception {
90+
try (IgniteClient cli = Ignition.startClient(new ClientConfiguration().setAddresses(ADDR))) {
91+
boolean storagePathSupportedBySrv = serverVer.compareTo(VER_2_18_0) >= 0;
92+
boolean storagePathSupportedByClient = clientVer.compareTo(VER_2_18_0) >= 0;
93+
94+
cli.cluster().state(ClusterState.ACTIVE);
95+
96+
doTestClientCache(cli, storagePathSupportedByClient, storagePathSupportedBySrv);
97+
doTestNodeCache(cli, storagePathSupportedByClient, storagePathSupportedBySrv);
98+
}
99+
}
100+
101+
/** */
102+
private void doTestNodeCache(IgniteClient cli, boolean storagePathSupportedByClient, boolean storagePathSupportedBySrv) {
103+
ClientCache<Object, Object> cache = cli.cache("nodeCache");
104+
105+
IntStream.range(0, 100).forEach(i -> cache.put(i, i));
106+
107+
ClientCacheConfiguration ccfg = cache.getConfiguration();
108+
109+
assertEquals("Must be able to receive config from server", "nodeCache", ccfg.getName());
110+
111+
checkConfig(storagePathSupportedByClient, storagePathSupportedBySrv, ccfg);
112+
}
113+
114+
/** */
115+
private void doTestClientCache(IgniteClient cli, boolean storagePathSupportedByClient, boolean storagePathSupportedBySrv) {
116+
ClientCacheConfiguration ccfg = new ClientCacheConfiguration().setName("clientCache");
117+
118+
if (storagePathSupportedByClient) {
119+
ccfg.setIndexPath("one")
120+
.setStoragePaths(STORAGE_PATH);
121+
122+
if (!storagePathSupportedBySrv) {
123+
assertThrows(null, () -> cli.createCache(ccfg), RuntimeException.class, "Cache storages are not supported by the server");
124+
125+
ccfg.setStoragePaths((String[])null);
126+
ccfg.setIndexPath(null);
127+
}
128+
}
129+
130+
ClientCache<Object, Object> cliCache = cli.createCache(ccfg);
131+
132+
IntStream.range(0, 100).forEach(i -> cliCache.put(i, i));
133+
134+
ClientCacheConfiguration cfg = cliCache.getConfiguration();
135+
136+
checkConfig(storagePathSupportedByClient, storagePathSupportedBySrv, cfg);
137+
}
138+
139+
/** */
140+
private static void checkConfig(
141+
boolean storagePathSupportedByClient,
142+
boolean storagePathSupportedBySrv,
143+
ClientCacheConfiguration ccfg
144+
) {
145+
if (!storagePathSupportedByClient)
146+
return;
147+
148+
if (storagePathSupportedBySrv) {
149+
assertEquals("one", ccfg.getIndexPath());
150+
assertTrue(Arrays.compare(STORAGE_PATH, ccfg.getStoragePaths()) == 0);
151+
}
152+
else {
153+
assertNull(ccfg.getStoragePaths());
154+
assertNull(ccfg.getIndexPath());
155+
}
156+
}
157+
}

modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/PersistenceBasicCompatibilityTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ public static Collection<Object[]> parameters() {
8585
new DataRegionConfiguration()
8686
.setPersistenceEnabled(true)
8787
.setMaxSize(DataStorageConfiguration.DFLT_DATA_REGION_INITIAL_SIZE)
88-
));
88+
)
89+
.setExtraStoragePaths("one", "two", "three"));
8990

9091
cfg.setBinaryConfiguration(
9192
new BinaryConfiguration()

modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.ignite.compatibility.testsuites;
1919

20+
import org.apache.ignite.compatibility.clients.JavaThinCompatibilityStoragePathTest;
2021
import org.apache.ignite.compatibility.clients.JavaThinCompatibilityTest;
2122
import org.apache.ignite.compatibility.clients.JdbcThinCompatibilityTest;
2223
import org.apache.ignite.compatibility.persistence.CompoundIndexCompatibilityTest;
@@ -46,6 +47,7 @@
4647
MoveBinaryMetadataCompatibility.class,
4748
JdbcThinCompatibilityTest.class,
4849
JavaThinCompatibilityTest.class,
50+
JavaThinCompatibilityStoragePathTest.class,
4951
IgnitePKIndexesMigrationToUnwrapPkTest.class,
5052
CompoundIndexCompatibilityTest.class,
5153
SnapshotCompatibilityTest.class

modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
import org.apache.ignite.cache.PartitionLossPolicy;
2828
import org.apache.ignite.cache.QueryEntity;
2929
import org.apache.ignite.configuration.CacheConfiguration;
30+
import org.apache.ignite.configuration.DataStorageConfiguration;
3031
import org.apache.ignite.configuration.IgniteConfiguration;
3132
import org.apache.ignite.internal.util.typedef.internal.S;
33+
import org.apache.ignite.lang.IgniteExperimental;
34+
import org.jetbrains.annotations.Nullable;
3235

3336
/** Cache configuration. */
3437
public final class ClientCacheConfiguration implements Serializable {
@@ -128,6 +131,24 @@ public final class ClientCacheConfiguration implements Serializable {
128131
/** @serial Expiry policy. */
129132
private ExpiryPolicy expiryPlc;
130133

134+
/**
135+
* Root directories where partition files are stored.
136+
* @see DataStorageConfiguration#setStoragePath(String)
137+
* @see DataStorageConfiguration#setExtraStoragePaths(String[])
138+
* @see CacheConfiguration#setStoragePaths(String...)
139+
*/
140+
@IgniteExperimental
141+
@Nullable private String[] storagePaths;
142+
143+
/**
144+
* Root directory where index file are stored.
145+
* @see DataStorageConfiguration#setStoragePath(String)
146+
* @see DataStorageConfiguration#setExtraStoragePaths(String[])
147+
* @see CacheConfiguration#setIndexPath(String)
148+
*/
149+
@IgniteExperimental
150+
@Nullable private String idxPath;
151+
131152
/** Default constructor. */
132153
public ClientCacheConfiguration() {
133154
// No-op.
@@ -170,6 +191,8 @@ public ClientCacheConfiguration(ClientCacheConfiguration ccfg) {
170191
sqlSchema = ccfg.getSqlSchema();
171192
statisticsEnabled = ccfg.isStatisticsEnabled();
172193
writeSynchronizationMode = ccfg.getWriteSynchronizationMode();
194+
storagePaths = ccfg.getStoragePaths();
195+
idxPath = ccfg.getIndexPath();
173196
}
174197

175198
/**
@@ -770,6 +793,50 @@ public ClientCacheConfiguration setExpiryPolicy(ExpiryPolicy expiryPlc) {
770793
return this;
771794
}
772795

796+
/**
797+
* @return A path to the root directory where the Persistent Store for cache group will persist data and indexes.
798+
*/
799+
@IgniteExperimental
800+
@Nullable public String[] getStoragePaths() {
801+
return storagePaths;
802+
}
803+
804+
/**
805+
* Sets a path to the root directory where the Persistent Store will persist data.
806+
* By default, the Persistent Store's files are located under {@link DataStorageConfiguration#getStoragePath()}.
807+
*
808+
* @param storagePaths Persistence store path.
809+
* @return {@code this} for chaining.
810+
*/
811+
@IgniteExperimental
812+
public ClientCacheConfiguration setStoragePaths(String... storagePaths) {
813+
this.storagePaths = storagePaths;
814+
815+
return this;
816+
}
817+
818+
/**
819+
* @return A path to the root directory where the Persistent Store for cache group will persist index.
820+
*/
821+
@IgniteExperimental
822+
@Nullable public String getIndexPath() {
823+
return idxPath;
824+
}
825+
826+
/**
827+
* Sets a path to the root directory where the Persistent Store will persist index partition.
828+
* By default, the Persistent Store's files are located under {@link DataStorageConfiguration#getStoragePath()}.
829+
*
830+
* @param idxPath Index path.
831+
* @return {@code this} for chaining.
832+
*/
833+
@IgniteExperimental
834+
public ClientCacheConfiguration setIndexPath(String idxPath) {
835+
this.idxPath = idxPath;
836+
837+
return this;
838+
}
839+
773840
/** {@inheritDoc} */
774841
@Override public String toString() {
775842
return S.toString(ClientCacheConfiguration.class, this);

modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@
5757
import org.apache.ignite.internal.binary.streams.BinaryInputStream;
5858
import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
5959
import org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicy;
60+
import org.apache.ignite.internal.util.typedef.F;
6061
import org.apache.ignite.internal.util.typedef.T2;
6162
import org.jetbrains.annotations.Nullable;
6263

64+
import static org.apache.ignite.internal.client.thin.ProtocolBitmaskFeature.CACHE_STORAGES;
6365
import static org.apache.ignite.internal.client.thin.ProtocolVersionFeature.EXPIRY_POLICY;
6466
import static org.apache.ignite.internal.client.thin.ProtocolVersionFeature.QUERY_ENTITY_PRECISION_AND_SCALE;
6567
import static org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicy.convertDuration;
@@ -366,6 +368,13 @@ else if (cfg.getExpiryPolicy() != null) {
366368
"version %s, required version %s", protocolCtx.version(), EXPIRY_POLICY.verIntroduced()));
367369
}
368370

371+
if (protocolCtx.isFeatureSupported(CACHE_STORAGES)) {
372+
itemWriter.accept(CfgItem.STORAGE_PATH, w -> w.writeStringArray(cfg.getStoragePaths()));
373+
itemWriter.accept(CfgItem.IDX_PATH, w -> w.writeString(cfg.getIndexPath()));
374+
}
375+
else if (!F.isEmpty(cfg.getStoragePaths()) || !F.isEmpty(cfg.getIndexPath()))
376+
throw new ClientProtocolError("Cache storages are not supported by the server");
377+
369378
writer.writeInt(origPos, out.position() - origPos - 4); // configuration length
370379
writer.writeInt(origPos + 4, propCnt.get()); // properties count
371380
}
@@ -496,7 +505,13 @@ ClientCacheConfiguration cacheConfiguration(BinaryInputStream in, ProtocolContex
496505
.setExpiryPolicy(!protocolCtx.isFeatureSupported(EXPIRY_POLICY) ?
497506
null : reader.readBoolean() ?
498507
new PlatformExpiryPolicy(reader.readLong(), reader.readLong(), reader.readLong()) : null
499-
);
508+
)
509+
.setStoragePaths(!protocolCtx.isFeatureSupported(CACHE_STORAGES)
510+
? null
511+
: reader.readStringArray())
512+
.setIndexPath(!protocolCtx.isFeatureSupported(CACHE_STORAGES)
513+
? null
514+
: reader.readString());
500515
}
501516
}
502517

@@ -765,7 +780,13 @@ private enum CfgItem {
765780
QUERY_ENTITIES(200),
766781

767782
/** Expire policy. */
768-
EXPIRE_POLICY(407);
783+
EXPIRE_POLICY(407),
784+
785+
/** Storage path. */
786+
STORAGE_PATH(408),
787+
788+
/** Index path. */
789+
IDX_PATH(409);
769790

770791
/** Code. */
771792
private final short code;

modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.BitSet;
2121
import java.util.Collection;
2222
import java.util.EnumSet;
23+
import org.apache.ignite.client.ClientCacheConfiguration;
2324
import org.apache.ignite.client.ClientServices;
2425
import org.apache.ignite.cluster.ClusterState;
2526

@@ -87,7 +88,15 @@ public enum ProtocolBitmaskFeature {
8788
TX_AWARE_QUERIES(18),
8889

8990
/** Force deactivation flag. See {@link org.apache.ignite.client.ClientCluster#state(ClusterState, boolean)}. */
90-
FORCE_DEACTIVATION_FLAG(19);
91+
FORCE_DEACTIVATION_FLAG(19),
92+
93+
/**
94+
* Cache storages.
95+
*
96+
* @see ClientCacheConfiguration#setStoragePaths(String...)
97+
* @see ClientCacheConfiguration#setIndexPath(String)
98+
*/
99+
CACHE_STORAGES(20);
91100

92101
/** */
93102
private static final EnumSet<ProtocolBitmaskFeature> ALL_FEATURES_AS_ENUM_SET =

modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.ignite.internal.processors.platform.client;
1919

2020
import java.util.EnumSet;
21+
import org.apache.ignite.client.ClientCacheConfiguration;
2122
import org.apache.ignite.client.ClientServices;
2223
import org.apache.ignite.cluster.ClusterState;
2324
import org.apache.ignite.internal.ThinProtocolFeature;
@@ -85,7 +86,15 @@ public enum ClientBitmaskFeature implements ThinProtocolFeature {
8586
TX_AWARE_QUERIES(18),
8687

8788
/** Force deactivation flag. See {@link org.apache.ignite.client.ClientCluster#state(ClusterState, boolean)}. */
88-
FORCE_DEACTIVATION_FLAG(19);
89+
FORCE_DEACTIVATION_FLAG(19),
90+
91+
/**
92+
* Cache storages.
93+
*
94+
* @see ClientCacheConfiguration#setStoragePaths(String...)
95+
* @see ClientCacheConfiguration#setIndexPath(String)
96+
*/
97+
CACHE_STORAGES(20);
8998

9099
/** */
91100
private static final EnumSet<ClientBitmaskFeature> ALL_FEATURES_AS_ENUM_SET =

0 commit comments

Comments
 (0)