/**
   * Configure and start the load balancer
   *
   * @throws LoadBalancerExtensionException if configuration or start process fails
   */
  private void configureAndStart() throws LoadBalancerExtensionException {
    // Initialize topology
    if (!topologyEventReceiver.isInitialized()) {
      topologyEventReceiver.initializeTopology();
    }

    // Configure load balancer
    Topology topology = topologyProvider.getTopology();
    if (topologyPopulated(topology) && loadBalancer.configure(topology)) {
      // Start load balancer
      loadBalancer.start();
      loadBalancerStarted = true;
    }
  }
  /**
   * Start topology event receiver thread.
   *
   * @param executorService executor service instance
   * @param topologyProvider topology provider instance
   */
  private void startTopologyEventReceiver(
      ExecutorService executorService, TopologyProvider topologyProvider) {
    // Enforcing the listener order in order execute extension listener later
    topologyEventReceiver = new LoadBalancerCommonTopologyEventReceiver(topologyProvider, false);
    // Add load-balancer extension event listener
    addTopologyEventListeners(topologyEventReceiver);
    // Add default topology provider event listeners
    topologyEventReceiver.addEventListeners();
    topologyEventReceiver.setExecutorService(executorService);
    topologyEventReceiver.execute();
    if (log.isInfoEnabled()) {
      log.info("Topology receiver thread started");
    }

    if (log.isInfoEnabled()) {
      if (TopologyServiceFilter.getInstance().isActive()) {
        log.info(
            String.format(
                "Service filter activated: [filter] %s",
                TopologyServiceFilter.getInstance().toString()));
      }

      if (TopologyClusterFilter.getInstance().isActive()) {
        log.info(
            String.format(
                "Cluster filter activated: [filter] %s",
                TopologyClusterFilter.getInstance().toString()));
      }

      if (TopologyMemberFilter.getInstance().isActive()) {
        log.info(
            String.format(
                "Member filter activated: [filter] %s",
                TopologyMemberFilter.getInstance().toString()));
      }
    }
  }
  /** Stop load balancer instance. */
  public void stop() {
    try {
      if (topologyEventReceiver != null) {
        topologyEventReceiver.terminate();
      }
    } catch (Exception ignore) {
    }

    try {
      if (statisticsNotifier != null) {
        statisticsNotifier.terminate();
      }
    } catch (Exception ignore) {
    }

    try {
      loadBalancer.stop();
    } catch (Exception ignore) {
    }
  }
  /**
   * Add topology event listeners to the topology event receiver.
   *
   * @param topologyEventReceiver topology event receiver instance
   */
  private void addTopologyEventListeners(
      final LoadBalancerCommonTopologyEventReceiver topologyEventReceiver) {
    topologyEventReceiver.addEventListener(
        new CompleteTopologyEventListener() {

          @Override
          protected void onEvent(Event event) {
            try {
              if (!loadBalancerStarted) {
                configureAndStart();
              }
            } catch (Exception e) {
              if (log.isErrorEnabled()) {
                log.error("Could not start load balancer", e);
              }
              stop();
            }
          }
        });
    topologyEventReceiver.addEventListener(
        new MemberActivatedEventListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
    topologyEventReceiver.addEventListener(
        new MemberSuspendedEventListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
    topologyEventReceiver.addEventListener(
        new MemberTerminatedEventListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
    topologyEventReceiver.addEventListener(
        new ClusterRemovedEventListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
    topologyEventReceiver.addEventListener(
        new ServiceRemovedEventListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
    topologyEventReceiver.addEventListener(
        new MemberMaintenanceListener() {
          @Override
          protected void onEvent(Event event) {
            reloadConfiguration();
          }
        });
  }