/**
   * Adds new participant to deployment.
   *
   * @param dep Shared deployment.
   * @param meta Request metadata.
   * @return {@code True} if participant was added.
   */
  private boolean addParticipant(SharedDeployment dep, GridDeploymentMetadata meta) {
    assert dep != null;
    assert meta != null;

    assert Thread.holdsLock(mux);

    if (!checkModeMatch(dep, meta)) return false;

    if (meta.participants() != null) {
      for (Map.Entry<UUID, GridTuple2<GridUuid, Long>> e : meta.participants().entrySet()) {
        dep.addParticipant(e.getKey(), e.getValue().get1(), e.getValue().get2());

        if (log.isDebugEnabled())
          log.debug(
              "Added new participant [nodeId="
                  + e.getKey()
                  + ", clsLdrId="
                  + e.getValue().get1()
                  + ", seqNum="
                  + e.getValue().get2()
                  + ']');
      }
    }

    if (dep.deployMode() == CONTINUOUS || meta.participants() == null) {
      if (!dep.addParticipant(meta.senderNodeId(), meta.classLoaderId(), meta.sequenceNumber())) {
        U.warn(
            log,
            "Failed to create shared mode deployment "
                + "(requested class loader was already undeployed, did sender node leave grid?) "
                + "[clsLdrId="
                + meta.classLoaderId()
                + ", senderNodeId="
                + meta.senderNodeId()
                + ']');

        return false;
      }

      if (log.isDebugEnabled())
        log.debug(
            "Added new participant [nodeId="
                + meta.senderNodeId()
                + ", clsLdrId="
                + meta.classLoaderId()
                + ", seqNum="
                + meta.sequenceNumber()
                + ']');
    }

    return true;
  }
  /**
   * Creates and caches new deployment.
   *
   * @param meta Deployment metadata.
   * @param isCache Whether or not to cache.
   * @return New deployment.
   */
  private SharedDeployment createNewDeployment(GridDeploymentMetadata meta, boolean isCache) {
    assert Thread.holdsLock(mux);

    assert meta.parentLoader() == null;

    GridUuid ldrId = GridUuid.randomUuid();

    GridDeploymentClassLoader clsLdr;

    if (meta.deploymentMode() == CONTINUOUS || meta.participants() == null) {
      // Create peer class loader.
      // Note that we are passing empty list for local P2P exclude, as it really
      // does not make sense with shared deployment.
      clsLdr =
          new GridDeploymentClassLoader(
              ldrId,
              meta.userVersion(),
              meta.deploymentMode(),
              false,
              ctx,
              ctxLdr,
              meta.classLoaderId(),
              meta.senderNodeId(),
              meta.sequenceNumber(),
              comm,
              ctx.config().getNetworkTimeout(),
              log,
              ctx.config().getPeerClassLoadingClassPathExclude(),
              ctx.config().getPeerClassLoadingMissedResourcesCacheSize(),
              meta.deploymentMode() == CONTINUOUS /* enable class byte cache in CONTINUOUS mode */);

      if (meta.participants() != null)
        for (Map.Entry<UUID, GridTuple2<GridUuid, Long>> e : meta.participants().entrySet())
          clsLdr.register(e.getKey(), e.getValue().get1(), e.getValue().get2());

      if (log.isDebugEnabled())
        log.debug(
            "Created class loader in CONTINUOUS mode or without participants "
                + "[ldr="
                + clsLdr
                + ", meta="
                + meta
                + ']');
    } else {
      assert meta.deploymentMode() == SHARED;

      // Create peer class loader.
      // Note that we are passing empty list for local P2P exclude, as it really
      // does not make sense with shared deployment.
      clsLdr =
          new GridDeploymentClassLoader(
              ldrId,
              meta.userVersion(),
              meta.deploymentMode(),
              false,
              ctx,
              ctxLdr,
              meta.participants(),
              comm,
              ctx.config().getNetworkTimeout(),
              log,
              ctx.config().getPeerClassLoadingClassPathExclude(),
              ctx.config().getPeerClassLoadingMissedResourcesCacheSize(),
              false);

      if (log.isDebugEnabled())
        log.debug(
            "Created classloader in SHARED mode with participants "
                + "[ldr="
                + clsLdr
                + ", meta="
                + meta
                + ']');
    }

    // Give this deployment a unique class loader to emphasize that this
    // ID is unique to this shared deployment and is not ID of loader on
    // sender node.
    SharedDeployment dep =
        new SharedDeployment(
            meta.deploymentMode(), clsLdr, ldrId, -1, meta.userVersion(), meta.alias());

    if (log.isDebugEnabled()) log.debug("Created new deployment: " + dep);

    if (isCache) {
      List<SharedDeployment> deps =
          F.addIfAbsent(cache, meta.userVersion(), new LinkedList<SharedDeployment>());

      assert deps != null;

      deps.add(dep);

      if (log.isDebugEnabled()) log.debug("Added deployment to cache: " + cache);
    }

    return dep;
  }