Skip to content

Commit

Permalink
Calculate request signatures using input parameters only
Browse files Browse the repository at this point in the history
References to temporary objects were used in some places for request
signatures calculation. Replace them with input parameters.
  • Loading branch information
akudiyar committed Jan 14, 2024
1 parent ec859a1 commit 5f9e69c
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.msgpack.value.Value;
import org.msgpack.value.ValueType;

import java.util.Collection;
import java.util.List;
import java.util.Map;

Expand Down
33 changes: 16 additions & 17 deletions src/main/java/io/tarantool/driver/core/AbstractTarantoolClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,10 @@ public <T> CompletableFuture<TarantoolResult<T>> callForTupleResult(
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
Class<T> tupleClass)
throws TarantoolClientException {
Supplier<CallResultMapper<TarantoolResult<T>, SingleValueCallResult<TarantoolResult<T>>>>
resultMapperSupplier = () ->
mapperFactoryFactory.getTarantoolResultMapper(config.getMessagePackMapper(), tupleClass);
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
functionName, arguments, tupleClass, argumentsMapperSupplier, resultMapperSupplier);
functionName, arguments, argumentsMapperSupplier, tupleClass);
Supplier<CallResultMapper<TarantoolResult<T>, SingleValueCallResult<TarantoolResult<T>>>> resultMapperSupplier =
() -> mapperFactoryFactory.getTarantoolResultMapper(config.getMessagePackMapper(), tupleClass);
return callForSingleResult(functionName, arguments, signature, argumentsMapperSupplier, resultMapperSupplier);
}

Expand Down Expand Up @@ -355,10 +354,10 @@ public <S> CompletableFuture<S> callForSingleResult(
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
Class<S> resultClass)
throws TarantoolClientException {
Supplier<CallResultMapper<S, SingleValueCallResult<S>>> resultMapperSupplier = () ->
mapperFactoryFactory.getDefaultSingleValueMapper(config.getMessagePackMapper(), resultClass);
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
functionName, arguments, resultClass, argumentsMapperSupplier, resultMapperSupplier);
functionName, arguments, argumentsMapperSupplier, resultClass);
Supplier<CallResultMapper<S, SingleValueCallResult<S>>> resultMapperSupplier =
() -> mapperFactoryFactory.getDefaultSingleValueMapper(config.getMessagePackMapper(), resultClass);
return callForSingleResult(functionName, arguments, signature, argumentsMapperSupplier, resultMapperSupplier);
}

Expand All @@ -369,10 +368,10 @@ public <S> CompletableFuture<S> callForSingleResult(
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
ValueConverter<Value, S> valueConverter)
throws TarantoolClientException {
Supplier<CallResultMapper<S, SingleValueCallResult<S>>> resultMapperSupplier = () ->
mapperFactoryFactory.getSingleValueResultMapper(valueConverter);
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
functionName, arguments, valueConverter.getClass(), argumentsMapperSupplier, resultMapperSupplier);
functionName, arguments, argumentsMapperSupplier, valueConverter);
Supplier<CallResultMapper<S, SingleValueCallResult<S>>> resultMapperSupplier =
() -> mapperFactoryFactory.getSingleValueResultMapper(valueConverter);
return callForSingleResult(functionName, arguments, signature, argumentsMapperSupplier, resultMapperSupplier);
}

Expand Down Expand Up @@ -464,10 +463,10 @@ public <T, R extends List<T>> CompletableFuture<R> callForMultiResult(
Supplier<R> resultContainerSupplier,
Class<T> resultClass)
throws TarantoolClientException {
Supplier<CallResultMapper<R, MultiValueCallResult<T, R>>> resultMapperSupplier = () ->
mapperFactoryFactory.getDefaultMultiValueMapper(config.getMessagePackMapper(), resultClass);
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
functionName, arguments, resultClass, argumentsMapperSupplier, resultMapperSupplier);
functionName, arguments, argumentsMapperSupplier, resultContainerSupplier, resultClass);
Supplier<CallResultMapper<R, MultiValueCallResult<T, R>>> resultMapperSupplier =
() -> mapperFactoryFactory.getDefaultMultiValueMapper(config.getMessagePackMapper(), resultClass);
return callForMultiResult(functionName, arguments, signature, argumentsMapperSupplier, resultMapperSupplier);
}

Expand All @@ -479,10 +478,10 @@ public <T, R extends List<T>> CompletableFuture<R> callForMultiResult(
Supplier<R> resultContainerSupplier,
ValueConverter<Value, T> valueConverter)
throws TarantoolClientException {
Supplier<CallResultMapper<R, MultiValueCallResult<T, R>>> resultMapperSupplier = () ->
mapperFactoryFactory.getMultiValueResultMapper(resultContainerSupplier, valueConverter);
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
functionName, arguments, valueConverter.getClass(), argumentsMapperSupplier, resultMapperSupplier);
functionName, arguments, argumentsMapperSupplier, resultContainerSupplier, valueConverter);
Supplier<CallResultMapper<R, MultiValueCallResult<T, R>>> resultMapperSupplier =
() -> mapperFactoryFactory.getMultiValueResultMapper(resultContainerSupplier, valueConverter);
return callForMultiResult(functionName, arguments, signature, argumentsMapperSupplier, resultMapperSupplier);
}

Expand Down Expand Up @@ -591,7 +590,7 @@ public CompletableFuture<List<?>> eval(
Supplier<? extends MessagePackValueMapper> resultMapperSupplier) throws TarantoolClientException {
try {
TarantoolRequestSignature signature = TarantoolRequestSignature.create(
expression, arguments, List.class, argumentsMapperSupplier, resultMapperSupplier);
expression, arguments, argumentsMapperSupplier, resultMapperSupplier);
MessagePackObjectMapper argumentsMapper = argumentsMapperCache.computeIfAbsent(
signature, s -> argumentsMapperSupplier.get());
MessagePackValueMapper resultMapper = resultMapperCache.computeIfAbsent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.msgpack.value.Value;

import io.tarantool.driver.protocol.TarantoolRequest;
import io.tarantool.driver.protocol.TarantoolRequestSignature;

/**
* Intermediate request metadata holder
Expand Down
22 changes: 15 additions & 7 deletions src/main/java/io/tarantool/driver/core/space/TarantoolSpace.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,32 @@ public TarantoolSpace(
String spaceIdStr = String.valueOf(this.spaceId);
methodSignatures.put(
TarantoolDeleteRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolDeleteRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolDeleteRequest.class.getName()));
methodSignatures.put(
TarantoolInsertRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolInsertRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolInsertRequest.class.getName()));
methodSignatures.put(
TarantoolReplaceRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolReplaceRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolReplaceRequest.class.getName()));
methodSignatures.put(
TarantoolSelectRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolSelectRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolSelectRequest.class.getName()));
methodSignatures.put(
TarantoolUpdateRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolUpdateRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolUpdateRequest.class.getName()));
methodSignatures.put(
TarantoolUpsertRequest.class.getName(),
new TarantoolRequestSignature(spaceIdStr, TarantoolUpsertRequest.class.getName()));
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent(TarantoolUpsertRequest.class.getName()));
methodSignatures.put(
"truncate", new TarantoolRequestSignature(spaceIdStr, "truncate", TarantoolCallRequest.class.getName()));
"truncate",
new TarantoolRequestSignature()
.addComponent(spaceIdStr).addComponent("truncate").addComponent(TarantoolCallRequest.class.getName()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import org.msgpack.value.Value;

import io.tarantool.driver.mappers.MessagePackObjectMapper;
import io.tarantool.driver.mappers.MessagePackValueMapper;
import io.tarantool.driver.mappers.converters.ValueConverter;

/**
* Represents a request signature, uniquely defining the operation and the
Expand All @@ -18,11 +20,19 @@
*
* @author Alexey Kuzin
*/
public class TarantoolRequestSignature {
public final class TarantoolRequestSignature {

private List<String> components = new LinkedList<>();
private List<String> components = new ArrayList<>();
private int hashCode = 1;

/**
* Constructor.
*
* Creates an empty signature - do not use it without providing the components!
*/
public TarantoolRequestSignature() {
}

/**
* Constructor.
*
Expand All @@ -32,8 +42,11 @@ public class TarantoolRequestSignature {
*
* @param initialComponents initial signature components
*/
public TarantoolRequestSignature(Object... initialComponents) {
private TarantoolRequestSignature(Object[] initialComponents) {
for (Object component : initialComponents) {
if (component == null) {
continue;
}
String componentValue = component instanceof String ? (String) component : component.getClass().getName();
components.add(componentValue);
hashCode = 31 * hashCode + Objects.hashCode(componentValue);
Expand All @@ -50,9 +63,11 @@ public TarantoolRequestSignature(Object... initialComponents) {
* @return this signature object instance
*/
public TarantoolRequestSignature addComponent(Object component) {
String componentValue = component instanceof String ? (String) component : component.getClass().getName();
components.add(componentValue);
hashCode = 31 * hashCode + Objects.hashCode(componentValue);
if (component != null) {
String componentValue = component instanceof String ? (String) component : component.getClass().getName();
components.add(componentValue);
hashCode = 31 * hashCode + Objects.hashCode(componentValue);
}
return this;
}

Expand All @@ -78,28 +93,107 @@ public String toString() {
}

/**
* Factory method for a typical RPC usage
* Factory method for building the common signature part
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @return new request signature
*/
private static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier) {
Object[] components = new Object[arguments.size() + 2];
int i = 0;
components[i++] = functionName;
for (Object argument : arguments) {
components[i++] = argument.getClass().getName();
}
components[i++] = Integer.toHexString(argumentsMapperSupplier.hashCode());
return new TarantoolRequestSignature(components);
}

/**
* Factory method for caching default result mapper suppliers
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @param resultClass type of the expected result. It's necessary
* for polymorphic functions, e.g. accepting a
* Tarantool space as an argument
* @return new request signature
*/
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier, Class<?> resultClass) {
return TarantoolRequestSignature.create(functionName, arguments, argumentsMapperSupplier)
.addComponent(resultClass.getName());
}

/**
* Factory method for caching default result mapper suppliers
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @param valueConverter single value result converter
* @return new request signature
*/
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
ValueConverter<Value, ?> valueConverter) {
return TarantoolRequestSignature.create(functionName, arguments, argumentsMapperSupplier)
.addComponent(Integer.toHexString(valueConverter.hashCode()));
}

/**
* Factory method for caching default multi value result mapper suppliers
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @param resultContainerSupplier multi value result container supplier
* @param valueConverter multi value result container item converter
* @return new request signature
*/
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
Supplier<?> resultContainerSupplier, ValueConverter<Value, ?> valueConverter) {
return TarantoolRequestSignature.create(functionName, arguments, argumentsMapperSupplier)
.addComponent(Integer.toHexString(resultContainerSupplier.hashCode()))
.addComponent(Integer.toHexString(valueConverter.hashCode()));
}

/**
* Factory method for caching default multi value result mapper suppliers
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @param resultContainerSupplier multi value result container supplier
* @param resultClass multi value result item class
* @return new request signature
*/
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
Supplier<?> resultContainerSupplier, Class<?> resultClass) {
return TarantoolRequestSignature.create(functionName, arguments, argumentsMapperSupplier)
.addComponent(Integer.toHexString(resultContainerSupplier.hashCode()))
.addComponent(resultClass.getName());
}

/**
* Factory method for a typical RPC usage
*
* @param functionName name of the remote function
* @param arguments list of arguments for the remote function
* @param argumentsMapperSupplier arguments mapper supplier
* @param resultMapperSupplier result mapper supplier
* @return new request signature
*/
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments, Class<?> resultClass,
public static TarantoolRequestSignature create(String functionName, Collection<?> arguments,
Supplier<? extends MessagePackObjectMapper> argumentsMapperSupplier,
Supplier<? extends MessagePackValueMapper> resultMapperSupplier) {
List<Object> components = new ArrayList<>(arguments.size() + 4);
components.add(functionName);
for (Object argument : arguments) {
components.add(argument.getClass().getName());
}
components.add(resultClass.getName());
components.add(Integer.toHexString(argumentsMapperSupplier.hashCode()));
components.add(Integer.toHexString(resultMapperSupplier.hashCode()));
return new TarantoolRequestSignature(components.toArray(new Object[] {}));
return TarantoolRequestSignature.create(functionName, arguments, argumentsMapperSupplier)
.addComponent(Integer.toHexString(resultMapperSupplier.hashCode()));
}
}
Loading

0 comments on commit 5f9e69c

Please sign in to comment.