public ClientSessionFactory createSessionFactory(String nodeID) throws Exception {
    TopologyMember topologyMember = topology.getMember(nodeID);

    if (HornetQLogger.LOGGER.isTraceEnabled()) {
      HornetQLogger.LOGGER.trace(
          "Creating connection factory towards "
              + nodeID
              + " = "
              + topologyMember
              + ", topology="
              + topology.describe());
    }

    if (topologyMember == null) {
      return null;
    } else if (topologyMember.getA() != null) {
      ClientSessionFactoryInternal factory =
          (ClientSessionFactoryInternal) createSessionFactory(topologyMember.getA());
      if (topologyMember.getB() != null) {
        factory.setBackupConnector(topologyMember.getA(), topologyMember.getB());
      }
      return factory;
    } else if (topologyMember.getA() == null && topologyMember.getB() != null) {
      // This shouldn't happen, however I wanted this to consider all possible cases
      ClientSessionFactoryInternal factory =
          (ClientSessionFactoryInternal) createSessionFactory(topologyMember.getB());
      return factory;
    } else {
      // it shouldn't happen
      return null;
    }
  }
  /**
   * This is directly called when the connection to the node is gone, or when the node sends a
   * disconnection. Look for callers of this method!
   */
  public void notifyNodeDown(final long eventTime, final String nodeID) {

    if (!ha) {
      // there's no topology here
      return;
    }

    if (HornetQLogger.LOGGER.isDebugEnabled()) {
      HornetQLogger.LOGGER.debug(
          "nodeDown " + this + " nodeID=" + nodeID + " as being down", new Exception("trace"));
    }

    topology.removeMember(eventTime, nodeID);

    if (clusterConnection) {
      updateArraysAndPairs();
    } else {
      synchronized (this) {
        if (topology.isEmpty()) {
          // Resetting the topology to its original condition as it was brand new
          receivedTopology = false;
          topologyArray = null;
        } else {
          updateArraysAndPairs();

          if (topology.nodes() == 1 && topology.getMember(this.nodeID) != null) {
            // Resetting the topology to its original condition as it was brand new
            receivedTopology = false;
          }
        }
      }
    }
  }
  public void notifyNodeUp(
      long uniqueEventID,
      final String nodeID,
      final Pair<TransportConfiguration, TransportConfiguration> connectorPair,
      final boolean last) {
    if (!ha) {
      // there's no topology
      return;
    }

    if (HornetQLogger.LOGGER.isDebugEnabled()) {
      HornetQLogger.LOGGER.debug(
          "NodeUp " + this + "::nodeID=" + nodeID + ", connectorPair=" + connectorPair,
          new Exception("trace"));
    }

    TopologyMember member = new TopologyMember(connectorPair.getA(), connectorPair.getB());

    topology.updateMember(uniqueEventID, nodeID, member);

    TopologyMember actMember = topology.getMember(nodeID);

    if (actMember != null
        && actMember.getConnector().getA() != null
        && actMember.getConnector().getB() != null) {
      HashSet<ClientSessionFactory> clonedFactories = new HashSet<ClientSessionFactory>();
      synchronized (factories) {
        clonedFactories.addAll(factories);
      }

      for (ClientSessionFactory factory : clonedFactories) {
        ((ClientSessionFactoryInternal) factory)
            .setBackupConnector(actMember.getConnector().getA(), actMember.getConnector().getB());
      }
    }

    updateArraysAndPairs();

    if (last) {
      synchronized (this) {
        receivedTopology = true;
        // Notify if waiting on getting topology
        notifyAll();
      }
    }
  }
  public synchronized void connectorsChanged() {
    List<DiscoveryEntry> newConnectors = discoveryGroup.getDiscoveryEntries();

    TransportConfiguration[] newInitialconnectors =
        (TransportConfiguration[])
            Array.newInstance(TransportConfiguration.class, newConnectors.size());

    int count = 0;
    for (DiscoveryEntry entry : newConnectors) {
      newInitialconnectors[count++] = entry.getConnector();

      if (ha && topology.getMember(entry.getNodeID()) == null) {
        TopologyMember member = new TopologyMember(entry.getConnector(), null);
        // on this case we set it as zero as any update coming from server should be accepted
        topology.updateMember(0, entry.getNodeID(), member);
      }
    }

    this.initialConnectors = newInitialconnectors;

    if (clusterConnection && !receivedTopology && initialConnectors.length > 0) {
      // The node is alone in the cluster. We create a connection to the new node
      // to trigger the node notification to form the cluster.

      Runnable connectRunnable =
          new Runnable() {
            public void run() {
              try {
                connect();
              } catch (HornetQException e) {
                HornetQLogger.LOGGER.errorConnectingToNodes(e);
              }
            }
          };
      if (startExecutor != null) {
        startExecutor.execute(connectRunnable);
      } else {
        connectRunnable.run();
      }
    }
  }