/** {@inheritDoc} */
    @Override
    protected IgniteBiTuple<Long, List<IgniteExceptionRegistry.ExceptionInfo>> run(
        Map<UUID, Long> arg) {
      Long lastOrder = arg.get(ignite.localNode().id());

      long order = lastOrder != null ? lastOrder : 0;

      List<IgniteExceptionRegistry.ExceptionInfo> errors =
          ignite.context().exceptionRegistry().getErrors(order);

      List<IgniteExceptionRegistry.ExceptionInfo> wrapped = new ArrayList<>(errors.size());

      for (IgniteExceptionRegistry.ExceptionInfo error : errors) {
        if (error.order() > order) order = error.order();

        wrapped.add(
            new IgniteExceptionRegistry.ExceptionInfo(
                error.order(),
                new VisorExceptionWrapper(error.error()),
                error.message(),
                error.threadId(),
                error.threadName(),
                error.time()));
      }

      return new IgniteBiTuple<>(order, wrapped);
    }
  /**
   * Helper function to get value from map.
   *
   * @param map Map to take value from.
   * @param key Key to search in map.
   * @param ifNull Default value if {@code null} was returned by map.
   * @param <K> Key type.
   * @param <V> Value type.
   * @return Value from map or default value if map return {@code null}.
   */
  public static <K, V> V getOrElse(Map<K, V> map, K key, V ifNull) {
    assert map != null;

    V res = map.get(key);

    return res != null ? res : ifNull;
  }
  /**
   * Cache preloader should call this method within partition lock.
   *
   * @param key Key.
   * @param ver Version.
   * @return {@code True} if preloading is permitted.
   */
  public boolean preloadingPermitted(KeyCacheObject key, GridCacheVersion ver) {
    assert key != null;
    assert ver != null;
    assert lock.isHeldByCurrentThread(); // Only one thread can enter this method at a time.

    if (state() != MOVING) return false;

    Map<KeyCacheObject, GridCacheVersion> evictHist0 = evictHist;

    if (evictHist0 != null) {
      GridCacheVersion ver0 = evictHist0.get(key);

      // Permit preloading if version in history
      // is missing or less than passed in.
      return ver0 == null || ver0.isLess(ver);
    }

    return false;
  }
  /**
   * @param key Key.
   * @param ver Version.
   */
  public void onEntryEvicted(KeyCacheObject key, GridCacheVersion ver) {
    assert key != null;
    assert ver != null;
    assert lock.isHeldByCurrentThread(); // Only one thread can enter this method at a time.

    if (state() != MOVING) return;

    Map<KeyCacheObject, GridCacheVersion> evictHist0 = evictHist;

    if (evictHist0 != null) {
      GridCacheVersion ver0 = evictHist0.get(key);

      if (ver0 == null || ver0.isLess(ver)) {
        GridCacheVersion ver1 = evictHist0.put(key, ver);

        assert ver1 == ver0;
      }
    }
  }
 /** {@inheritDoc} */
 @Override
 public boolean isCacheTopologyValid(GridCacheContext cctx) {
   return cctx.config().getTopologyValidator() != null && cacheValidRes.containsKey(cctx.cacheId())
       ? cacheValidRes.get(cctx.cacheId())
       : true;
 }