/** @throws Exception If failed. */
  public void testInternalTaskMetrics() throws Exception {
    Ignite ignite = grid();

    // Visor task is internal and should not affect metrics.
    ignite.compute().withName("visor-test-task").execute(new TestInternalTask(), "testArg");

    // Let metrics update twice.
    final CountDownLatch latch = new CountDownLatch(2);

    ignite
        .events()
        .localListen(
            new IgnitePredicate<Event>() {
              @Override
              public boolean apply(Event evt) {
                assert evt.type() == EVT_NODE_METRICS_UPDATED;

                latch.countDown();

                return true;
              }
            },
            EVT_NODE_METRICS_UPDATED);

    // Wait for metrics update.
    latch.await();

    ClusterMetrics metrics = ignite.cluster().localNode().metrics();

    info("Node metrics: " + metrics);

    assert metrics.getAverageActiveJobs() == 0;
    assert metrics.getAverageCancelledJobs() == 0;
    assert metrics.getAverageJobExecuteTime() == 0;
    assert metrics.getAverageJobWaitTime() == 0;
    assert metrics.getAverageRejectedJobs() == 0;
    assert metrics.getAverageWaitingJobs() == 0;
    assert metrics.getCurrentActiveJobs() == 0;
    assert metrics.getCurrentCancelledJobs() == 0;
    assert metrics.getCurrentJobExecuteTime() == 0;
    assert metrics.getCurrentJobWaitTime() == 0;
    assert metrics.getCurrentWaitingJobs() == 0;
    assert metrics.getMaximumActiveJobs() == 0;
    assert metrics.getMaximumCancelledJobs() == 0;
    assert metrics.getMaximumJobExecuteTime() == 0;
    assert metrics.getMaximumJobWaitTime() == 0;
    assert metrics.getMaximumRejectedJobs() == 0;
    assert metrics.getMaximumWaitingJobs() == 0;
    assert metrics.getTotalCancelledJobs() == 0;
    assert metrics.getTotalExecutedJobs() == 0;
    assert metrics.getTotalRejectedJobs() == 0;
    assert metrics.getTotalExecutedTasks() == 0;

    assertTrue(
        "MaximumJobExecuteTime="
            + metrics.getMaximumJobExecuteTime()
            + " is less than AverageJobExecuteTime="
            + metrics.getAverageJobExecuteTime(),
        metrics.getMaximumJobExecuteTime() >= metrics.getAverageJobExecuteTime());
  }
  /** @throws Exception If failed. */
  public void testIoMetrics() throws Exception {
    Ignite ignite0 = grid();
    Ignite ignite1 = startGrid(1);

    Object msg = new TestMessage();

    int size = ignite0.configuration().getMarshaller().marshal(msg).length;

    assert size > MSG_SIZE;

    final CountDownLatch latch = new CountDownLatch(MSG_CNT);

    ignite0
        .message()
        .localListen(
            null,
            new MessagingListenActor<TestMessage>() {
              @Override
              protected void receive(UUID nodeId, TestMessage rcvMsg) throws Throwable {
                latch.countDown();
              }
            });

    ignite1
        .message()
        .localListen(
            null,
            new MessagingListenActor<TestMessage>() {
              @Override
              protected void receive(UUID nodeId, TestMessage rcvMsg) throws Throwable {
                respond(rcvMsg);
              }
            });

    for (int i = 0; i < MSG_CNT; i++) message(ignite0.cluster().forRemotes()).send(null, msg);

    latch.await();

    ClusterMetrics metrics = ignite0.cluster().localNode().metrics();

    info("Node 0 metrics: " + metrics);

    // Time sync messages are being sent.
    assert metrics.getSentMessagesCount() >= MSG_CNT;
    assert metrics.getSentBytesCount() > size * MSG_CNT;
    assert metrics.getReceivedMessagesCount() >= MSG_CNT;
    assert metrics.getReceivedBytesCount() > size * MSG_CNT;

    metrics = ignite1.cluster().localNode().metrics();

    info("Node 1 metrics: " + metrics);

    // Time sync messages are being sent.
    assert metrics.getSentMessagesCount() >= MSG_CNT;
    assert metrics.getSentBytesCount() > size * MSG_CNT;
    assert metrics.getReceivedMessagesCount() >= MSG_CNT;
    assert metrics.getReceivedBytesCount() > size * MSG_CNT;
  }
  /**
   * Event callback.
   *
   * @param exchId Exchange ID.
   * @param discoEvt Discovery event.
   */
  public void onEvent(GridDhtPartitionExchangeId exchId, DiscoveryEvent discoEvt) {
    assert exchId.equals(this.exchId);

    this.discoEvt = discoEvt;

    evtLatch.countDown();
  }
  /** {@inheritDoc} */
  @Override
  public String toString() {
    ClusterNode oldestNode = this.oldestNode.get();

    return S.toString(
        GridDhtPartitionsExchangeFuture.class,
        this,
        "oldest",
        oldestNode == null ? "null" : oldestNode.id(),
        "oldestOrder",
        oldestNode == null ? "null" : oldestNode.order(),
        "evtLatch",
        evtLatch == null ? "null" : evtLatch.getCount(),
        "remaining",
        remaining(),
        "super",
        super.toString());
  }
  /**
   * JUnit.
   *
   * @throws Exception If failed.
   */
  public void testQueueRemoveMultithreadBounded() throws Exception {
    // Random queue name.
    final String queueName = UUID.randomUUID().toString();

    final IgniteQueue<String> queue = grid(0).queue(queueName, QUEUE_CAPACITY, config(false));

    final CountDownLatch putLatch = new CountDownLatch(THREAD_NUM);

    final CountDownLatch clearLatch = new CountDownLatch(THREAD_NUM);

    for (int t = 0; t < THREAD_NUM; t++) {
      Thread th =
          new Thread(
              new Runnable() {
                @Override
                public void run() {
                  if (log.isDebugEnabled())
                    log.debug("Thread has been started." + Thread.currentThread().getName());

                  try {
                    // Thread must be blocked on put operation.
                    for (int i = 0; i < (QUEUE_CAPACITY * THREAD_NUM); i++)
                      queue.offer("anything", 3, TimeUnit.MINUTES);

                    fail("Queue failed");
                  } catch (IgniteException | IllegalStateException e) {
                    putLatch.countDown();

                    assert e.getMessage().contains("removed");

                    assert queue.removed();
                  }

                  if (log.isDebugEnabled())
                    log.debug("Thread has been stopped." + Thread.currentThread().getName());
                }
              });
      th.start();
    }

    for (int t = 0; t < THREAD_NUM; t++) {
      Thread th =
          new Thread(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    IgniteQueue<String> queue = grid(0).queue(queueName, 0, null);

                    if (queue != null) queue.close();
                  } catch (Exception e) {
                    fail("Unexpected exception: " + e);
                  } finally {
                    clearLatch.countDown();
                  }
                }
              });
      th.start();
    }

    assert putLatch.await(3, TimeUnit.MINUTES);

    assert clearLatch.await(3, TimeUnit.MINUTES);

    try {
      assert queue.isEmpty() : queue.size();

      fail("Queue must be removed.");
    } catch (IgniteException | IllegalStateException e) {
      assert e.getMessage().contains("removed");

      assert queue.removed();
    }
  }