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
6 changes: 6 additions & 0 deletions client/trino-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-testing-services</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-tpch</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public ConcurrentMap<K, V> asMap()
public V putIfAbsent(K key, V value)
{
// Cache, even if configured to evict everything immediately, should allow writes.
return value;
// putIfAbsent returns the previous value
return null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the above comment looks weird now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed myself

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you forced pushed.
Would you consider

// putIfAbsent returns the previous value

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that 🤦

Notice that the put method has the old comment still, I find old comment still useful. It is more about empty cache, not the put method. I will leave both ones.

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/
package io.trino.collect.cache;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Ticker;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
Expand Down Expand Up @@ -126,19 +127,23 @@ public EvictableCacheBuilder<K, V> recordStats()
*/
public EvictableCacheBuilder<K, V> shareResultsAndFailuresEvenIfDisabled()
{
checkState(!disabledCacheImplementation.isPresent(), "disabledCacheImplementation already set");
disabledCacheImplementation = Optional.of(DisabledCacheImplementation.GUAVA);
return this;
return disabledCacheImplementation(DisabledCacheImplementation.GUAVA);
}

/**
* Choose a behavior for case when caching is disabled that prevents data and failure sharing between concurrent callers.
* Note: disabled cache won't report any statistics.
*/
public EvictableCacheBuilder<K, V> shareNothingWhenDisabled()
{
return disabledCacheImplementation(DisabledCacheImplementation.NOOP);
}

@VisibleForTesting
EvictableCacheBuilder<K, V> disabledCacheImplementation(DisabledCacheImplementation cacheImplementation)
Comment thread
findepi marked this conversation as resolved.
Outdated
{
checkState(!disabledCacheImplementation.isPresent(), "disabledCacheImplementation already set");
disabledCacheImplementation = Optional.of(DisabledCacheImplementation.NOOP);
disabledCacheImplementation = Optional.of(cacheImplementation);
return this;
}

Expand Down Expand Up @@ -237,7 +242,8 @@ private static Duration toDuration(long duration, TimeUnit unit)
return Duration.ofNanos(unit.toNanos(duration));
}

private enum DisabledCacheImplementation
@VisibleForTesting
enum DisabledCacheImplementation
{
NOOP,
GUAVA,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.airlift.testing.TestingTicker;
import io.trino.collect.cache.EvictableCacheBuilder.DisabledCacheImplementation;
import org.gaul.modernizer_maven_annotations.SuppressModernizer;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
Expand All @@ -38,11 +40,13 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static io.trino.collect.cache.CacheStatsAssertions.assertCacheStats;
import static io.trino.testing.DataProviders.toDataProvider;
import static java.lang.Math.toIntExact;
import static java.lang.String.format;
import static java.util.concurrent.Executors.newFixedThreadPool;
Expand Down Expand Up @@ -542,4 +546,46 @@ public void testInvalidateAndLoadConcurrently(Invalidation invalidation)
executor.awaitTermination(10, SECONDS);
}
}

@Test(dataProvider = "disabledCacheImplementations")
public void testPutOnEmptyCacheImplementation(DisabledCacheImplementation disabledCacheImplementation)
{
Cache<Object, Object> cache = EvictableCacheBuilder.newBuilder()
.maximumSize(0)
.disabledCacheImplementation(disabledCacheImplementation)
.build();
Map<Object, Object> cacheMap = cache.asMap();

int key = 0;
int value = 1;
assertThat(cacheMap.put(key, value)).isNull();
assertThat(cacheMap.put(key, value)).isNull();
assertThat(cacheMap.putIfAbsent(key, value)).isNull();
assertThat(cacheMap.putIfAbsent(key, value)).isNull();
}

@Test
public void testPutOnNonEmptyCacheImplementation()
{
Cache<Object, Object> cache = EvictableCacheBuilder.newBuilder()
.maximumSize(10)
.build();
Map<Object, Object> cacheMap = cache.asMap();

int key = 0;
int value = 1;
assertThatThrownBy(() -> cacheMap.put(key, value))
.isInstanceOf(UnsupportedOperationException.class)
.hasMessage("The operation is not supported, as in inherently races with cache invalidation. Use get(key, callable) instead.");
assertThatThrownBy(() -> cacheMap.putIfAbsent(key, value))
.isInstanceOf(UnsupportedOperationException.class)
.hasMessage("The operation is not supported, as in inherently races with cache invalidation");
}

@DataProvider
public static Object[][] disabledCacheImplementations()
{
return Stream.of(DisabledCacheImplementation.values())
.collect(toDataProvider());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,41 @@ public void testInvalidateAndLoadConcurrently(Invalidation invalidation)
}
}

@Test(dataProvider = "disabledCacheImplementations", dataProviderClass = TestEvictableCache.class)
public void testPutOnEmptyCacheImplementation(EvictableCacheBuilder.DisabledCacheImplementation disabledCacheImplementation)
{
LoadingCache<Object, Object> cache = EvictableCacheBuilder.newBuilder()
.maximumSize(0)
.disabledCacheImplementation(disabledCacheImplementation)
.build(CacheLoader.from(key -> key));
Map<Object, Object> cacheMap = cache.asMap();

int key = 0;
int value = 1;
assertThat(cacheMap.put(key, value)).isNull();
assertThat(cacheMap.put(key, value)).isNull();
assertThat(cacheMap.putIfAbsent(key, value)).isNull();
assertThat(cacheMap.putIfAbsent(key, value)).isNull();
}

@Test
public void testPutOnNonEmptyCacheImplementation()
{
LoadingCache<Object, Object> cache = EvictableCacheBuilder.newBuilder()
.maximumSize(10)
.build(CacheLoader.from(key -> key));
Map<Object, Object> cacheMap = cache.asMap();

int key = 0;
int value = 1;
assertThatThrownBy(() -> cacheMap.put(key, value))
.isInstanceOf(UnsupportedOperationException.class)
.hasMessage("The operation is not supported, as in inherently races with cache invalidation. Use get(key, callable) instead.");
assertThatThrownBy(() -> cacheMap.putIfAbsent(key, value))
.isInstanceOf(UnsupportedOperationException.class)
.hasMessage("The operation is not supported, as in inherently races with cache invalidation");
}

/**
* A class implementing value-based equality taking into account some fields, but not all.
* This is definitely discouraged, but still may happen in practice.
Expand Down
6 changes: 6 additions & 0 deletions testing/trino-test-jdbc-compatibility-old-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-testing-services</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.airlift</groupId>
<artifactId>configuration</artifactId>
Expand Down
27 changes: 12 additions & 15 deletions testing/trino-testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@
<artifactId>trino-spi</artifactId>
</dependency>

<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-testing-services</artifactId>
<exclusions>
<exclusion>
<!-- conflicts with test-scoped dependency declared below -->
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
</exclusion>
Comment on lines 55 to 59
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still the case?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me do it as follow up.

</exclusions>
</dependency>

<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-tpch</artifactId>
Expand Down Expand Up @@ -148,21 +160,6 @@
<artifactId>testng</artifactId>
</dependency>

<dependency>
<!-- trino-testing is on test classpath of many modules. It's important to pull trino-testing-services as a dependency,
because trino-testing-services includes various test-related checkers -->
<groupId>io.trino</groupId>
<artifactId>trino-testing-services</artifactId>
<scope>runtime</scope>
<exclusions>
<exclusion>
<!-- conflicts with test-scoped dependency declared below -->
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down