X-Git-Url: https://yaffs.net/gitweb/?a=blobdiff_plain;f=vendor%2Fdrush%2Fdrush%2Fincludes%2Fbatch.inc;fp=vendor%2Fdrush%2Fdrush%2Fincludes%2Fbatch.inc;h=f2a659d579a9c421d861f1318efc32ad2972e094;hb=af6d1fb995500ae68849458ee10d66abbdcfb252;hp=71fedb330d2956983a234b20eb46ac5ff27aba0f;hpb=680c79a86e3ed402f263faeac92e89fb6d9edcc0;p=yaffs-website diff --git a/vendor/drush/drush/includes/batch.inc b/vendor/drush/drush/includes/batch.inc index 71fedb330..f2a659d57 100644 --- a/vendor/drush/drush/includes/batch.inc +++ b/vendor/drush/drush/includes/batch.inc @@ -64,7 +64,7 @@ class DrushBatchContext extends ArrayObject { * * @param string $command * (optional) The command to call for the back end process. By default this will be - * the 'batch-process' command, but some commands such as updatedb will + * the 'batch-process' command, but some commands will * have special initialization requirements, and will need to define and * use their own command. * @param array $args @@ -72,12 +72,10 @@ class DrushBatchContext extends ArrayObject { * @param array $options * (optional) */ -function drush_backend_batch_process($command = 'batch-process', $args = array(), $options = array()) { +function drush_backend_batch_process($command = 'batch-process', $args = [], $options = []) { // Command line options to pass to the command. - $options['u'] = drush_user_get_class()->getCurrentUserAsSingle()->id(); - - drush_include_engine('drupal', 'batch'); - _drush_backend_batch_process($command, $args, $options); + $options['u'] = \Drupal::currentUser()->id(); + return _drush_backend_batch_process($command, $args, $options); } /** @@ -94,6 +92,280 @@ function drush_backend_batch_process($command = 'batch-process', $args = array() */ function drush_batch_command($id) { include_once(DRUSH_DRUPAL_CORE . '/includes/batch.inc'); - drush_include_engine('drupal', 'batch'); - _drush_batch_command($id); + return _drush_batch_command($id); +} + +/** + * Main loop for the Drush batch API. + * + * Saves a record of the batch into the database, and progressively call $command to + * process the operations. + * + * @param command + * The command to call to process the batch. + * + */ +function _drush_backend_batch_process($command = 'batch-process', $args, $options) { + $result = NULL; + + $batch =& batch_get(); + + if (isset($batch)) { + $process_info = [ + 'current_set' => 0, + ]; + $batch += $process_info; + + // The batch is now completely built. Allow other modules to make changes + // to the batch so that it is easier to reuse batch processes in other + // enviroments. + \Drupal::moduleHandler()->alter('batch', $batch); + + // Assign an arbitrary id: don't rely on a serial column in the 'batch' + // table, since non-progressive batches skip database storage completely. + $batch['id'] = db_next_id(); + $args[] = $batch['id']; + + $batch['progressive'] = TRUE; + + // Move operations to a job queue. Non-progressive batches will use a + // memory-based queue. + foreach ($batch['sets'] as $key => $batch_set) { + _batch_populate_queue($batch, $key); + } + + // Store the batch. + /** @var \Drupal\Core\Batch\BatchStorage $batch_storage */ + $batch_storage = \Drupal::service('batch.storage'); + $batch_storage->create($batch); + $finished = FALSE; + + while (!$finished) { + $result = drush_invoke_process('@self', $command, $args); + $finished = drush_get_error() || !$result || (isset($result['context']['drush_batch_process_finished']) && $result['context']['drush_batch_process_finished'] == TRUE); + } + } + + return $result; +} + + +/** + * Initialize the batch command and call the worker function. + * + * Loads the batch record from the database and sets up the requirements + * for the worker, such as registering the shutdown function. + * + * @param id + * The batch id of the batch being processed. + */ +function _drush_batch_command($id) { + $batch =& batch_get(); + + $data = db_query("SELECT batch FROM {batch} WHERE bid = :bid", [ + ':bid' => $id + ])->fetchField(); + + if ($data) { + $batch = unserialize($data); + } + else { + return FALSE; + } + + if (!isset($batch['running'])) { + $batch['running'] = TRUE; + } + + // Register database update for end of processing. + register_shutdown_function('_drush_batch_shutdown'); + + if (_drush_batch_worker()) { + return _drush_batch_finished(); + } +} + + +/** + * Process batch operations + * + * Using the current $batch process each of the operations until the batch + * has been completed or half of the available memory for the process has been + * reached. + */ +function _drush_batch_worker() { + $batch =& batch_get(); + $current_set =& _batch_current_set(); + $set_changed = TRUE; + + if (empty($current_set['start'])) { + $current_set['start'] = microtime(TRUE); + } + $queue = _batch_queue($current_set); + while (!$current_set['success']) { + // If this is the first time we iterate this batch set in the current + // request, we check if it requires an additional file for functions + // definitions. + if ($set_changed && isset($current_set['file']) && is_file($current_set['file'])) { + include_once DRUPAL_ROOT . '/' . $current_set['file']; + } + + $task_message = ''; + // Assume a single pass operation and set the completion level to 1 by + // default. + $finished = 1; + + if ($item = $queue->claimItem()) { + list($function, $args) = $item->data; + + // Build the 'context' array and execute the function call. + $batch_context = [ + 'sandbox' => &$current_set['sandbox'], + 'results' => &$current_set['results'], + 'finished' => &$finished, + 'message' => &$task_message, + ]; + // Magic wrap to catch changes to 'message' key. + $batch_context = new DrushBatchContext($batch_context); + + // Tolerate recoverable errors. + // See https://github.com/drush-ops/drush/issues/1930 + $halt_on_error = \Drush\Drush::config()->get('runtime.php.halt-on-error', TRUE); + \Drush\Drush::config()->set('runtime.php.halt-on-error', FALSE); + $message = call_user_func_array($function, array_merge($args, [&$batch_context])); + if (!empty($message)) { + drush_print(strip_tags($message), 2); + } + \Drush\Drush::config()->set('runtime.php.halt-on-error', $halt_on_error); + + $finished = $batch_context['finished']; + if ($finished >= 1) { + // Make sure this step is not counted twice when computing $current. + $finished = 0; + // Remove the processed operation and clear the sandbox. + $queue->deleteItem($item); + $current_set['count']--; + $current_set['sandbox'] = []; + } + } + + // When all operations in the current batch set are completed, browse + // through the remaining sets, marking them 'successfully processed' + // along the way, until we find a set that contains operations. + // _batch_next_set() executes form submit handlers stored in 'control' + // sets (see form_execute_handlers()), which can in turn add new sets to + // the batch. + $set_changed = FALSE; + $old_set = $current_set; + while (empty($current_set['count']) && ($current_set['success'] = TRUE) && _batch_next_set()) { + $current_set = &_batch_current_set(); + $current_set['start'] = microtime(TRUE); + $set_changed = TRUE; + } + + // At this point, either $current_set contains operations that need to be + // processed or all sets have been completed. + $queue = _batch_queue($current_set); + + // If we are in progressive mode, break processing after 1 second. + if (drush_memory_limit() > 0 && (memory_get_usage() * 2) >= drush_memory_limit()) { + drush_log(dt("Batch process has consumed in excess of 50% of available memory. Starting new thread"), LogLevel::BATCH); + // Record elapsed wall clock time. + $current_set['elapsed'] = round((microtime(TRUE) - $current_set['start']) * 1000, 2); + break; + } + } + + // Reporting 100% progress will cause the whole batch to be considered + // processed. If processing was paused right after moving to a new set, + // we have to use the info from the new (unprocessed) set. + if ($set_changed && isset($current_set['queue'])) { + // Processing will continue with a fresh batch set. + $remaining = $current_set['count']; + $total = $current_set['total']; + $progress_message = $current_set['init_message']; + $task_message = ''; + } + else { + // Processing will continue with the current batch set. + $remaining = $old_set['count']; + $total = $old_set['total']; + $progress_message = $old_set['progress_message']; + } + + $current = $total - $remaining + $finished; + $percentage = _batch_api_percentage($total, $current); + return ($percentage == 100); +} + +/** + * End the batch processing: + * Call the 'finished' callbacks to allow custom handling of results, + * and resolve page redirection. + */ +function _drush_batch_finished() { + $results = []; + + $batch = &batch_get(); + + // Execute the 'finished' callbacks for each batch set, if defined. + foreach ($batch['sets'] as $id => $batch_set) { + if (isset($batch_set['finished'])) { + // Check if the set requires an additional file for function definitions. + if (isset($batch_set['file']) && is_file($batch_set['file'])) { + include_once DRUPAL_ROOT . '/' . $batch_set['file']; + } + if (is_callable($batch_set['finished'])) { + $queue = _batch_queue($batch_set); + $operations = $queue->getAllItems(); + $elapsed = $batch_set['elapsed'] / 1000; + $elapsed = drush_drupal_major_version() >=8 ? \Drupal::service('date.formatter')->formatInterval($elapsed) : format_interval($elapsed); + $batch_set['finished']($batch_set['success'], $batch_set['results'], $operations, $elapsed); + $results[$id] = $batch_set['results']; + } + } + } + + // Clean up the batch table and unset the static $batch variable. + if (drush_drupal_major_version() >= 8) { + /** @var \Drupal\Core\Batch\BatchStorage $batch_storage */ + $batch_storage = \Drupal::service('batch.storage'); + $batch_storage->delete($batch['id']); + } + else { + db_delete('batch') + ->condition('bid', $batch['id']) + ->execute(); + } + + foreach ($batch['sets'] as $batch_set) { + if ($queue = _batch_queue($batch_set)) { + $queue->deleteQueue(); + } + } + $_batch = $batch; + $batch = NULL; + drush_set_option('drush_batch_process_finished', TRUE); + + return $results; +} + +/** + * Shutdown function: store the batch data for next request, + * or clear the table if the batch is finished. + */ +function _drush_batch_shutdown() { + if ($batch = batch_get()) { + if (drush_drupal_major_version() >= 8) { + /** @var \Drupal\Core\Batch\BatchStorage $batch_storage */ + $batch_storage = \Drupal::service('batch.storage'); + $batch_storage->update($batch); + } + else { + db_update('batch') + ->fields(['batch' => serialize($batch)]) + ->condition('bid', $batch['id']) + ->execute(); + } + } }