/**
   * Checks that gets work for implicit txs.
   *
   * @param cache Cache to test.
   * @throws Exception If failed.
   */
  private void checkExplicitTx(Ignite ignite, IgniteCache<String, String> cache) throws Exception {
    IgniteCache<String, String> asyncCache = cache.withAsync();

    Transaction tx = ignite.transactions().txStart();

    try {
      assertNull(cache.get("key1"));

      tx.commit();
    } finally {
      tx.close();
    }

    tx = ignite.transactions().txStart();

    try {
      asyncCache.get("key2");

      assertNull(asyncCache.future().get());

      tx.commit();
    } finally {
      tx.close();
    }

    tx = ignite.transactions().txStart();

    try {
      assertTrue(cache.getAll(F.asSet("key3", "key4")).isEmpty());

      tx.commit();
    } finally {
      tx.close();
    }

    tx = ignite.transactions().txStart();

    try {
      asyncCache.getAll(F.asSet("key5", "key6"));

      assertTrue(((Map) asyncCache.future().get()).isEmpty());

      tx.commit();
    } finally {
      tx.close();
    }

    tx = ignite.transactions().txStart();

    try {
      cache.put("key7", "key7");

      cache.remove("key7");

      assertNull(cache.get("key7"));

      tx.commit();
    } finally {
      tx.close();
    }

    checkEmpty(cache);
  }
  /**
   * Change topology.
   *
   * @param parent Grid to execute tasks on.
   * @param add New nodes count.
   * @param rmv Remove nodes count.
   * @param type Type of nodes to manipulate.
   */
  private static void changeTopology(Ignite parent, int add, int rmv, String type) {
    Collection<ComputeTaskFuture<?>> tasks = new ArrayList<>();

    IgniteCompute comp = parent.compute().withAsync();

    // Start nodes in parallel.
    while (add-- > 0) {
      comp.execute(ClientStartNodeTask.class, type);

      tasks.add(comp.future());
    }

    for (ComputeTaskFuture<?> task : tasks) task.get();

    // Stop nodes in sequence.
    while (rmv-- > 0) parent.compute().execute(ClientStopNodeTask.class, type);

    // Wait for node stops.
    // U.sleep(1000);

    Collection<String> gridNames = new ArrayList<>();

    for (Ignite g : G.allGrids()) gridNames.add(g.name());

    parent.log().info(">>> Available grids: " + gridNames);
  }
    /** {@inheritDoc} */
    @Override
    public Set<Long> call() throws IgniteCheckedException {
      assert ignite != null;

      if (log.isInfoEnabled())
        log.info("Running GetAndIncrementJob on node: " + ignite.cluster().localNode().id());

      IgniteAtomicSequence seq = ignite.atomicSequence(seqName, 0, true);

      assert seq != null;

      // Result set.
      Set<Long> resSet = new HashSet<>();

      // Get sequence value and try to put it result set.
      for (int i = 0; i < retries; i++) {
        long val = seq.getAndIncrement();

        assert !resSet.contains(val) : "Element already in set : " + val;

        resSet.add(val);
      }

      return resSet;
    }
  /**
   * Tests preset eviction policy.
   *
   * @throws Exception If failed.
   */
  private void checkPolicy0() throws Exception {
    for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
      txConcurrency = concurrency;

      for (TransactionIsolation isolation : TransactionIsolation.values()) {
        txIsolation = isolation;

        Ignite g = startGrids();

        IgniteCache<String, String> cache = g.cache(null);

        try {
          info(
              ">>> Checking policy [txConcurrency="
                  + txConcurrency
                  + ", txIsolation="
                  + txIsolation
                  + ", plc="
                  + plc
                  + ", nearPlc="
                  + nearPlc
                  + ']');

          checkExplicitTx(g, cache);

          checkImplicitTx(cache);
        } finally {
          stopAllGrids();
        }
      }
    }
  }
 /**
  * Injects resources.
  *
  * @param ignite Ignite
  */
 @IgniteInstanceResource
 private void injectResources(Ignite ignite) {
   if (ignite != null) {
     // Inject resources.
     gridName = ignite.name();
     locNodeId = ignite.configuration().getNodeId();
   } else {
     // Cleanup resources.
     gridName = null;
     locNodeId = null;
   }
 }
  /** {@inheritDoc} */
  @Override
  protected void beforeTestsStarted() throws Exception {
    chunk = new byte[128];

    for (int i = 0; i < chunk.length; i++) chunk[i] = (byte) i;

    Ignite igniteSecondary =
        startGridWithIgfs("grid-secondary", "igfs-secondary", PRIMARY, null, SECONDARY_REST_CFG);

    IgfsSecondaryFileSystem hadoopFs =
        new IgniteHadoopIgfsSecondaryFileSystem(SECONDARY_URI, SECONDARY_CFG);

    Ignite ignite = startGridWithIgfs("grid", "igfs", mode, hadoopFs, PRIMARY_REST_CFG);

    igfsSecondary = (IgfsImpl) igniteSecondary.fileSystem("igfs-secondary");
    igfs = (IgfsImpl) ignite.fileSystem("igfs");
  }
  /** @throws Exception if error occur. */
  @SuppressWarnings("unchecked")
  private void checkGar() throws Exception {
    initGar = true;

    String garDir = "modules/extdata/p2p/deploy";
    String garFileName = "p2p.gar";

    File origGarPath = U.resolveIgnitePath(garDir + '/' + garFileName);

    File tmpPath = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());

    if (!tmpPath.mkdir()) throw new IOException("Can not create temp directory");

    try {
      File newGarFile = new File(tmpPath, garFileName);

      U.copy(origGarPath, newGarFile, false);

      assert newGarFile.exists();

      try {
        garFile = "file:///" + tmpPath.getAbsolutePath();

        try {
          Ignite ignite1 = startGrid(1);
          Ignite ignite2 = startGrid(2);

          Integer res =
              ignite1
                  .compute()
                  .<UUID, Integer>execute(TASK_NAME, ignite2.cluster().localNode().id());

          assert res != null;
        } finally {
          stopGrid(1);
          stopGrid(2);
        }
      } finally {
        if (newGarFile != null && !newGarFile.delete()) error("Can not delete temp gar file");
      }
    } finally {
      if (!tmpPath.delete()) error("Can not delete temp directory");
    }
  }
  /**
   * Checks for explicit events configuration.
   *
   * @param ignite Grid instance.
   * @return {@code true} if all task events explicitly specified in configuration.
   */
  public static boolean checkExplicitTaskMonitoring(Ignite ignite) {
    int[] evts = ignite.configuration().getIncludeEventTypes();

    if (F.isEmpty(evts)) return false;

    for (int evt : VISOR_TASK_EVTS) {
      if (!F.contains(evts, evt)) return false;
    }

    return true;
  }
  /** {@inheritDoc} */
  @Override
  protected Object executeJob(int gridSize, String type) {
    log.info(">>> Starting new grid node [currGridSize=" + gridSize + ", arg=" + type + "]");

    if (type == null) throw new IllegalArgumentException("Node type to start should be specified.");

    IgniteConfiguration cfg = getConfig(type);

    // Generate unique for this VM grid name.
    String gridName = cfg.getGridName() + " (" + UUID.randomUUID() + ")";

    // Update grid name (required to be unique).
    cfg.setGridName(gridName);

    // Start new node in current VM.
    Ignite g = G.start(cfg);

    log.info(
        ">>> Grid started [nodeId=" + g.cluster().localNode().id() + ", name='" + g.name() + "']");

    return true;
  }
  /**
   * Example for start/stop node tasks.
   *
   * @param args Not used.
   */
  public static void main(String[] args) {
    String nodeType = "tcp+ssl";

    // Start initial node = 1
    try (Ignite g = G.start(NODE_CFG.get(nodeType))) {
      // Change topology.
      changeTopology(g, 4, 1, nodeType);
      changeTopology(g, 1, 4, nodeType);

      // Stop node by id = 0
      g.compute().execute(ClientStopNodeTask.class, g.cluster().localNode().id().toString());

      // Wait for node stops.
      // U.sleep(1000);

      assert G.allGrids().isEmpty();
    } catch (Exception e) {
      System.err.println("Uncaught exception: " + e.getMessage());

      e.printStackTrace(System.err);
    }
  }
  /**
   * Test what happens if peer class loading is disabled.
   *
   * @throws Exception if error occur.
   */
  @SuppressWarnings("unchecked")
  private void checkClassNotFound() throws Exception {
    initGar = false;

    try {
      Ignite ignite1 = startGrid(1);
      Ignite ignite2 = startGrid(2);

      Class task = extLdr.loadClass(TASK_NAME);

      try {
        ignite1.compute().execute(task, ignite2.cluster().localNode().id());

        assert false;
      } catch (IgniteException e) {
        info("Received expected exception: " + e);
      }
    } finally {
      stopGrid(1);
      stopGrid(2);
    }
  }
  /**
   * Grabs local events and detects if events was lost since last poll.
   *
   * @param ignite Target grid.
   * @param evtOrderKey Unique key to take last order key from node local map.
   * @param evtThrottleCntrKey Unique key to take throttle count from node local map.
   * @param evtTypes Event types to collect.
   * @param evtMapper Closure to map grid events to Visor data transfer objects.
   * @return Collections of node events
   */
  public static Collection<VisorGridEvent> collectEvents(
      Ignite ignite,
      String evtOrderKey,
      String evtThrottleCntrKey,
      final int[] evtTypes,
      IgniteClosure<Event, VisorGridEvent> evtMapper) {
    assert ignite != null;
    assert evtTypes != null && evtTypes.length > 0;

    ConcurrentMap<String, Long> nl = ignite.cluster().nodeLocalMap();

    final long lastOrder = getOrElse(nl, evtOrderKey, -1L);
    final long throttle = getOrElse(nl, evtThrottleCntrKey, 0L);

    // When we first time arrive onto a node to get its local events,
    // we'll grab only last those events that not older than given period to make sure we are
    // not grabbing GBs of data accidentally.
    final long notOlderThan = System.currentTimeMillis() - EVENTS_COLLECT_TIME_WINDOW;

    // Flag for detecting gaps between events.
    final AtomicBoolean lastFound = new AtomicBoolean(lastOrder < 0);

    IgnitePredicate<Event> p =
        new IgnitePredicate<Event>() {
          /** */
          private static final long serialVersionUID = 0L;

          @Override
          public boolean apply(Event e) {
            // Detects that events were lost.
            if (!lastFound.get() && (lastOrder == e.localOrder())) lastFound.set(true);

            // Retains events by lastOrder, period and type.
            return e.localOrder() > lastOrder
                && e.timestamp() > notOlderThan
                && F.contains(evtTypes, e.type());
          }
        };

    Collection<Event> evts = ignite.events().localQuery(p);

    // Update latest order in node local, if not empty.
    if (!evts.isEmpty()) {
      Event maxEvt = Collections.max(evts, EVTS_ORDER_COMPARATOR);

      nl.put(evtOrderKey, maxEvt.localOrder());
    }

    // Update throttle counter.
    if (!lastFound.get())
      nl.put(evtThrottleCntrKey, throttle == 0 ? EVENTS_LOST_THROTTLE : throttle - 1);

    boolean lost = !lastFound.get() && throttle == 0;

    Collection<VisorGridEvent> res = new ArrayList<>(evts.size() + (lost ? 1 : 0));

    if (lost) res.add(new VisorGridEventsLost(ignite.cluster().localNode().id()));

    for (Event e : evts) {
      VisorGridEvent visorEvt = evtMapper.apply(e);

      if (visorEvt != null) res.add(visorEvt);
    }

    return res;
  }
  /** @throws Exception If failed. */
  private void doTest() throws Exception {
    System.gc();
    System.gc();
    System.gc();

    try {
      useCache = true;

      startGridsMultiThreaded(GRID_CNT);

      useCache = false;

      Ignite ignite = startGrid();

      final IgniteDataStreamer<Integer, String> ldr = ignite.dataStreamer(null);

      ldr.perNodeBufferSize(8192);
      ldr.receiver(DataStreamerCacheUpdaters.<Integer, String>batchedSorted());
      ldr.autoFlushFrequency(0);

      final LongAdder8 cnt = new LongAdder8();

      long start = U.currentTimeMillis();

      Thread t =
          new Thread(
              new Runnable() {
                @SuppressWarnings("BusyWait")
                @Override
                public void run() {
                  while (true) {
                    try {
                      Thread.sleep(10000);
                    } catch (InterruptedException ignored) {
                      break;
                    }

                    info(">>> Adds/sec: " + cnt.sumThenReset() / 10);
                  }
                }
              });

      t.setDaemon(true);

      t.start();

      int threadNum = 2; // Runtime.getRuntime().availableProcessors();

      multithreaded(
          new Callable<Object>() {
            @SuppressWarnings("InfiniteLoopStatement")
            @Override
            public Object call() throws Exception {
              ThreadLocalRandom8 rnd = ThreadLocalRandom8.current();

              while (true) {
                int i = rnd.nextInt(ENTRY_CNT);

                ldr.addData(i, vals[rnd.nextInt(vals.length)]);

                cnt.increment();
              }
            }
          },
          threadNum,
          "loader");

      info("Closing loader...");

      ldr.close(false);

      long duration = U.currentTimeMillis() - start;

      info("Finished performance test. Duration: " + duration + "ms.");
    } finally {
      stopAllGrids();
    }
  }