/** @param log Logger. */
    private void execute(GridLogger log) {
      try {
        log.info("Started execute.");

        // Countdown shared job latch so that the main thread know that all jobs are
        // inside the "execute" routine.
        jobLatch.countDown();

        log.info("After job latch.");

        // Await for the main thread to allow jobs to proceed.
        latch.await();

        log.info("After latch.");

        if (awaitMasterLeaveCallback) {
          latch0.await();

          log.info("After latch0.");
        } else log.info("Latch 0 skipped.");
      } catch (InterruptedException e) {
        // We do not expect any interruptions here, hence this statement.
        fail("Unexpected exception: " + e);
      }
    }
  /** {@inheritDoc} */
  @Override
  public void spiStop() throws GridSpiException {
    unregisterMBean();

    // Ack ok stop.
    if (log.isDebugEnabled()) log.debug(stopInfo());
  }
  /**
   * Method cleans up all events that either outnumber queue size or exceeds time-to-live value. It
   * does none if someone else cleans up queue (lock is locked) or if there are queue readers
   * (readersNum > 0).
   */
  private void cleanupQueue() {
    long now = U.currentTimeMillis();

    long queueOversize = evts.sizex() - expireCnt;

    for (int i = 0; i < queueOversize && evts.sizex() > expireCnt; i++) {
      GridEvent expired = evts.poll();

      if (log.isDebugEnabled()) log.debug("Event expired by count: " + expired);
    }

    while (true) {
      ConcurrentLinkedDeque8.Node<GridEvent> node = evts.peekx();

      if (node == null) // Queue is empty.
      break;

      GridEvent evt = node.item();

      if (evt == null) // Competing with another thread.
      continue;

      if (now - evt.timestamp() < expireAgeMs) break;

      if (evts.unlinkx(node) && log.isDebugEnabled())
        log.debug("Event expired by age: " + node.item());
    }
  }
  /**
   * 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;
  }
  /** {@inheritDoc} */
  @Override
  public void spiStart(String gridName) throws GridSpiException {
    assertParameter(parallelJobsNum > 0, "parallelJobsNum > 0");
    assertParameter(waitJobsNum >= 0, "waitingJobsNum >= 0");
    assertParameter(taskAttrKey != null, "taskAttrKey != null");
    assertParameter(jobAttrKey != null, "jobAttrKey != null");

    // Start SPI start stopwatch.
    startStopwatch();

    // Ack parameters.
    if (log.isDebugEnabled()) {
      log.debug(configInfo("parallelJobsNum", parallelJobsNum));
      log.debug(configInfo("taskAttrKey", taskAttrKey));
      log.debug(configInfo("jobAttrKey", jobAttrKey));
      log.debug(configInfo("dfltPriority", dfltPriority));
      log.debug(configInfo("starvationInc", starvationInc));
      log.debug(configInfo("preventStarvation", preventStarvation));
    }

    registerMBean(gridName, this, GridPriorityQueueCollisionSpiMBean.class);

    // Ack start.
    if (log.isDebugEnabled()) log.debug(startInfo());
  }
  /** {@inheritDoc} */
  @Override
  public void record(GridEvent evt) throws GridSpiException {
    assert evt != null;

    // Filter out events.
    if (filter == null || filter.apply(evt)) {
      cleanupQueue();

      evts.add(evt);

      // Make sure to filter out metrics updates to prevent log from flooding.
      if (evt.type() != EVT_NODE_METRICS_UPDATED && log.isDebugEnabled())
        log.debug("Event recorded: " + evt);
    }
  }
    /**
     * @param log Logger.
     * @param job Actual job.
     */
    private void onMasterLeave(GridLogger log, Object job) {
      log.info("Callback executed: " + job);

      latch0.countDown();

      invokeLatch.countDown();
    }
  /** {@inheritDoc} */
  @Override
  public void spiStart(String gridName) throws GridSpiException {
    // Start SPI start stopwatch.
    startStopwatch();

    assertParameter(expireCnt > 0, "expireCnt > 0");
    assertParameter(expireAgeMs > 0, "expireAgeMs > 0");

    // Ack parameters.
    if (log.isDebugEnabled()) {
      log.debug(configInfo("expireAgeMs", expireAgeMs));
      log.debug(configInfo("expireCnt", expireCnt));
    }

    registerMBean(gridName, this, GridMemoryEventStorageSpiMBean.class);

    // Ack ok start.
    if (log.isDebugEnabled()) log.debug(startInfo());
  }