@Test
  @SuppressWarnings("unchecked")
  public void testTransportHandlers()
      throws NoSuchFieldException, IllegalAccessException, InterruptedException {
    InternalTestCluster internalCluster = backwardsCluster().internalCluster();
    TransportService transportService = internalCluster.getInstance(TransportService.class);
    ImmutableMap<String, TransportRequestHandler> requestHandlers = transportService.serverHandlers;

    DiscoveryNodes nodes = client().admin().cluster().prepareState().get().getState().nodes();

    DiscoveryNode selectedNode = null;
    for (DiscoveryNode node : nodes) {
      if (node.getVersion().before(Version.CURRENT)) {
        selectedNode = node;
        break;
      }
    }
    assertThat(selectedNode, notNullValue());

    final TransportRequest transportRequest = new TransportRequest() {};

    for (String action : requestHandlers.keySet()) {

      final CountDownLatch latch = new CountDownLatch(1);
      final AtomicReference<TransportException> failure = new AtomicReference<>();
      transportService.sendRequest(
          selectedNode,
          action,
          transportRequest,
          new TransportResponseHandler<TransportResponse>() {
            @Override
            public TransportResponse newInstance() {
              return new TransportResponse() {};
            }

            @Override
            public void handleResponse(TransportResponse response) {
              latch.countDown();
            }

            @Override
            public void handleException(TransportException exp) {
              failure.set(exp);
              latch.countDown();
            }

            @Override
            public String executor() {
              return ThreadPool.Names.SAME;
            }
          });
      assertThat(latch.await(5, TimeUnit.SECONDS), equalTo(true));

      if (failure.get() != null) {
        Throwable cause = failure.get().unwrapCause();
        if (isActionNotFoundExpected(selectedNode.version(), action)) {
          assertThat(cause, instanceOf(ActionNotFoundTransportException.class));
        } else {
          assertThat(cause, not(instanceOf(ActionNotFoundTransportException.class)));
          if (!(cause instanceof IndexOutOfBoundsException)) {
            cause.printStackTrace();
          }
        }
      }
    }
  }
Beispiel #2
0
    private ClusterState applyUpdate(ClusterState currentState, ClusterChangedEvent task) {
      boolean clusterStateChanged = false;
      ClusterState tribeState = task.state();
      DiscoveryNodes.Builder nodes = DiscoveryNodes.builder(currentState.nodes());
      // -- merge nodes
      // go over existing nodes, and see if they need to be removed
      for (DiscoveryNode discoNode : currentState.nodes()) {
        String markedTribeName = discoNode.attributes().get(TRIBE_NAME);
        if (markedTribeName != null && markedTribeName.equals(tribeName)) {
          if (tribeState.nodes().get(discoNode.id()) == null) {
            clusterStateChanged = true;
            logger.info("[{}] removing node [{}]", tribeName, discoNode);
            nodes.remove(discoNode.id());
          }
        }
      }
      // go over tribe nodes, and see if they need to be added
      for (DiscoveryNode tribe : tribeState.nodes()) {
        if (currentState.nodes().get(tribe.id()) == null) {
          // a new node, add it, but also add the tribe name to the attributes
          Map<String, String> tribeAttr = new HashMap<>();
          for (ObjectObjectCursor<String, String> attr : tribe.attributes()) {
            tribeAttr.put(attr.key, attr.value);
          }
          tribeAttr.put(TRIBE_NAME, tribeName);
          DiscoveryNode discoNode =
              new DiscoveryNode(
                  tribe.name(),
                  tribe.id(),
                  tribe.getHostName(),
                  tribe.getHostAddress(),
                  tribe.address(),
                  unmodifiableMap(tribeAttr),
                  tribe.version());
          clusterStateChanged = true;
          logger.info("[{}] adding node [{}]", tribeName, discoNode);
          nodes.put(discoNode);
        }
      }

      // -- merge metadata
      ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
      MetaData.Builder metaData = MetaData.builder(currentState.metaData());
      RoutingTable.Builder routingTable = RoutingTable.builder(currentState.routingTable());
      // go over existing indices, and see if they need to be removed
      for (IndexMetaData index : currentState.metaData()) {
        String markedTribeName = index.getSettings().get(TRIBE_NAME);
        if (markedTribeName != null && markedTribeName.equals(tribeName)) {
          IndexMetaData tribeIndex = tribeState.metaData().index(index.getIndex());
          clusterStateChanged = true;
          if (tribeIndex == null || tribeIndex.getState() == IndexMetaData.State.CLOSE) {
            logger.info("[{}] removing index [{}]", tribeName, index.getIndex());
            removeIndex(blocks, metaData, routingTable, index);
          } else {
            // always make sure to update the metadata and routing table, in case
            // there are changes in them (new mapping, shards moving from initializing to started)
            routingTable.add(tribeState.routingTable().index(index.getIndex()));
            Settings tribeSettings =
                Settings.builder().put(tribeIndex.getSettings()).put(TRIBE_NAME, tribeName).build();
            metaData.put(IndexMetaData.builder(tribeIndex).settings(tribeSettings));
          }
        }
      }
      // go over tribe one, and see if they need to be added
      for (IndexMetaData tribeIndex : tribeState.metaData()) {
        // if there is no routing table yet, do nothing with it...
        IndexRoutingTable table = tribeState.routingTable().index(tribeIndex.getIndex());
        if (table == null) {
          continue;
        }
        final IndexMetaData indexMetaData = currentState.metaData().index(tribeIndex.getIndex());
        if (indexMetaData == null) {
          if (!droppedIndices.contains(tribeIndex.getIndex())) {
            // a new index, add it, and add the tribe name as a setting
            clusterStateChanged = true;
            logger.info("[{}] adding index [{}]", tribeName, tribeIndex.getIndex());
            addNewIndex(tribeState, blocks, metaData, routingTable, tribeIndex);
          }
        } else {
          String existingFromTribe = indexMetaData.getSettings().get(TRIBE_NAME);
          if (!tribeName.equals(existingFromTribe)) {
            // we have a potential conflict on index names, decide what to do...
            if (ON_CONFLICT_ANY.equals(onConflict)) {
              // we chose any tribe, carry on
            } else if (ON_CONFLICT_DROP.equals(onConflict)) {
              // drop the indices, there is a conflict
              clusterStateChanged = true;
              logger.info(
                  "[{}] dropping index [{}] due to conflict with [{}]",
                  tribeName,
                  tribeIndex.getIndex(),
                  existingFromTribe);
              removeIndex(blocks, metaData, routingTable, tribeIndex);
              droppedIndices.add(tribeIndex.getIndex());
            } else if (onConflict.startsWith(ON_CONFLICT_PREFER)) {
              // on conflict, prefer a tribe...
              String preferredTribeName = onConflict.substring(ON_CONFLICT_PREFER.length());
              if (tribeName.equals(preferredTribeName)) {
                // the new one is hte preferred one, replace...
                clusterStateChanged = true;
                logger.info(
                    "[{}] adding index [{}], preferred over [{}]",
                    tribeName,
                    tribeIndex.getIndex(),
                    existingFromTribe);
                removeIndex(blocks, metaData, routingTable, tribeIndex);
                addNewIndex(tribeState, blocks, metaData, routingTable, tribeIndex);
              } // else: either the existing one is the preferred one, or we haven't seen one, carry
                // on
            }
          }
        }
      }

      if (!clusterStateChanged) {
        return currentState;
      } else {
        return ClusterState.builder(currentState)
            .incrementVersion()
            .blocks(blocks)
            .nodes(nodes)
            .metaData(metaData)
            .routingTable(routingTable.build())
            .build();
      }
    }
    @Override
    protected void doSample() {
      HashSet<DiscoveryNode> newNodes = new HashSet<>();
      HashSet<DiscoveryNode> newFilteredNodes = new HashSet<>();
      for (DiscoveryNode listedNode : listedNodes) {
        if (!transportService.nodeConnected(listedNode)) {
          try {
            // its a listed node, light connect to it...
            logger.trace("connecting to listed node (light) [{}]", listedNode);
            transportService.connectToNodeLight(listedNode);
          } catch (Throwable e) {
            logger.debug("failed to connect to node [{}], removed from nodes list", e, listedNode);
            continue;
          }
        }
        try {
          LivenessResponse livenessResponse =
              transportService
                  .submitRequest(
                      listedNode,
                      TransportLivenessAction.NAME,
                      headers.applyTo(new LivenessRequest()),
                      TransportRequestOptions.options()
                          .withType(TransportRequestOptions.Type.STATE)
                          .withTimeout(pingTimeout),
                      new FutureTransportResponseHandler<LivenessResponse>() {
                        @Override
                        public LivenessResponse newInstance() {
                          return new LivenessResponse();
                        }
                      })
                  .txGet();
          if (!ignoreClusterName && !clusterName.equals(livenessResponse.getClusterName())) {
            logger.warn("node {} not part of the cluster {}, ignoring...", listedNode, clusterName);
            newFilteredNodes.add(listedNode);
          } else if (livenessResponse.getDiscoveryNode() != null) {
            // use discovered information but do keep the original transport address, so people can
            // control which address is exactly used.
            DiscoveryNode nodeWithInfo = livenessResponse.getDiscoveryNode();
            newNodes.add(
                new DiscoveryNode(
                    nodeWithInfo.name(),
                    nodeWithInfo.id(),
                    nodeWithInfo.getHostName(),
                    nodeWithInfo.getHostAddress(),
                    listedNode.address(),
                    nodeWithInfo.attributes(),
                    nodeWithInfo.version()));
          } else {
            // although we asked for one node, our target may not have completed initialization yet
            // and doesn't have cluster nodes
            logger.debug(
                "node {} didn't return any discovery info, temporarily using transport discovery node",
                listedNode);
            newNodes.add(listedNode);
          }
        } catch (Throwable e) {
          logger.info("failed to get node info for {}, disconnecting...", e, listedNode);
          transportService.disconnectFromNode(listedNode);
        }
      }

      nodes = validateNewNodes(newNodes);
      filteredNodes = ImmutableList.copyOf(newFilteredNodes);
    }