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

nl.topicus.jdbc.shaded.io.grpc.internal.ConnectivityStateManager Maven / Gradle / Ivy

There is a newer version: 1.1.6
Show newest version
/*
 * Copyright 2016, gRPC Authors All rights reserved.
 *
 * 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 nl.topicus.jdbc.shaded.io.grpc.internal;

import static nl.topicus.jdbc.shaded.com.google.common.base.Preconditions.checkNotNull;
import static nl.topicus.jdbc.shaded.com.google.common.base.Preconditions.checkState;

import nl.topicus.jdbc.shaded.io.grpc.ConnectivityState;
import nl.topicus.jdbc.shaded.io.grpc.ManagedChannel;
import java.util.ArrayList;
import java.util.concurrent.Executor;
import nl.topicus.jdbc.shaded.javax.annotation.Nonnull;
import nl.topicus.jdbc.shaded.javax.annotation.Nullable;
import nl.topicus.jdbc.shaded.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 nl.topicus.jdbc.shaded.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"); checkState(!isDisabled(), "ConnectivityStateManager is already disabled"); gotoNullableState(newState); } private void gotoNullableState(@Nullable ConnectivityState 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; } /** * Call this method when the channel learns from the load balancer that channel state API is not * supported. */ void disable() { gotoNullableState(null); } /** * This method is threadsafe. */ boolean isDisabled() { return state == null; } 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