Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ subprojects {
googleCloudStorageVersion = '2.60.0'
picocliVersion = '4.7.7'
commonsTextVersion = '1.14.0'
caffeineVersion = '2.9.3'
junitVersion = '5.14.1'
commonsLangVersion = '3.20.0'
assertjVersion = '3.27.6'
Expand Down
1 change: 1 addition & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ dependencies {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation "org.apache.commons:commons-text:${commonsTextVersion}"
implementation "com.github.ben-manes.caffeine:caffeine:${caffeineVersion}"
testImplementation platform("org.junit:junit-bom:${junitVersion}")
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
Expand Down
38 changes: 14 additions & 24 deletions core/src/main/java/com/scalar/db/common/TableMetadataManager.java
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
package com.scalar.db.common;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.scalar.db.api.Admin;
import com.scalar.db.api.Operation;
import com.scalar.db.api.TableMetadata;
import com.scalar.db.exception.storage.ExecutionException;
import com.scalar.db.util.ScalarDbUtils;
import com.scalar.db.util.ThrowableFunction;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

/** A class that manages and caches table metadata */
@ThreadSafe
public class TableMetadataManager {

private final LoadingCache<TableKey, Optional<TableMetadata>> tableMetadataCache;
private final LoadingCache<TableKey, TableMetadata> tableMetadataCache;

public TableMetadataManager(Admin admin, long cacheExpirationTimeSecs) {
this(
key -> Optional.ofNullable(admin.getTableMetadata(key.namespace, key.table)),
cacheExpirationTimeSecs);
this(key -> admin.getTableMetadata(key.namespace, key.table), cacheExpirationTimeSecs);
}

public TableMetadataManager(
ThrowableFunction<TableKey, Optional<TableMetadata>, Exception> getTableMetadataFunc,
ThrowableFunction<TableKey, TableMetadata, Exception> getTableMetadataFunc,
long cacheExpirationTimeSecs) {
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
Caffeine<Object, Object> builder = Caffeine.newBuilder();
if (cacheExpirationTimeSecs >= 0) {
builder.expireAfterWrite(cacheExpirationTimeSecs, TimeUnit.SECONDS);
}
tableMetadataCache =
builder.build(
new CacheLoader<TableKey, Optional<TableMetadata>>() {
@Nonnull
@Override
public Optional<TableMetadata> load(@Nonnull TableKey key) throws Exception {
return getTableMetadataFunc.apply(key);
}
});
tableMetadataCache = builder.build(getTableMetadataFunc::apply);
}

/**
Expand All @@ -61,22 +50,23 @@ public TableMetadata getTableMetadata(Operation operation) throws ExecutionExcep
}

/**
* Returns a table metadata corresponding to the specified operation.
* Returns a table metadata corresponding to the specified namespace and table.
*
* @param namespace a namespace to retrieve
* @param table a table to retrieve
* @return a table metadata. null if the table is not found.
* @throws ExecutionException if the operation fails
*/
@Nullable
public TableMetadata getTableMetadata(String namespace, String table) throws ExecutionException {
try {
TableKey key = new TableKey(namespace, table);
return tableMetadataCache.get(key).orElse(null);
} catch (java.util.concurrent.ExecutionException e) {
return tableMetadataCache.get(key);
} catch (CompletionException e) {
throw new ExecutionException(
CoreError.GETTING_TABLE_METADATA_FAILED.buildMessage(
ScalarDbUtils.getFullTableName(namespace, table)),
e);
e.getCause());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
package com.scalar.db.transaction.consensuscommit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.scalar.db.api.DistributedStorageAdmin;
import com.scalar.db.api.Operation;
import com.scalar.db.api.TableMetadata;
import com.scalar.db.common.CoreError;
import com.scalar.db.exception.storage.ExecutionException;
import com.scalar.db.util.ScalarDbUtils;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

@ThreadSafe
public class TransactionTableMetadataManager {

private final LoadingCache<TableKey, Optional<TransactionTableMetadata>> tableMetadataCache;
private final LoadingCache<TableKey, TransactionTableMetadata> tableMetadataCache;

public TransactionTableMetadataManager(
DistributedStorageAdmin admin, long cacheExpirationTimeSecs) {

CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
Caffeine<Object, Object> builder = Caffeine.newBuilder();
if (cacheExpirationTimeSecs >= 0) {
builder.expireAfterWrite(cacheExpirationTimeSecs, TimeUnit.SECONDS);
}
tableMetadataCache =
builder.build(
new CacheLoader<TableKey, Optional<TransactionTableMetadata>>() {
@Nonnull
@Override
public Optional<TransactionTableMetadata> load(@Nonnull TableKey key)
throws ExecutionException {
TableMetadata tableMetadata = admin.getTableMetadata(key.namespace, key.table);
if (tableMetadata == null) {
return Optional.empty();
}
return Optional.of(new TransactionTableMetadata(tableMetadata));
key -> {
TableMetadata tableMetadata = admin.getTableMetadata(key.namespace, key.table);
if (tableMetadata == null) {
return null;
}
return new TransactionTableMetadata(tableMetadata);
});
}

Expand Down Expand Up @@ -74,12 +67,12 @@ public TransactionTableMetadata getTransactionTableMetadata(String namespace, St
throws ExecutionException {
try {
TableKey key = new TableKey(namespace, table);
return tableMetadataCache.get(key).orElse(null);
} catch (java.util.concurrent.ExecutionException e) {
return tableMetadataCache.get(key);
} catch (CompletionException e) {
throw new ExecutionException(
CoreError.GETTING_TABLE_METADATA_FAILED.buildMessage(
ScalarDbUtils.getFullTableName(namespace, table)),
e);
e.getCause());
}
}

Expand Down
Loading