You are here

function elysia_cron_run in Elysia Cron 7

Same name and namespace in other branches
  1. 5.2 elysia_cron.module \elysia_cron_run()
  2. 5 elysia_cron.module \elysia_cron_run()
  3. 6.2 elysia_cron.module \elysia_cron_run()
  4. 6 elysia_cron.module \elysia_cron_run()
  5. 7.2 elysia_cron.module \elysia_cron_run()
4 calls to elysia_cron_run()
cron.php in ./cron.php
drush_elysia_cron_run_wrapper in ./elysia_cron.drush.inc
A drush command callback.
elysia_cron_cron in ./elysia_cron.module
Hook cron is invoked only by standard drupal cron. It's used to replace drupal cron.
elysia_cron_run_form_submit in ./elysia_cron.admin.inc
1 string reference to 'elysia_cron_run'
cron.php in ./cron.php

File

./elysia_cron.module, line 861

Code

function elysia_cron_run($manual_run = false) {
  global $conf;

  // Allow execution to continue even if the request gets canceled.
  @ignore_user_abort(true);

  // Try to allocate enough time to run all the hook_cron implementations.
  if (!ini_get('safe_mode')) {
    set_time_limit(variable_get('elysia_cron_time_limit', 240));
  }

  // Prevent session information from being saved while cron is running.
  if (EC_DRUPAL_VERSION >= 7) {
    drupal_save_session(FALSE);
  }

  // If DISABLED block the execution
  if (variable_get('elysia_cron_disabled', false)) {
    return;
  }

  // Check for CRON_KEY or ALLOWED_HOSTS
  if (!$manual_run) {
    $cron_key = variable_get('cron_key', '');
    if ($cron_key && !user_access('administer elysia_cron') && (empty($_GET['cron_key']) || $_GET['cron_key'] != $cron_key)) {
      return;
    }
    $allowed_hosts = variable_get('elysia_cron_allowed_hosts', false);
    if ($allowed_hosts && !user_access('administer elysia_cron') && !in_array(ip_address(), explode(",", $allowed_hosts))) {
      return;
    }
  }
  _ec_variable_set('elysia_cron_last_run', time());
  _ec_variable_set('cron_last', time());
  $execute = true;
  if (EC_DRUPAL_VERSION >= 7) {
    if (!lock_acquire('cron', 240.0)) {
      _dco_watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING);
      $execute = false;
    }
  }
  else {

    // Global Semaphore to avoid concurrent execution of cron preparation code
    $execute = _ec_semaphore_get('elysia_cron_semaphore', 120);
  }

  // Force the current user to anonymous to ensure consistent permissions on
  // cron runs (only if run by interface)
  if ($manual_run) {
    $original_user = $GLOBALS['user'];
    $GLOBALS['user'] = drupal_anonymous_user();
  }
  if (EC_DRUPAL_VERSION >= 7) {

    // D7 Queue processing
    // Grab the defined cron queues (even if execute = false)
    $queues = module_invoke_all('cron_queue_info');
    drupal_alter('cron_queue_info', $queues);
  }
  if ($execute) {
    if (EC_DRUPAL_VERSION >= 7) {

      // D7 Queue processing
      // Make sure every queue exists. There is no harm in trying to recreate an
      // existing queue.
      foreach ($queues as $queue_name => $info) {
        DrupalQueue::get($queue_name)
          ->createQueue();
      }
    }
    elysia_cron_initialize();
    global $elysia_cron_settings, $elysia_cron_settings_by_channel, $elysia_cron_current_channel, $cron_completed, $cron_completed_time;
    $channels = array_keys($elysia_cron_settings_by_channel);
    $channel = elysia_cron_last_channel();
    $i = array_search($channel, $channels);
    if ($i === FALSE) {
      $i = -1;
    }
    $k = 0;
    $jobs = false;
    $stuck_time = variable_get('elysia_cron_stuck_time', 3600);
    for ($j = ($i + 1) % count($channels); $k < count($channels); $j = ($j + 1) % count($channels)) {
      $sem = elysia_cron_is_channel_running($channels[$j]);
      if ($sem && time() - $sem > $stuck_time) {
        elysia_cron_set_channel_running($channels[$j], 0);
        $last_job = elysia_cron_execute_aborted($channels[$j]);
        unset($sem);
        _dco_watchdog('cron', 'Cron channel (%channel) has been running for more than an %stuck_time secs and is most likely stuck. Last job executed: %job', array(
          '%channel' => $channels[$j],
          '%stuck_time' => $stuck_time,
          '%job' => $last_job,
        ), WATCHDOG_ERROR);
      }
      if (empty($sem) && !$elysia_cron_settings_by_channel[$channels[$j]]['#data']['disabled']) {
        $jobs = elysia_cron_active_jobs($channels[$j]);
        if (count($jobs)) {
          break;
        }
      }
      $k++;
    }
    if ($jobs && count($jobs)) {

      // There are jobs ready to be executed
      $elysia_cron_current_channel = $channels[$j];
      elysia_cron_set_last_channel($elysia_cron_current_channel);
      if (variable_get('elysia_cron_debug_messages', 0)) {
        _dco_watchdog('cron', 'Cron channel %channel run started.', array(
          '%channel' => $elysia_cron_current_channel,
        ), WATCHDOG_NOTICE);
      }

      // Register shutdown callback
      register_shutdown_function('elysia_cron_cleanup');
      elysia_cron_set($elysia_cron_current_channel, true, array(
        'running' => time(),
        'last_run' => time(),
      ));

      // Now I can unlock cron semaphore
      if (EC_DRUPAL_VERSION < 7) {
        _ec_variable_del('elysia_cron_semaphore');

        // Some modules (feedapi, ipaper...) uses the internal "cron_semaphore" variable to detect
        // start time of cron process. I'll set this only in memory for that purpose.
        // (In normal drupal cron execution that is done by a variable_set just before this call,
        // but i need to set this manually if drupal cron is bypassed)
        $conf['cron_semaphore'] = time();
      }
      foreach ($jobs as $job) {
        $job_running = false;
        if (elysia_cron_is_job_running($job)) {
          if (time() - elysia_cron_get_job_last_run($job, 0) > variable_get('elysia_cron_stuck_time', 3600)) {
            _dco_watchdog('cron', 'Job %job is already running, but is probably stuck, so i consider it as terminated', array(
              '%job' => $job,
            ), WATCHDOG_NOTICE);
          }
          else {
            _dco_watchdog('cron', 'Job %job is already running', array(
              '%job' => $job,
            ), WATCHDOG_NOTICE);
            $job_running = true;
          }
        }
        if (!$job_running) {
          elysia_cron_execute($job);
        }
      }
      $cron_completed = true;
      $cron_completed_time = time();

      // Cron is really completed after shutdown functions
      register_shutdown_function('elysia_cron_completed');
    }
    else {

      // No jobs should be executed, i must unlock cron semaphore
      if (EC_DRUPAL_VERSION < 7) {
        _ec_variable_del('elysia_cron_semaphore');
      }
      if (variable_get('elysia_cron_debug_messages', 0)) {
        _dco_watchdog('cron', 'No channels ready to be executed, skipping cron.', array(), WATCHDOG_NOTICE);
      }
    }

    // Release cron lock.
    if (EC_DRUPAL_VERSION >= 7) {
      lock_release('cron');
    }
    else {
      _ec_variable_del('cron_semaphore');
      $conf['cron_semaphore'] = false;
    }
  }
  if (EC_DRUPAL_VERSION >= 7) {

    // D7 Queue processing
    foreach ($queues as $queue_name => $info) {
      $function = $info['worker callback'];
      $end = time() + (isset($info['time']) ? $info['time'] : 15);
      $queue = DrupalQueue::get($queue_name);
      while (time() < $end && ($item = $queue
        ->claimItem())) {
        $function($item->data);
        $queue
          ->deleteItem($item);
      }
    }
  }
  if ($manual_run) {

    // Restore the user.
    $GLOBALS['user'] = $original_user;

    /*if (EC_DRUPAL_VERSION >= 7) {
        drupal_save_session(TRUE);
      }*/
  }

  // Return TRUE so other functions can check if it did run successfully
  return $execute;
}