/** @throws Exception If failed. */
  private void checkRemove(CacheAtomicityMode atomicityMode) throws Exception {
    this.atomicityMode = atomicityMode;

    try {
      IgniteCache<IncorrectCacheKey, String> cache = grid(0).cache(null);

      cache.remove(new IncorrectCacheKey(0));

      fail("Key without hashCode()/equals() was successfully used for remove operation.");
    } catch (IllegalArgumentException e) {
      info("Catched expected exception: " + e.getMessage());

      assertTrue(
          e.getMessage().startsWith("Cache key must override hashCode() and equals() methods"));
    }
  }
  /**
   * 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);
  }
  /**
   * INternal routine for ATOMIC cache testing.
   *
   * @param caches Caches.
   * @throws Exception If failed.
   */
  private void testAtomic0(IgniteCache<Integer, Object>[] caches) throws Exception {
    byte[] val = wrap(1);

    for (IgniteCache<Integer, Object> cache : caches) {
      cache.put(KEY_1, val);

      for (IgniteCache<Integer, Object> cacheInner : caches)
        assertArrayEquals(val, (byte[]) cacheInner.get(KEY_1));

      cache.remove(KEY_1);

      assertNull(cache.get(KEY_1));
    }
  }
  /**
   * Checks that gets work for implicit txs.
   *
   * @param cache Cache to test.
   * @throws Exception If failed.
   */
  private void checkImplicitTx(IgniteCache<String, String> cache) throws Exception {
    assertNull(cache.get("key1"));

    IgniteCache<String, String> asyncCache = cache.withAsync();

    asyncCache.get("key2");

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

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

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

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

    cache.put("key7", "key7");
    cache.remove("key7", "key7");
    assertNull(cache.get("key7"));

    checkEmpty(cache);
  }
 @Override
 public void removeIfPresent(K key, V value, Handler<AsyncResult<Boolean>> handler) {
   execute(cache -> cache.remove(key, value), handler);
 }
  /** @throws Exception If error occur. */
  public void testBasicOps() throws Exception {
    CountDownLatch latch = new CountDownLatch(3);

    CacheEventListener lsnr = new CacheEventListener(latch);

    try {
      IgniteCache<String, String> cache1 = ignite1.cache(null);
      IgniteCache<String, String> cache2 = ignite2.cache(null);
      IgniteCache<String, String> cache3 = ignite3.cache(null);

      ignite1.events().localListen(lsnr, EVT_CACHE_OBJECT_PUT, EVT_CACHE_OBJECT_REMOVED);
      ignite2.events().localListen(lsnr, EVT_CACHE_OBJECT_PUT, EVT_CACHE_OBJECT_REMOVED);
      ignite3.events().localListen(lsnr, EVT_CACHE_OBJECT_PUT, EVT_CACHE_OBJECT_REMOVED);

      assert !cache1.containsKey("1");
      assert !cache2.containsKey("1");
      assert !cache3.containsKey("1");

      info("First put");

      cache1.put("1", "a");

      info("Start latch wait 1");

      assert latch.await(5, SECONDS);

      info("Stop latch wait 1");

      assert cache1.containsKey("1");
      assert cache2.containsKey("1");
      assert cache3.containsKey("1");

      latch = new CountDownLatch(6);

      lsnr.setLatch(latch);

      cache2.put("1", "b");
      cache3.put("1", "c");

      info("Start latch wait 2");

      assert latch.await(5, SECONDS);

      info("Stop latch wait 2");

      assert cache1.containsKey("1");
      assert cache2.containsKey("1");
      assert cache3.containsKey("1");

      latch = new CountDownLatch(3);

      lsnr.setLatch(latch);

      cache1.remove("1");

      info("Start latch wait 3");

      assert latch.await(5, SECONDS);

      info("Stop latch wait 3");

      assert !cache1.containsKey("1");
      assert !cache2.containsKey("1");
      assert !cache3.containsKey("1");
    } finally {
      ignite1.events().stopLocalListen(lsnr);
      ignite2.events().stopLocalListen(lsnr);
      ignite3.events().stopLocalListen(lsnr);
    }
  }