/**
   * Gets job priority. At first tries to get from job context. If job context has no priority, then
   * tries to get from task session. If task session has no priority default one will be used.
   *
   * @param ctx Collision job context.
   * @return Job priority.
   */
  private int getJobPriority(GridCollisionJobContext ctx) {
    assert ctx != null;

    Integer p = null;

    GridJobContext jctx = ctx.getJobContext();

    try {
      p = (Integer) jctx.getAttribute(jobAttrKey);
    } catch (ClassCastException e) {
      LT.error(
          log,
          e,
          "Type of job context priority attribute '"
              + jobAttrKey
              + "' is not java.lang.Integer [type="
              + jctx.getAttribute(jobAttrKey).getClass()
              + ']');
    }

    if (p == null) {
      GridTaskSession ses = ctx.getTaskSession();

      try {
        p = (Integer) ses.getAttribute(taskAttrKey);
      } catch (ClassCastException e) {
        LT.error(
            log,
            e,
            "Type of task session priority attribute '"
                + taskAttrKey
                + "' is not java.lang.Integer [type="
                + ses.getAttribute(taskAttrKey).getClass()
                + ']');
      }

      if (p == null) {
        if (log.isDebugEnabled()) {
          log.debug(
              "Failed get priority from job context attribute '"
                  + jobAttrKey
                  + "' and task session attribute '"
                  + taskAttrKey
                  + "' (will use default priority): "
                  + dfltPriority);
        }

        p = dfltPriority;
      }
    }

    assert p != null;

    return p;
  }
  /**
   * Increases priority if job has bumped down.
   *
   * @param waitJobs Ordered collection of collision contexts for jobs that are currently waiting
   *     for execution.
   * @param passiveJobs Reordered collection of collision contexts for waiting jobs.
   */
  private void bumpPriority(
      Collection<GridCollisionJobContext> waitJobs, List<GridCollisionJobContext> passiveJobs) {
    assert waitJobs != null;
    assert passiveJobs != null;
    assert waitJobs.size() == passiveJobs.size();

    for (int i = 0; i < passiveJobs.size(); i++) {
      GridCollisionJobContext ctx = passiveJobs.get(i);

      if (i > indexOf(waitJobs, ctx))
        ctx.getJobContext().setAttribute(jobAttrKey, getJobPriority(ctx) + starvationInc);
    }
  }
  /** {@inheritDoc} */
  @Override
  public void onCollision(
      Collection<GridCollisionJobContext> waitJobs,
      Collection<GridCollisionJobContext> activeJobs) {
    assert waitJobs != null;
    assert activeJobs != null;

    int activeSize = F.size(activeJobs, RUNNING_JOBS);

    waitingCnt.set(waitJobs.size());
    runningCnt.set(activeSize);
    heldCnt.set(activeJobs.size() - activeSize);

    int waitSize = waitJobs.size();

    int activateCnt = parallelJobsNum - activeSize;

    if (activateCnt > 0 && !waitJobs.isEmpty()) {
      if (waitJobs.size() <= activateCnt) {
        for (GridCollisionJobContext waitJob : waitJobs) {
          waitJob.activate();

          waitSize--;
        }
      } else {
        List<GridCollisionJobContext> passiveList =
            new ArrayList<GridCollisionJobContext>(waitJobs);

        Collections.sort(
            passiveList,
            new Comparator<GridCollisionJobContext>() {
              /** {@inheritDoc} */
              @Override
              public int compare(GridCollisionJobContext o1, GridCollisionJobContext o2) {
                int p1 = getJobPriority(o1);
                int p2 = getJobPriority(o2);

                return p1 < p2 ? 1 : p1 == p2 ? 0 : -1;
              }
            });

        if (preventStarvation) bumpPriority(waitJobs, passiveList);

        for (int i = 0; i < activateCnt; i++) {
          passiveList.get(i).activate();

          waitSize--;
        }
      }
    }

    if (waitSize > waitJobsNum) {
      List<GridCollisionJobContext> waitList = new ArrayList<GridCollisionJobContext>(waitJobs);

      // Put jobs with highest priority first.
      Collections.sort(
          waitList,
          new Comparator<GridCollisionJobContext>() {
            /** {@inheritDoc} */
            @Override
            public int compare(GridCollisionJobContext o1, GridCollisionJobContext o2) {
              int p1 = getJobPriority(o1);
              int p2 = getJobPriority(o2);

              return p1 < p2 ? 1 : p1 == p2 ? 0 : -1;
            }
          });

      int skip = waitJobs.size() - waitSize;

      int i = 0;

      for (GridCollisionJobContext waitCtx : waitList) {
        if (++i >= skip) {
          waitCtx.cancel();

          if (--waitSize <= waitJobsNum) break;
        }
      }
    }
  }
 @Override
 public boolean apply(GridCollisionJobContext ctx) {
   return !ctx.getJobContext().heldcc();
 }