All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.grpc.internal.ConnectivityStateManager Maven / Gradle / Ivy

/*
 * Copyright 2016 The gRPC Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.grpc.internal;

import static com.google.common.base.Preconditions.checkNotNull;

import io.grpc.ConnectivityState;
import io.grpc.ManagedChannel;
import java.util.ArrayList;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;

/**
 * Manages connectivity states of the channel. Used for {@link ManagedChannel#getState} to read the
 * current state of the channel, for {@link ManagedChannel#notifyWhenStateChanged} to add
 * listeners to state change events, and for {@link io.grpc.LoadBalancer.Helper#updateBalancingState
 * LoadBalancer.Helper#updateBalancingState} to update the state and run the {@link #gotoState}s.
 */
@NotThreadSafe
final class ConnectivityStateManager {
  private ArrayList listeners = new ArrayList<>();

  private volatile ConnectivityState state = ConnectivityState.IDLE;

  /**
   * Adds a listener for state change event.
   *
   * 

The {@code executor} must be one that can run RPC call listeners. */ void notifyWhenStateChanged(Runnable callback, Executor executor, ConnectivityState source) { checkNotNull(callback, "callback"); checkNotNull(executor, "executor"); checkNotNull(source, "source"); Listener stateChangeListener = new Listener(callback, executor); if (state != source) { stateChangeListener.runInExecutor(); } else { listeners.add(stateChangeListener); } } /** * Connectivity state is changed to the specified value. Will trigger some notifications that have * been registered earlier by {@link ManagedChannel#notifyWhenStateChanged}. */ void gotoState(@Nonnull ConnectivityState newState) { checkNotNull(newState, "newState"); if (state != newState && state != ConnectivityState.SHUTDOWN) { state = newState; if (listeners.isEmpty()) { return; } // Swap out callback list before calling them, because a callback may register new callbacks, // if run in direct executor, can cause ConcurrentModificationException. ArrayList savedListeners = listeners; listeners = new ArrayList<>(); for (Listener listener : savedListeners) { listener.runInExecutor(); } } } /** * Gets the current connectivity state of the channel. This method is threadsafe. */ ConnectivityState getState() { ConnectivityState stateCopy = state; if (stateCopy == null) { throw new UnsupportedOperationException("Channel state API is not implemented"); } return stateCopy; } private static final class Listener { final Runnable callback; final Executor executor; Listener(Runnable callback, Executor executor) { this.callback = callback; this.executor = executor; } void runInExecutor() { executor.execute(callback); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy