io.tarantool.driver.core.metadata.TarantoolMetadata Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cartridge-driver Show documentation
Show all versions of cartridge-driver Show documentation
Tarantool Cartridge driver for Tarantool versions 1.10+ based on Netty framework
package io.tarantool.driver.core.metadata;
import io.tarantool.driver.api.metadata.TarantoolIndexMetadata;
import io.tarantool.driver.api.metadata.TarantoolMetadataOperations;
import io.tarantool.driver.api.metadata.TarantoolMetadataProvider;
import io.tarantool.driver.api.metadata.TarantoolSpaceMetadata;
import io.tarantool.driver.exceptions.TarantoolClientException;
import io.tarantool.driver.exceptions.TarantoolNoSuchProcedureException;
import io.tarantool.driver.utils.Assert;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Phaser;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Base class for {@link TarantoolMetadataOperations} implementations
*
* @author Alexey Kuzin
*/
public class TarantoolMetadata implements TarantoolMetadataOperations {
protected final Map spaceMetadataByName = new ConcurrentHashMap<>();
protected final Map spaceMetadataById = new ConcurrentHashMap<>();
protected final Map> indexMetadataBySpaceName =
new ConcurrentHashMap<>();
protected final Map> indexMetadataBySpaceId =
new ConcurrentHashMap<>();
private final Phaser initPhaser = new Phaser(0);
private final AtomicBoolean needRefresh = new AtomicBoolean(true);
private final TarantoolMetadataProvider metadataProvider;
public TarantoolMetadata(TarantoolMetadataProvider metadataProvider) {
this.metadataProvider = metadataProvider;
}
protected Map getSpaceMetadata() {
awaitInitLatch();
return spaceMetadataByName;
}
protected Map getSpaceMetadataById() {
awaitInitLatch();
return spaceMetadataById;
}
protected Map> getIndexMetadata() {
awaitInitLatch();
return indexMetadataBySpaceName;
}
protected Map> getIndexMetadataBySpaceId() {
awaitInitLatch();
return indexMetadataBySpaceId;
}
@Override
public void scheduleRefresh() {
needRefresh.set(true);
}
@Override
public CompletableFuture refresh() throws TarantoolClientException {
return populateMetadata().whenComplete((v, ex) -> {
if (ex != null) {
needRefresh.set(true);
}
initPhaser.arriveAndDeregister();
});
}
private void awaitInitLatch() {
if (initPhaser.getRegisteredParties() == 0 && needRefresh.compareAndSet(true, false)) {
initPhaser.register();
try {
refresh().get();
} catch (InterruptedException e) {
throw new TarantoolClientException("Failed to refresh spaces and indexes metadata", e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof TarantoolNoSuchProcedureException) {
//This case is required to handle retry when instances are not initialized yet.
//See https://github.com/tarantool/cartridge-java/issues/170
throw (TarantoolNoSuchProcedureException) cause;
}
throw new TarantoolClientException("Failed to refresh spaces and indexes metadata", cause);
}
} else {
initPhaser.awaitAdvance(initPhaser.getPhase());
}
}
private CompletableFuture populateMetadata() {
CompletableFuture result = new CompletableFuture<>();
try {
result = metadataProvider.getMetadata().thenAccept(container -> {
spaceMetadataByName.clear();
spaceMetadataById.clear();
indexMetadataBySpaceName.clear();
indexMetadataBySpaceId.clear();
indexMetadataBySpaceName.putAll(container.getIndexMetadataBySpaceName());
container.getSpaceMetadataByName().forEach((spaceName, spaceMetadata) -> {
spaceMetadataByName.put(spaceName, spaceMetadata);
spaceMetadataById.put(spaceMetadata.getSpaceId(), spaceMetadata);
Map indexesForSpace =
indexMetadataBySpaceName.get(spaceMetadata.getSpaceName());
if (indexesForSpace != null) {
indexMetadataBySpaceId.put(spaceMetadata.getSpaceId(), indexesForSpace);
}
});
});
} catch (Throwable e) {
result.completeExceptionally(e);
}
return result;
}
@Override
public Optional getSpaceByName(String spaceName) {
Assert.hasText(spaceName, "Space name must not be null or empty");
return Optional.ofNullable(getSpaceMetadata().get(spaceName));
}
@Override
public Optional getIndexByName(int spaceId, String indexName) {
Assert.state(spaceId > 0, "Space ID must be greater than 0");
Assert.hasText(indexName, "Index name must not be null or empty");
Map metaMap = getIndexMetadataBySpaceId().get(spaceId);
if (metaMap == null) {
return Optional.empty();
}
return Optional.ofNullable(metaMap.get(indexName));
}
@Override
public Optional getIndexByName(String spaceName, String indexName) {
Assert.hasText(spaceName, "Space name must not be null or empty");
Assert.hasText(indexName, "Index name must not be null or empty");
Map metaMap = getIndexMetadata().get(spaceName);
if (metaMap == null) {
return Optional.empty();
}
return Optional.ofNullable(metaMap.get(indexName));
}
@Override
public Optional getIndexById(String spaceName, int indexId) {
Assert.hasText(spaceName, "Space name must not be null or empty");
Assert.state(indexId >= 0, "Index ID must be greater than or equal 0");
Map metaMap = getIndexMetadata().get(spaceName);
if (metaMap == null) {
return Optional.empty();
}
return metaMap.values().stream().filter(i -> i.getIndexId() == indexId).findFirst();
}
@Override
public Optional getIndexById(int spaceId, int indexId) {
Assert.state(spaceId > 0, "Space ID must be greater than 0");
Assert.state(indexId >= 0, "Index ID must be greater than or equal 0");
Map metaMap = getIndexMetadataBySpaceId().get(spaceId);
if (metaMap == null) {
return Optional.empty();
}
return metaMap.values().stream().filter(i -> i.getIndexId() == indexId).findFirst();
}
@Override
public Optional getSpaceById(int spaceId) {
Assert.state(spaceId > 0, "Space ID must be greater than 0");
return Optional.ofNullable(getSpaceMetadataById().get(spaceId));
}
@Override
public Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy