Search in sources :

Example 1 with PickResult

use of io.grpc.LoadBalancer.PickResult in project grpc-java by grpc.

the class OobChannel method setSubchannel.

// Must be called only once, right after the OobChannel is created.
void setSubchannel(final InternalSubchannel subchannel) {
    log.log(Level.FINE, "[{0}] Created with [{1}]", new Object[] { this, subchannel });
    subchannelImpl = new SubchannelImpl() {

        @Override
        public void shutdown() {
            subchannel.shutdown();
        }

        @Override
        ClientTransport obtainActiveTransport() {
            return subchannel.obtainActiveTransport();
        }

        @Override
        public void requestConnection() {
            subchannel.obtainActiveTransport();
        }

        @Override
        public EquivalentAddressGroup getAddresses() {
            return subchannel.getAddressGroup();
        }

        @Override
        public Attributes getAttributes() {
            return Attributes.EMPTY;
        }
    };
    subchannelPicker = new SubchannelPicker() {

        final PickResult result = PickResult.withSubchannel(subchannelImpl);

        @Override
        public PickResult pickSubchannel(PickSubchannelArgs args) {
            return result;
        }
    };
    delayedTransport.reprocess(subchannelPicker);
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Attributes(io.grpc.Attributes) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs)

Example 2 with PickResult

use of io.grpc.LoadBalancer.PickResult in project grpc-java by grpc.

the class DelayedClientTransportTest method reprocess_newStreamRacesWithReprocess.

@Test
public void reprocess_newStreamRacesWithReprocess() throws Exception {
    final CyclicBarrier barrier = new CyclicBarrier(2);
    // In both phases, we only expect the first pickSubchannel() call to block on the barrier.
    final AtomicBoolean nextPickShouldWait = new AtomicBoolean(true);
    ///////// Phase 1: reprocess() twice with the same picker
    SubchannelPicker picker = mock(SubchannelPicker.class);
    doAnswer(new Answer<PickResult>() {

        @Override
        public PickResult answer(InvocationOnMock invocation) throws Throwable {
            if (nextPickShouldWait.compareAndSet(true, false)) {
                try {
                    barrier.await();
                    return PickResult.withNoResult();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return PickResult.withNoResult();
        }
    }).when(picker).pickSubchannel(any(PickSubchannelArgs.class));
    // Because there is no pending stream yet, it will do nothing but save the picker.
    delayedTransport.reprocess(picker);
    verify(picker, never()).pickSubchannel(any(PickSubchannelArgs.class));
    Thread sideThread = new Thread("sideThread") {

        @Override
        public void run() {
            // Will call pickSubchannel and wait on barrier
            delayedTransport.newStream(method, headers, callOptions, statsTraceCtx);
        }
    };
    sideThread.start();
    PickSubchannelArgsImpl args = new PickSubchannelArgsImpl(method, headers, callOptions);
    PickSubchannelArgsImpl args2 = new PickSubchannelArgsImpl(method, headers2, callOptions);
    // Is called from sideThread
    verify(picker, timeout(5000)).pickSubchannel(args);
    // Because stream has not been buffered (it's still stuck in newStream()), this will do nothing,
    // but incrementing the picker version.
    delayedTransport.reprocess(picker);
    verify(picker).pickSubchannel(args);
    // Now let the stuck newStream() through
    barrier.await(5, TimeUnit.SECONDS);
    sideThread.join(5000);
    assertFalse("sideThread should've exited", sideThread.isAlive());
    // newStream() detects that there has been a new picker while it's stuck, thus will pick again.
    verify(picker, times(2)).pickSubchannel(args);
    barrier.reset();
    nextPickShouldWait.set(true);
    ////////// Phase 2: reprocess() with a different picker
    // Create the second stream
    Thread sideThread2 = new Thread("sideThread2") {

        @Override
        public void run() {
            // Will call pickSubchannel and wait on barrier
            delayedTransport.newStream(method, headers2, callOptions, statsTraceCtx);
        }
    };
    sideThread2.start();
    // The second stream will see the first picker
    verify(picker, timeout(5000)).pickSubchannel(args2);
    // While the first stream won't use the first picker any more.
    verify(picker, times(2)).pickSubchannel(args);
    // Now use a different picker
    SubchannelPicker picker2 = mock(SubchannelPicker.class);
    when(picker2.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withNoResult());
    delayedTransport.reprocess(picker2);
    // The pending first stream uses the new picker
    verify(picker2).pickSubchannel(args);
    // The second stream is still pending in creation, doesn't use the new picker.
    verify(picker2, never()).pickSubchannel(args2);
    // Now let the second stream finish creation
    barrier.await(5, TimeUnit.SECONDS);
    sideThread2.join(5000);
    assertFalse("sideThread2 should've exited", sideThread2.isAlive());
    // The second stream should see the new picker
    verify(picker2, timeout(5000)).pickSubchannel(args2);
    // Wrapping up
    verify(picker, times(2)).pickSubchannel(args);
    verify(picker).pickSubchannel(args2);
    verify(picker2).pickSubchannel(args);
    verify(picker2).pickSubchannel(args);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) InvocationOnMock(org.mockito.invocation.InvocationOnMock) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) CyclicBarrier(java.util.concurrent.CyclicBarrier) Test(org.junit.Test)

Example 3 with PickResult

use of io.grpc.LoadBalancer.PickResult in project grpc-java by grpc.

the class PickFirstLoadBalancerTest method nameResolutionError.

@Test
public void nameResolutionError() throws Exception {
    Status error = Status.NOT_FOUND.withDescription("nameResolutionError");
    loadBalancer.handleNameResolutionError(error);
    verify(mockHelper).updatePicker(pickerCaptor.capture());
    PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
    assertEquals(null, pickResult.getSubchannel());
    assertEquals(error, pickResult.getStatus());
    verifyNoMoreInteractions(mockHelper);
}
Also used : PickResult(io.grpc.LoadBalancer.PickResult) Test(org.junit.Test)

Example 4 with PickResult

use of io.grpc.LoadBalancer.PickResult in project grpc-java by grpc.

the class PickFirstLoadBalancerTest method nameResolutionErrorWithStateChanges.

@Test
public void nameResolutionErrorWithStateChanges() throws Exception {
    InOrder inOrder = inOrder(mockHelper);
    loadBalancer.handleSubchannelState(mockSubchannel, ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE));
    Status error = Status.NOT_FOUND.withDescription("nameResolutionError");
    loadBalancer.handleNameResolutionError(error);
    inOrder.verify(mockHelper).updatePicker(pickerCaptor.capture());
    PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
    assertEquals(null, pickResult.getSubchannel());
    assertEquals(error, pickResult.getStatus());
    loadBalancer.handleSubchannelState(mockSubchannel, ConnectivityStateInfo.forNonError(ConnectivityState.READY));
    Status error2 = Status.NOT_FOUND.withDescription("nameResolutionError2");
    loadBalancer.handleNameResolutionError(error2);
    inOrder.verify(mockHelper).updatePicker(pickerCaptor.capture());
    pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
    assertEquals(null, pickResult.getSubchannel());
    assertEquals(error2, pickResult.getStatus());
    verifyNoMoreInteractions(mockHelper);
}
Also used : InOrder(org.mockito.InOrder) PickResult(io.grpc.LoadBalancer.PickResult) Test(org.junit.Test)

Example 5 with PickResult

use of io.grpc.LoadBalancer.PickResult in project grpc-java by grpc.

the class DelayedClientTransport method newStream.

/**
   * If a {@link SubchannelPicker} is being, or has been provided via {@link #reprocess}, the last
   * picker will be consulted.
   *
   * <p>Otherwise, if the delayed transport is not shutdown, then a {@link PendingStream} is
   * returned; if the transport is shutdown, then a {@link FailingClientStream} is returned.
   */
@Override
public final ClientStream newStream(MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions, StatsTraceContext statsTraceCtx) {
    try {
        SubchannelPicker picker = null;
        PickSubchannelArgs args = new PickSubchannelArgsImpl(method, headers, callOptions);
        long pickerVersion = -1;
        synchronized (lock) {
            if (!shutdown) {
                if (lastPicker == null) {
                    return createPendingStream(args, statsTraceCtx);
                }
                picker = lastPicker;
                pickerVersion = lastPickerVersion;
            }
        }
        if (picker != null) {
            while (true) {
                PickResult pickResult = picker.pickSubchannel(args);
                ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult, callOptions.isWaitForReady());
                if (transport != null) {
                    return transport.newStream(args.getMethodDescriptor(), args.getHeaders(), args.getCallOptions(), statsTraceCtx);
                }
                // picker.
                synchronized (lock) {
                    if (shutdown) {
                        break;
                    }
                    if (pickerVersion == lastPickerVersion) {
                        return createPendingStream(args, statsTraceCtx);
                    }
                    picker = lastPicker;
                    pickerVersion = lastPickerVersion;
                }
            }
        }
        return new FailingClientStream(Status.UNAVAILABLE.withDescription("Channel has shutdown (reported by delayed transport)"));
    } finally {
        channelExecutor.drain();
    }
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs)

Aggregations

PickResult (io.grpc.LoadBalancer.PickResult)6 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)3 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)3 Test (org.junit.Test)3 Attributes (io.grpc.Attributes)1 CallOptions (io.grpc.CallOptions)1 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)1 ArrayList (java.util.ArrayList)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1 Executor (java.util.concurrent.Executor)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 InOrder (org.mockito.InOrder)1 InvocationOnMock (org.mockito.invocation.InvocationOnMock)1