Skip to content

Commit 5d7f09a

Browse files
committed
Fixes after review
1 parent d4d45b8 commit 5d7f09a

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,59 @@ class Scratch {
244244
}
245245
```
246246

247+
#### Using custom sharding function
248+
249+
You can use your own sharding function to determine bucket id - location in cluster and use it in cluster operations.
250+
For this purpose you need:
251+
1) hash function
252+
For the example, equality of function from tarantool - [crc32](https://www.tarantool.io/en/doc/latest/reference/reference_lua/digest/#lua-function.digest.crc32) with specific polynomial value.
253+
Java doesn't have crc32 out of the box with the ability to pass polynomial value, then we'll implement our own:
254+
```java
255+
private static long crc32(byte[] data) {
256+
BitSet bitSet = BitSet.valueOf(data);
257+
int crc32 = 0xFFFFFFFF; // initial value
258+
for (int i = 0; i < data.length * 8; i++) {
259+
if (((crc32 >>> 31) & 1) != (bitSet.get(i) ? 1 : 0)) {
260+
crc32 = (crc32 << 1) ^ 0x1EDC6F41; // xor with polynomial
261+
} else {
262+
crc32 = crc32 << 1;
263+
}
264+
}
265+
crc32 = Integer.reverse(crc32); // result reflect
266+
return crc32 & 0x00000000ffffffffL; // the unsigned java problem
267+
}
268+
```
269+
2) number of buckets
270+
We can obtain number from tarantool via `vshard.router.bucket_count` function out of [vshard module](https://github.com/tarantool/vshard)
271+
```java
272+
public static <T extends Packable, R extends Collection<T>> Integer getBucketCount(
273+
TarantoolClient<T, R> client) throws ExecutionException, InterruptedException {
274+
if (!bucketCount.isPresent()) {
275+
bucketCount = Optional.ofNullable(
276+
client.callForSingleResult("vshard.router.bucket_count", Integer.class).get()
277+
);
278+
}
279+
return bucketCount.get();
280+
}
281+
```
282+
283+
Then you can determine bucket id by passing your key through hash function and get the remainder of the division by number of buckets:
284+
```java
285+
byte[] key = ... // can be multipart
286+
Integer bucketId = (bucketIdcrc32(key) % getBucketCount(client)) + 1;
287+
```
288+
289+
After that you may apply it in operations:
290+
```java
291+
InsertOptions insertOptions = ProxyInsertOptions.create().withBucketId(bucketId);
292+
insertResult = profileSpace.insert(tarantoolTuple, insertOptions).get();
293+
294+
ProxySelectOptions selectOptions = ProxySelectOptions.create().withBucketId(bucketId);
295+
selectResult = profileSpace.select(condition, selectOptions).get();
296+
```
297+
298+
You can see sources of example in [tests](src/test/java/io/tarantool/driver/integration/proxy/options/ProxySpaceInsertOptionsIT.java)
299+
247300
### Retrying Tarantool client
248301

249302
For the cases of reliable communication with a Cartridge cluster under heavy load or in a case of some failure causing

src/test/java/io/tarantool/driver/integration/Utils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public static <T extends Packable, R extends Collection<T>> Integer getBucketIdS
8181
);
8282
}
8383

84+
/**
85+
* Implementation of crc32 partially is taken from
86+
* <a href="https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/CRC32.java">
87+
* github.com/TheAlgorithms</a>
88+
*
89+
* @param data input bytes array
90+
* @return hash response in decimal view
91+
*/
8492
private static long crc32(byte[] data) {
8593
BitSet bitSet = BitSet.valueOf(data);
8694
int crc32 = 0xFFFFFFFF; // initial value

src/test/java/io/tarantool/driver/integration/proxy/options/ProxySpaceInsertOptionsIT.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.tarantool.driver.api.conditions.Conditions;
77
import io.tarantool.driver.api.space.TarantoolSpaceOperations;
88
import io.tarantool.driver.api.space.options.InsertOptions;
9+
import io.tarantool.driver.api.space.options.SelectOptions;
910
import io.tarantool.driver.api.space.options.proxy.ProxySelectOptions;
1011
import io.tarantool.driver.api.tuple.DefaultTarantoolTupleFactory;
1112
import io.tarantool.driver.api.tuple.TarantoolTuple;
@@ -135,6 +136,29 @@ public void withBucketIdTest() throws ExecutionException, InterruptedException {
135136
assertEquals(1, selectResult.size());
136137
}
137138

139+
@Test
140+
public void withBucketIdFromClientTest() throws ExecutionException, InterruptedException {
141+
TarantoolSpaceOperations<TarantoolTuple, TarantoolResult<TarantoolTuple>> profileSpace =
142+
client.space(TEST_SPACE_NAME);
143+
144+
TarantoolTuple tarantoolTuple = tupleFactory.create(1, null, "FIO", 50, 100);
145+
Conditions condition = Conditions.equals(PK_FIELD_NAME, 1);
146+
147+
Integer bucketId = Utils.getBucketIdStrCRC32(client,
148+
Collections.singletonList(tarantoolTuple.getInteger(0)));
149+
InsertOptions insertOptions = ProxyInsertOptions.create().withBucketId(bucketId);
150+
151+
TarantoolResult<TarantoolTuple> insertResult = profileSpace.insert(tarantoolTuple, insertOptions).get();
152+
assertEquals(1, insertResult.size());
153+
154+
TarantoolResult<TarantoolTuple> selectResult = profileSpace.select(condition).get();
155+
assertEquals(1, selectResult.size());
156+
157+
SelectOptions selectOptions = ProxySelectOptions.create().withBucketId(bucketId);
158+
selectResult = profileSpace.select(condition, selectOptions).get();
159+
assertEquals(1, selectResult.size());
160+
}
161+
138162
private Integer getBucketIdFromTarantool(List<Object> key) throws ExecutionException, InterruptedException {
139163
return client.callForSingleResult(
140164
"vshard.router.bucket_id_strcrc32",

0 commit comments

Comments
 (0)