Refine search
@Test public void closeAfterInitialCreateDoesNotBlockIndefinitely() throws Exception { pool.getReadSession().close(); pool.closeAsync().get(); }
static SessionPool createPool( SessionPoolOptions poolOptions, ExecutorFactory<ScheduledExecutorService> executorFactory, DatabaseId db, SpannerImpl spanner, Clock clock) { SessionPool pool = new SessionPool(poolOptions, executorFactory, executorFactory.get(), db, spanner, clock); pool.initPool(); return pool; }
@Test public void getMultipleReadWriteSessions() { Session mockSession1 = mockSession(); Session mockSession2 = mockSession(); when(client.createSession(db)).thenReturn(mockSession1).thenReturn(mockSession2); pool = createPool(); Session session1 = pool.getReadWriteSession(); Session session2 = pool.getReadWriteSession(); verify(mockSession1).prepareReadWriteTransaction(); verify(mockSession2).prepareReadWriteTransaction(); session1.close(); session2.close(); }
private void invalidateSession(PooledSession session) { synchronized (lock) { if (isClosed()) { return; } allSessions.remove(session); // replenish the pool. createSession(); } }
private void closeSession(PooledSession sess) { try { sess.delegate.close(); } catch (SpannerException e) { // Backend will delete these sessions after a while even if we fail to close them. if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Failed to close session: " + sess.getName(), e); } } finally { synchronized (lock) { allSessions.remove(sess); if (isClosed()) { decrementPendingClosures(); return; } // Create a new session if needed to unblock some waiter. if (numWaiters() > numSessionsBeingCreated) { createSession(); } } } }
@Test public void keepAlive() throws Exception { options = SessionPoolOptions.newBuilder().setMinSessions(2).setMaxSessions(3).build(); Session session = mockSession(); mockKeepAlive(session); // This is cheating as we are returning the same session each but it makes the verification // easier. when(client.createSession(db)).thenReturn(session); FakeClock clock = new FakeClock(); clock.currentTimeMillis = System.currentTimeMillis(); pool = createPool(clock); Session session1 = pool.getReadSession(); Session session2 = pool.getReadSession(); session1.close(); session2.close(); runMaintainanceLoop(clock, pool, pool.poolMaintainer.numKeepAliveCycles); verify(session, never()).singleUse(any(TimestampBound.class)); runMaintainanceLoop(clock, pool, pool.poolMaintainer.numKeepAliveCycles); verify(session, times(2)).singleUse(any(TimestampBound.class)); clock.currentTimeMillis += clock.currentTimeMillis + 35 * 60 * 1000; session1 = pool.getReadSession(); session1.writeAtLeastOnce(new ArrayList<Mutation>()); session1.close(); runMaintainanceLoop(clock, pool, pool.poolMaintainer.numKeepAliveCycles); verify(session, times(3)).singleUse(any(TimestampBound.class)); pool.closeAsync().get(); }
@Test public void getReadSessionFallsBackToWritePreparedSession() throws Exception { Session mockSession1 = mockSession(); final CountDownLatch prepareLatch = new CountDownLatch(2); doAnswer( new Answer<Void>() { @Override public Void answer(InvocationOnMock arg0) throws Throwable { prepareLatch.countDown(); return null; } }) .when(mockSession1) .prepareReadWriteTransaction(); when(client.createSession(db)).thenReturn(mockSession1); options = SessionPoolOptions.newBuilder() .setMinSessions(minSessions) .setMaxSessions(1) .setWriteSessionsFraction(1.0f) .build(); pool = createPool(); pool.getReadWriteSession().close(); prepareLatch.await(); // This session should also be write prepared. PooledSession readSession = (PooledSession) pool.getReadSession(); verify(readSession.delegate, times(2)).prepareReadWriteTransaction(); }
@Override public void run() { Uninterruptibles.awaitUninterruptibly(releaseThreads); for (int j = 0; j < numOperationsPerThread; j++) { try { Session session = null; if (random.nextInt(10) < writeOperationFraction) { session = pool.getReadWriteSession(); assertWritePrepared(session); } else { session = pool.getReadSession(); } Uninterruptibles.sleepUninterruptibly( random.nextInt(5), TimeUnit.MILLISECONDS); resetTransaction(session); session.close(); } catch (SpannerException e) { if (e.getErrorCode() != ErrorCode.RESOURCE_EXHAUSTED || shouldBlock) { setFailed(e); } } catch (Exception e) { setFailed(e); } } threadsDone.countDown(); } })
@Test public void closeWhenSessionsActiveFinishes() throws Exception { Session session = pool.getReadSession(); pool.closeAsync().get(); } }
@Override public ReadContext singleUse() { Span span = tracer.spanBuilder(READ_ONLY_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadSession().singleUse(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public ReadOnlyTransaction singleUseReadOnlyTransaction() { Span span = tracer.spanBuilder(READ_ONLY_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadSession().singleUseReadOnlyTransaction(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public ReadOnlyTransaction readOnlyTransaction(TimestampBound bound) { Span span = tracer.spanBuilder(READ_ONLY_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadSession().readOnlyTransaction(bound); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Test public void sessionCreation() { try (Session session = pool.getReadSession()) { assertThat(session).isNotNull(); } try (Session session = pool.getReadSession()) { assertThat(session).isNotNull(); Session session2 = pool.getReadSession(); assertThat(session2).isNotNull(); session2.close(); } }
.prepareReadWriteTransaction(); doAnswer( new Answer<Void>() { .prepareReadWriteTransaction(); when(client.createSession(db)).thenReturn(mockSession1).thenReturn(mockSession2); PooledSession readSession = (PooledSession) pool.getReadSession(); PooledSession writeSession = (PooledSession) pool.getReadWriteSession(); verify(writeSession.delegate, times(1)).prepareReadWriteTransaction(); verify(readSession.delegate, never()).prepareReadWriteTransaction(); readSession.close();
@Test public void getReadWriteSession() { Session mockSession = mockSession(); when(client.createSession(db)).thenReturn(mockSession); pool = createPool(); try (Session session = pool.getReadWriteSession()) { assertThat(session).isNotNull(); verify(mockSession).prepareReadWriteTransaction(); } }
@Override public Timestamp writeAtLeastOnce(Iterable<Mutation> mutations) throws SpannerException { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().writeAtLeastOnce(mutations); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } finally { span.end(); } }
@Override public TransactionRunner readWriteTransaction() { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().readWriteTransaction(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
if (readSession != null) { span.addAnnotation("Acquired read only session. Preparing for read write transaction"); prepareSession(readSession); } else { span.addAnnotation("No session available"); maybeCreateSession(); incrementNumSessionsInUse(); span.addAnnotation(sessionAnnotation(sess)); return sess;
@Override public DatabaseClient getDatabaseClient(DatabaseId db) { synchronized (this) { Preconditions.checkState(!spannerIsClosed, "Cloud Spanner client has been closed"); if (dbClients.containsKey(db)) { return dbClients.get(db); } else { SessionPool pool = SessionPool.createPool(getOptions(), db, SpannerImpl.this); DatabaseClientImpl dbClient = new DatabaseClientImpl(pool); dbClients.put(db, dbClient); return dbClient; } } }
@Test public void poolClosesEvenIfPreparationFails() throws Exception { Session session = mockSession(); when(client.createSession(db)).thenReturn(session); final CountDownLatch insidePrepare = new CountDownLatch(1); final CountDownLatch releasePrepare = new CountDownLatch(1); doAnswer( new Answer<Session>() { @Override public Session answer(InvocationOnMock invocation) throws Throwable { insidePrepare.countDown(); releasePrepare.await(); throw SpannerExceptionFactory.newSpannerException(new RuntimeException()); } }) .when(session) .prepareReadWriteTransaction(); pool = createPool(); AtomicBoolean failed = new AtomicBoolean(false); CountDownLatch latch = new CountDownLatch(1); getReadWriteSessionAsync(latch, failed); insidePrepare.await(); ListenableFuture<Void> f = pool.closeAsync(); releasePrepare.countDown(); f.get(); assertThat(f.isDone()).isTrue(); }