Thanks to visit codestin.com
Credit goes to github.com

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: 0 additions & 6 deletions google-cloud-clients/google-cloud-spanner/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,6 @@
<classifier>testlib</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
<version>${opencensus.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-grpc-util</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -838,6 +839,7 @@ private PooledSession take() throws SpannerException {
SessionOrError s = pollUninterruptiblyWithTimeout(currentTimeout);
if (s == null) {
// Set the status to DEADLINE_EXCEEDED and retry.
numWaiterTimeouts.incrementAndGet();
tracer.getCurrentSpan().setStatus(Status.DEADLINE_EXCEEDED);
currentTimeout = Math.min(currentTimeout * 2, MAX_SESSION_WAIT_TIMEOUT);
} else {
Expand Down Expand Up @@ -1065,6 +1067,8 @@ private void replenishPool() {
@GuardedBy("lock")
private int maxSessionsInUse = 0;

private AtomicLong numWaiterTimeouts = new AtomicLong();

@GuardedBy("lock")
private final Set<PooledSession> allSessions = new HashSet<>();

Expand Down Expand Up @@ -1123,6 +1127,11 @@ int getNumberOfAvailableWritePreparedSessions() {
return writePreparedSessions.size();
}

@VisibleForTesting
long getNumWaiterTimeouts() {
return numWaiterTimeouts.get();
}

private void initPool() {
synchronized (lock) {
poolMaintainer.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,14 @@
import com.google.cloud.spanner.spi.v1.SpannerRpc;
import com.google.cloud.spanner.spi.v1.SpannerRpc.ResultStreamConsumer;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.protobuf.ByteString;
import com.google.spanner.v1.CommitRequest;
import com.google.spanner.v1.ExecuteBatchDmlRequest;
import com.google.spanner.v1.ExecuteSqlRequest;
import com.google.spanner.v1.ResultSetStats;
import com.google.spanner.v1.RollbackRequest;
import io.opencensus.trace.Span;
import io.opencensus.trace.Status;
import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing;
import io.opencensus.trace.config.TraceConfig;
import io.opencensus.trace.config.TraceParams;
import io.opencensus.trace.export.SpanData;
import io.opencensus.trace.export.SpanExporter.Handler;
import io.opencensus.trace.samplers.Samplers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -581,32 +573,6 @@ public void keepAlive() throws Exception {

@Test
public void blockAndTimeoutOnPoolExhaustion() throws InterruptedException, ExecutionException {
if (minSessions != 0) {
// Only execute for minSessions == 0 as we need to setup and shutdown a mock sampler during
// the test case. A second run would not work as there is no way to restart the sampler.
return;
}
// Setup a dummy trace handler.
final AtomicInteger deadlineExceededCount = new AtomicInteger();
Handler handler =
new Handler() {
@Override
public void export(Collection<SpanData> spanDataList) {
for (SpanData sd : spanDataList) {
if (sd.getStatus() == Status.DEADLINE_EXCEEDED
&& sd.getName().equals(SessionPool.WAIT_FOR_SESSION)) {
deadlineExceededCount.incrementAndGet();
}
}
}
};
Tracing.getExportComponent()
.getSpanExporter()
.registerHandler(SessionPoolTest.class.getName(), handler);
TraceConfig traceConfig = Tracing.getTraceConfig();
TraceParams activeTraceParams = traceConfig.getActiveTraceParams();
traceConfig.updateActiveTraceParams(
activeTraceParams.toBuilder().setSampler(Samplers.alwaysSample()).build());
// Create a session pool with max 1 session and a low timeout for waiting for a session.
options =
SessionPoolOptions.newBuilder()
Expand All @@ -618,20 +584,22 @@ public void export(Collection<SpanData> spanDataList) {
when(client.createSession(db)).thenReturn(mockSession);
pool = createPool();

Tracer tracer = Tracing.getTracer();
Span span = tracer.spanBuilder("RunTest").startSpan();
// Try to take a read or a read/write session. These requests should block.
for (Boolean write : new Boolean[] {true, false}) {
// Take the only session that can be in the pool.
Session checkedOutSession = pool.getReadSession();
final Boolean finWrite = write;
ExecutorService executor = Executors.newFixedThreadPool(1);
// Setup a flag that will indicate when the thread will start waiting for a session to prevent
// flaky fails if it takes some time before the thread is started.
final SettableFuture<Boolean> waitingForSession = SettableFuture.create();
Future<Void> fut =
executor.submit(
new Callable<Void>() {
@Override
public Void call() throws Exception {
Session session;
waitingForSession.set(Boolean.TRUE);
if (finWrite) {
session = pool.getReadWriteSession();
} else {
Expand All @@ -642,6 +610,8 @@ public Void call() throws Exception {
}
});
try {
// Wait until the background thread is actually waiting for a session.
waitingForSession.get();
fut.get(80L, TimeUnit.MILLISECONDS);
fail("missing expected timeout exception");
} catch (TimeoutException e) {
Expand All @@ -657,18 +627,7 @@ public Void call() throws Exception {
Session session = pool.getReadSession();
assertThat(session).isNotNull();
session.close();
span.end();
Tracing.getExportComponent().shutdown();
// Verify that we got a DEADLINE_EXCEEDED span for both read and read/write session.
// There might be more than 1 for each request, depending on the execution speed of
// the environment.
if (!isNoopExportComponent()) {
assertThat(deadlineExceededCount.get()).isAtLeast(2);
}
}

private boolean isNoopExportComponent() {
return Tracing.getExportComponent().getClass().getName().contains("Noop");
assertThat(pool.getNumWaiterTimeouts()).isAtLeast(2L);
}

@Test
Expand Down