/**
   * Removes given value from the set and returns the instance stored in the set or {@code null} if
   * value was not found.
   *
   * @param val Value to remove.
   * @return The instance that was stored in the set or {@code null}.
   */
  @Nullable
  public V removex(V val) {
    A.notNull(val, "val");

    if (comp == null || !strict) {
      for (Iterator<V> it = vals.iterator(); it.hasNext(); ) {
        V v = it.next();

        if (v.equals(val)) {
          it.remove();

          return v;
        }
      }

      return null;
    }

    assert comp != null && strict;

    for (Iterator<V> it = vals.iterator(); it.hasNext(); ) {
      V v = it.next();

      // Prefer equals to comparator.
      if (v.equals(val)) {
        it.remove();

        return v;
      }

      if (comp.compare(v, val) > 0) break;
    }

    return null;
  }
  /**
   * Waits for renting partitions.
   *
   * @return {@code True} if mapping was changed.
   * @throws IgniteCheckedException If failed.
   */
  private boolean waitForRent() throws IgniteCheckedException {
    boolean changed = false;

    // Synchronously wait for all renting partitions to complete.
    for (Iterator<GridDhtLocalPartition> it = locParts.values().iterator(); it.hasNext(); ) {
      GridDhtLocalPartition p = it.next();

      GridDhtPartitionState state = p.state();

      if (state == RENTING || state == EVICTED) {
        if (log.isDebugEnabled()) log.debug("Waiting for renting partition: " + p);

        // Wait for partition to empty out.
        p.rent(true).get();

        if (log.isDebugEnabled()) log.debug("Finished waiting for renting partition: " + p);

        // Remove evicted partition.
        it.remove();

        changed = true;
      }
    }

    return changed;
  }
  /** {@inheritDoc} */
  @Override
  public void finishUnmarshal(GridCacheSharedContext ctx, ClassLoader ldr)
      throws IgniteCheckedException {
    super.finishUnmarshal(ctx, ldr);

    if (writes != null) unmarshalTx(writes, false, ctx, ldr);

    if (reads != null) unmarshalTx(reads, false, ctx, ldr);

    if (grpLockKeyBytes != null && grpLockKey == null)
      grpLockKey = ctx.marshaller().unmarshal(grpLockKeyBytes, ldr);

    if (dhtVerKeys != null && dhtVers == null) {
      assert dhtVerVals != null;
      assert dhtVerKeys.size() == dhtVerVals.size();

      Iterator<IgniteTxKey> keyIt = dhtVerKeys.iterator();
      Iterator<GridCacheVersion> verIt = dhtVerVals.iterator();

      dhtVers = U.newHashMap(dhtVerKeys.size());

      while (keyIt.hasNext()) {
        IgniteTxKey key = keyIt.next();

        key.finishUnmarshal(ctx.cacheContext(key.cacheId()), ldr);

        dhtVers.put(key, verIt.next());
      }
    }

    if (txNodesBytes != null) txNodes = ctx.marshaller().unmarshal(txNodesBytes, ldr);
  }
  /** {@inheritDoc} */
  @Override
  public void explicitUndeploy(UUID nodeId, String rsrcName) {
    Collection<SharedDeployment> undeployed = new LinkedList<SharedDeployment>();

    synchronized (mux) {
      for (Iterator<List<SharedDeployment>> i1 = cache.values().iterator(); i1.hasNext(); ) {
        List<SharedDeployment> deps = i1.next();

        for (Iterator<SharedDeployment> i2 = deps.iterator(); i2.hasNext(); ) {
          SharedDeployment dep = i2.next();

          if (dep.hasName(rsrcName)) {
            if (!dep.isUndeployed()) {
              dep.undeploy();

              dep.onRemoved();

              // Undeploy.
              i2.remove();

              undeployed.add(dep);

              if (log.isInfoEnabled()) log.info("Undeployed per-version class loader: " + dep);
            }

            break;
          }
        }

        if (deps.isEmpty()) i1.remove();
      }
    }

    recordUndeployed(null, undeployed);
  }
  /** {@inheritDoc} */
  @Override
  public void loadCache(GridBiInClosure<K, V> c, @Nullable Object... args) throws GridException {
    ExecutorService exec =
        new ThreadPoolExecutor(
            threadsCnt,
            threadsCnt,
            0L,
            MILLISECONDS,
            new ArrayBlockingQueue<Runnable>(batchQueueSize),
            new BlockingRejectedExecutionHandler());

    Iterator<I> iter = inputIterator(args);

    Collection<I> buf = new ArrayList<>(batchSize);

    try {
      while (iter.hasNext()) {
        if (Thread.currentThread().isInterrupted()) {
          U.warn(log, "Working thread was interrupted while loading data.");

          break;
        }

        buf.add(iter.next());

        if (buf.size() == batchSize) {
          exec.submit(new Worker(c, buf, args));

          buf = new ArrayList<>(batchSize);
        }
      }

      if (!buf.isEmpty()) exec.submit(new Worker(c, buf, args));
    } catch (RejectedExecutionException ignored) {
      // Because of custom RejectedExecutionHandler.
      assert false : "RejectedExecutionException was thrown while it shouldn't.";
    } finally {
      exec.shutdown();

      try {
        exec.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
      } catch (InterruptedException ignored) {
        U.warn(log, "Working thread was interrupted while waiting for put operations to complete.");

        Thread.currentThread().interrupt();
      }
    }
  }
 private void computeEffects(final Iterator<WakfuEffect> it) {
   while (it.hasNext()) {
     final WakfuEffect effect = it.next();
     if (this.isMergeable(effect)) {
       final WakfuEffect wakfuEffect = this.findEffectWithActionId(effect.getActionId());
       if (wakfuEffect != null) {
         final float[] toAddParams = effect.getRawParams();
         final float[] sourceParams = wakfuEffect.getRawParams();
         for (int i = 0, size = sourceParams.length; i < size; i += 2) {
           final float[] array = sourceParams;
           final int n = i;
           array[n] += toAddParams[i];
         }
       } else {
         this.m_effects.add(effect.clone());
       }
     } else {
       this.m_effects.add(effect);
     }
   }
 }
  /**
   * @param ldr Class loader to undeploy.
   * @param recEvt Whether or not to record the event.
   */
  private void undeploy(ClassLoader ldr, boolean recEvt) {
    Collection<GridDeployment> doomed = new HashSet<GridDeployment>();

    synchronized (mux) {
      for (Iterator<LinkedList<GridDeployment>> i1 = cache.values().iterator(); i1.hasNext(); ) {
        LinkedList<GridDeployment> deps = i1.next();

        for (Iterator<GridDeployment> i2 = deps.iterator(); i2.hasNext(); ) {
          GridDeployment dep = i2.next();

          if (dep.classLoader() == ldr) {
            dep.undeploy();

            i2.remove();

            doomed.add(dep);

            if (log.isInfoEnabled()) {
              log.info("Removed undeployed class: " + dep);
            }
          }
        }

        if (deps.isEmpty()) {
          i1.remove();
        }
      }
    }

    for (GridDeployment dep : doomed) {
      if (dep.isObsolete()) {
        // Resource cleanup.
        ctx.resource().onUndeployed(dep);
      }

      if (recEvt) {
        recordUndeploy(dep, true);
      }
    }
  }
    /** {@inheritDoc} */
    @Override
    public Class<?> deployClass() {
      if (cls == null) {
        Class<?> cls0 = null;

        if (depCls != null) cls0 = depCls;
        else {
          for (Iterator<Object> it = objs.iterator();
              (cls0 == null || U.isJdk(cls0)) && it.hasNext(); ) {
            Object o = it.next();

            if (o != null) cls0 = U.detectClass(o);
          }

          if (cls0 == null || U.isJdk(cls0)) cls0 = GridDataLoaderImpl.class;
        }

        assert cls0 != null : "Failed to detect deploy class [objs=" + objs + ']';

        cls = cls0;
      }

      return cls;
    }
  /**
   * Creates REST request.
   *
   * @param cmd Command.
   * @param params Parameters.
   * @return REST request.
   * @throws GridException If creation failed.
   */
  @Nullable
  private GridRestRequest createRequest(
      GridRestCommand cmd, Map<String, Object> params, ServletRequest req) throws GridException {
    GridRestRequest restReq;

    switch (cmd) {
      case CACHE_GET:
      case CACHE_GET_ALL:
      case CACHE_PUT:
      case CACHE_PUT_ALL:
      case CACHE_REMOVE:
      case CACHE_REMOVE_ALL:
      case CACHE_ADD:
      case CACHE_CAS:
      case CACHE_METRICS:
      case CACHE_REPLACE:
      case CACHE_DECREMENT:
      case CACHE_INCREMENT:
      case CACHE_APPEND:
      case CACHE_PREPEND:
        {
          GridRestCacheRequest restReq0 = new GridRestCacheRequest();

          restReq0.cacheName((String) params.get("cacheName"));
          restReq0.key(params.get("key"));
          restReq0.value(params.get("val"));
          restReq0.value2(params.get("val2"));

          Object val1 = params.get("val1");

          if (val1 != null) restReq0.value(val1);

          restReq0.cacheFlags(intValue("cacheFlags", params, 0));
          restReq0.ttl(longValue("exp", params, null));
          restReq0.initial(longValue("init", params, null));
          restReq0.delta(longValue("delta", params, null));

          if (cmd == CACHE_GET_ALL || cmd == CACHE_PUT_ALL || cmd == CACHE_REMOVE_ALL) {
            List<Object> keys = values("k", params);
            List<Object> vals = values("v", params);

            if (keys.size() < vals.size())
              throw new GridException(
                  "Number of keys must be greater or equals to number of values.");

            Map<Object, Object> map = U.newHashMap(keys.size());

            Iterator<Object> keyIt = keys.iterator();
            Iterator<Object> valIt = vals.iterator();

            while (keyIt.hasNext()) map.put(keyIt.next(), valIt.hasNext() ? valIt.next() : null);

            restReq0.values(map);
          }

          restReq = restReq0;

          break;
        }

      case TOPOLOGY:
      case NODE:
        {
          GridRestTopologyRequest restReq0 = new GridRestTopologyRequest();

          restReq0.includeMetrics(Boolean.parseBoolean((String) params.get("mtr")));
          restReq0.includeAttributes(Boolean.parseBoolean((String) params.get("attr")));

          restReq0.nodeIp((String) params.get("ip"));

          restReq0.nodeId(uuidValue("id", params));

          restReq = restReq0;

          break;
        }

      case EXE:
      case RESULT:
      case NOOP:
        {
          GridRestTaskRequest restReq0 = new GridRestTaskRequest();

          restReq0.taskId((String) params.get("id"));
          restReq0.taskName((String) params.get("name"));

          restReq0.params(values("p", params));

          restReq0.async(Boolean.parseBoolean((String) params.get("async")));

          restReq0.timeout(longValue("timeout", params, 0L));

          restReq = restReq0;

          break;
        }

      case LOG:
        {
          GridRestLogRequest restReq0 = new GridRestLogRequest();

          restReq0.path((String) params.get("path"));

          restReq0.from(intValue("from", params, -1));
          restReq0.to(intValue("to", params, -1));

          restReq = restReq0;

          break;
        }

      case VERSION:
        {
          restReq = new GridRestRequest();

          break;
        }

      default:
        throw new GridException("Invalid command: " + cmd);
    }

    restReq.address(new InetSocketAddress(req.getRemoteAddr(), req.getRemotePort()));

    restReq.command(cmd);

    if (params.containsKey("gridgain.login") || params.containsKey("gridgain.password")) {
      GridSecurityCredentials cred =
          new GridSecurityCredentials(
              (String) params.get("gridgain.login"), (String) params.get("gridgain.password"));

      restReq.credentials(cred);
    }

    String clientId = (String) params.get("clientId");

    try {
      if (clientId != null) restReq.clientId(UUID.fromString(clientId));
    } catch (Exception ignored) {
      // Ignore invalid client id. Rest handler will process this logic.
    }

    String destId = (String) params.get("destId");

    try {
      if (destId != null) restReq.destinationId(UUID.fromString(destId));
    } catch (IllegalArgumentException ignored) {
      // Don't fail - try to execute locally.
    }

    String sesTokStr = (String) params.get("sessionToken");

    try {
      if (sesTokStr != null) restReq.sessionToken(U.hexString2ByteArray(sesTokStr));
    } catch (IllegalArgumentException ignored) {
      // Ignore invalid session token.
    }

    return restReq;
  }
  /** Clears values for this partition. */
  private void clearAll() {
    GridCacheVersion clearVer = cctx.versions().next();

    boolean swap = cctx.isSwapOrOffheapEnabled();

    boolean rec = cctx.events().isRecordable(EVT_CACHE_REBALANCE_OBJECT_UNLOADED);

    Iterator<GridDhtCacheEntry> it = map.values().iterator();

    GridCloseableIterator<Map.Entry<byte[], GridCacheSwapEntry>> swapIt = null;

    if (swap
        && GridQueryProcessor.isEnabled(cctx.config())) { // Indexing needs to unswap cache values.
      Iterator<GridDhtCacheEntry> unswapIt = null;

      try {
        swapIt = cctx.swap().iterator(id);
        unswapIt = unswapIterator(swapIt);
      } catch (Exception e) {
        U.error(log, "Failed to clear swap for evicted partition: " + this, e);
      }

      if (unswapIt != null) it = F.concat(it, unswapIt);
    }

    try {
      while (it.hasNext()) {
        GridDhtCacheEntry cached = it.next();

        try {
          if (cached.clearInternal(clearVer, swap)) {
            map.remove(cached.key(), cached);

            if (!cached.isInternal()) {
              mapPubSize.decrement();

              if (rec)
                cctx.events()
                    .addEvent(
                        cached.partition(),
                        cached.key(),
                        cctx.localNodeId(),
                        (IgniteUuid) null,
                        null,
                        EVT_CACHE_REBALANCE_OBJECT_UNLOADED,
                        null,
                        false,
                        cached.rawGet(),
                        cached.hasValue(),
                        null,
                        null,
                        null);
            }
          }
        } catch (IgniteCheckedException e) {
          U.error(log, "Failed to clear cache entry for evicted partition: " + cached, e);
        }
      }
    } finally {
      U.close(swapIt, log);
    }
  }
  /** {@inheritDoc} */
  @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
  @Nullable
  @Override
  public GridDhtPartitionMap update(
      @Nullable GridDhtPartitionExchangeId exchId, GridDhtPartitionFullMap partMap) {
    if (log.isDebugEnabled())
      log.debug(
          "Updating full partition map [exchId=" + exchId + ", parts=" + fullMapString() + ']');

    assert partMap != null;

    lock.writeLock().lock();

    try {
      if (stopping) return null;

      if (exchId != null && lastExchangeId != null && lastExchangeId.compareTo(exchId) >= 0) {
        if (log.isDebugEnabled())
          log.debug(
              "Stale exchange id for full partition map update (will ignore) [lastExchId="
                  + lastExchangeId
                  + ", exchId="
                  + exchId
                  + ']');

        return null;
      }

      if (node2part != null && node2part.compareTo(partMap) >= 0) {
        if (log.isDebugEnabled())
          log.debug(
              "Stale partition map for full partition map update (will ignore) [lastExchId="
                  + lastExchangeId
                  + ", exchId="
                  + exchId
                  + ", curMap="
                  + node2part
                  + ", newMap="
                  + partMap
                  + ']');

        return null;
      }

      long updateSeq = this.updateSeq.incrementAndGet();

      if (exchId != null) lastExchangeId = exchId;

      if (node2part != null) {
        for (GridDhtPartitionMap part : node2part.values()) {
          GridDhtPartitionMap newPart = partMap.get(part.nodeId());

          // If for some nodes current partition has a newer map,
          // then we keep the newer value.
          if (newPart != null && newPart.updateSequence() < part.updateSequence()) {
            if (log.isDebugEnabled())
              log.debug(
                  "Overriding partition map in full update map [exchId="
                      + exchId
                      + ", curPart="
                      + mapString(part)
                      + ", newPart="
                      + mapString(newPart)
                      + ']');

            partMap.put(part.nodeId(), part);
          }
        }

        for (Iterator<UUID> it = partMap.keySet().iterator(); it.hasNext(); ) {
          UUID nodeId = it.next();

          if (!cctx.discovery().alive(nodeId)) {
            if (log.isDebugEnabled())
              log.debug(
                  "Removing left node from full map update [nodeId="
                      + nodeId
                      + ", partMap="
                      + partMap
                      + ']');

            it.remove();
          }
        }
      }

      node2part = partMap;

      Map<Integer, Set<UUID>> p2n = new HashMap<>(cctx.affinity().partitions(), 1.0f);

      for (Map.Entry<UUID, GridDhtPartitionMap> e : partMap.entrySet()) {
        for (Integer p : e.getValue().keySet()) {
          Set<UUID> ids = p2n.get(p);

          if (ids == null)
            // Initialize HashSet to size 3 in anticipation that there won't be
            // more than 3 nodes per partitions.
            p2n.put(p, ids = U.newHashSet(3));

          ids.add(e.getKey());
        }
      }

      part2node = p2n;

      boolean changed = checkEvictions(updateSeq);

      consistencyCheck();

      if (log.isDebugEnabled()) log.debug("Partition map after full update: " + fullMapString());

      return changed ? localPartitionMap() : null;
    } finally {
      lock.writeLock().unlock();
    }
  }
  /** {@inheritDoc} */
  @Override
  public void onKernalStart() throws GridException {
    discoLsnr =
        new GridLocalEventListener() {
          @Override
          public void onEvent(GridEvent evt) {
            assert evt instanceof GridDiscoveryEvent;

            assert evt.type() == EVT_NODE_LEFT || evt.type() == EVT_NODE_FAILED;

            GridDiscoveryEvent discoEvt = (GridDiscoveryEvent) evt;

            Collection<SharedDeployment> undeployed = new LinkedList<SharedDeployment>();

            if (log.isDebugEnabled()) log.debug("Processing node departure event: " + evt);

            synchronized (mux) {
              for (Iterator<List<SharedDeployment>> i1 = cache.values().iterator();
                  i1.hasNext(); ) {
                List<SharedDeployment> deps = i1.next();

                for (Iterator<SharedDeployment> i2 = deps.iterator(); i2.hasNext(); ) {
                  SharedDeployment dep = i2.next();

                  dep.removeParticipant(discoEvt.eventNodeId());

                  if (!dep.hasParticipants()) {
                    if (dep.deployMode() == SHARED) {
                      if (!dep.isUndeployed()) {
                        dep.undeploy();

                        // Undeploy.
                        i2.remove();

                        assert !dep.isRemoved();

                        dep.onRemoved();

                        undeployed.add(dep);

                        if (log.isDebugEnabled())
                          log.debug(
                              "Undeployed class loader as there are no participating "
                                  + "nodes: "
                                  + dep);
                      }
                    } else if (log.isDebugEnabled())
                      log.debug("Preserving deployment without node participants: " + dep);
                  } else if (log.isDebugEnabled())
                    log.debug("Keeping deployment as it still has participants: " + dep);
                }

                if (deps.isEmpty()) i1.remove();
              }
            }

            recordUndeployed(discoEvt.eventNodeId(), undeployed);
          }
        };

    ctx.event().addLocalEventListener(discoLsnr, EVT_NODE_FAILED, EVT_NODE_LEFT);

    Collection<SharedDeployment> undeployed = new LinkedList<SharedDeployment>();

    synchronized (mux) {
      for (Iterator<List<SharedDeployment>> i1 = cache.values().iterator(); i1.hasNext(); ) {
        List<SharedDeployment> deps = i1.next();

        for (Iterator<SharedDeployment> i2 = deps.iterator(); i2.hasNext(); ) {
          SharedDeployment dep = i2.next();

          for (UUID nodeId : dep.getParticipantNodeIds())
            if (ctx.discovery().node(nodeId) == null) dep.removeParticipant(nodeId);

          if (!dep.hasParticipants()) {
            if (dep.deployMode() == SHARED) {
              if (!dep.isUndeployed()) {
                dep.undeploy();

                // Undeploy.
                i2.remove();

                dep.onRemoved();

                undeployed.add(dep);

                if (log.isDebugEnabled())
                  log.debug("Undeployed class loader as there are no participating nodes: " + dep);
              }
            } else if (log.isDebugEnabled())
              log.debug("Preserving deployment without node participants: " + dep);
          } else if (log.isDebugEnabled())
            log.debug("Keeping deployment as it still has participants: " + dep);
        }

        if (deps.isEmpty()) i1.remove();
      }
    }

    recordUndeployed(null, undeployed);

    if (log.isDebugEnabled()) log.debug("Registered deployment discovery listener: " + discoLsnr);
  }