internal static MergeExecutor <TInputOutput> Execute <TKey>(PartitionedStream <TInputOutput, TKey> partitions, bool ignoreOutput, ParallelMergeOptions options, TaskScheduler taskScheduler, bool isOrdered, CancellationState cancellationState, int queryId) { MergeExecutor <TInputOutput> executor = new MergeExecutor <TInputOutput>(); if (isOrdered && !ignoreOutput) { if ((options != ParallelMergeOptions.FullyBuffered) && !partitions.OrdinalIndexState.IsWorseThan(OrdinalIndexState.Increasing)) { bool autoBuffered = options == ParallelMergeOptions.AutoBuffered; if (partitions.PartitionCount > 1) { executor.m_mergeHelper = new OrderPreservingPipeliningMergeHelper <TInputOutput>((PartitionedStream <TInputOutput, int>)partitions, taskScheduler, cancellationState, autoBuffered, queryId); } else { executor.m_mergeHelper = new DefaultMergeHelper <TInputOutput, TKey>(partitions, false, options, taskScheduler, cancellationState, queryId); } } else { executor.m_mergeHelper = new OrderPreservingMergeHelper <TInputOutput, TKey>(partitions, taskScheduler, cancellationState, queryId); } } else { executor.m_mergeHelper = new DefaultMergeHelper <TInputOutput, TKey>(partitions, ignoreOutput, options, taskScheduler, cancellationState, queryId); } executor.Execute(); return(executor); }
public void Receive <TKey>(PartitionedStream <TOutput, TKey> partitionedStream) { #if DEBUG m_received = true; #endif m_mergeExecutor = MergeExecutor <TOutput> .Execute <TKey>( partitionedStream, m_forEffectMerge, m_mergeOptions, m_taskScheduler, m_isOrdered, m_cancellationState, m_queryId); TraceHelpers.TraceInfo("[timing]: {0}: finished opening - QueryOperator<>::GetEnumerator", DateTime.Now.Ticks); }
//----------------------------------------------------------------------------------- // Creates and executes a new merge executor object. // // Arguments: // partitions - the partitions whose data will be merged into one stream // ignoreOutput - if true, we are enumerating "for effect", and we won't actually // generate data in the output stream // pipeline - whether to use a pipelined merge or not. // isOrdered - whether to perform an ordering merge. // internal static MergeExecutor <TInputOutput> Execute <TKey>( PartitionedStream <TInputOutput, TKey> partitions, bool ignoreOutput, ParallelMergeOptions options, TaskScheduler taskScheduler, bool isOrdered, CancellationState cancellationState, int queryId) { Debug.Assert(partitions != null); Debug.Assert(partitions.PartitionCount > 0); Debug.Assert(!ignoreOutput || options == ParallelMergeOptions.FullyBuffered, "Pipelining with no output is not supported."); MergeExecutor <TInputOutput> mergeExecutor = new MergeExecutor <TInputOutput>(); if (isOrdered && !ignoreOutput) { if (options != ParallelMergeOptions.FullyBuffered && !partitions.OrdinalIndexState.IsWorseThan(OrdinalIndexState.Increasing)) { Debug.Assert(options == ParallelMergeOptions.NotBuffered || options == ParallelMergeOptions.AutoBuffered); bool autoBuffered = (options == ParallelMergeOptions.AutoBuffered); if (partitions.PartitionCount > 1) { Debug.Assert(!ParallelEnumerable.SinglePartitionMode); // We use a pipelining ordered merge mergeExecutor._mergeHelper = new OrderPreservingPipeliningMergeHelper <TInputOutput, TKey>( partitions, taskScheduler, cancellationState, autoBuffered, queryId, partitions.KeyComparer); } else { // When DOP=1, the default merge simply returns the single producer enumerator to the consumer. This way, ordering // does not add any extra overhead, and no producer task needs to be scheduled. mergeExecutor._mergeHelper = new DefaultMergeHelper <TInputOutput, TKey>( partitions, false, options, taskScheduler, cancellationState, queryId); } } else { // We use a stop-and-go ordered merge helper mergeExecutor._mergeHelper = new OrderPreservingMergeHelper <TInputOutput, TKey>(partitions, taskScheduler, cancellationState, queryId); } } else { // We use a default - unordered - merge helper. mergeExecutor._mergeHelper = new DefaultMergeHelper <TInputOutput, TKey>(partitions, ignoreOutput, options, taskScheduler, cancellationState, queryId); } mergeExecutor.Execute(); return(mergeExecutor); }
//--------------------------------------------------------------------------------------- // A helper method that executes the query rooted at the openedChild operator, and returns // the results as ListQueryResults<TSource>. // internal static ListQueryResults <TOutput> ExecuteAndCollectResults <TKey>( PartitionedStream <TOutput, TKey> openedChild, int partitionCount, bool outputOrdered, bool useStriping, QuerySettings settings) { TaskScheduler taskScheduler = settings.TaskScheduler; MergeExecutor <TOutput> executor = MergeExecutor <TOutput> .Execute <TKey>( openedChild, false, ParallelMergeOptions.FullyBuffered, taskScheduler, outputOrdered, settings.CancellationState, settings.QueryId); return(new ListQueryResults <TOutput>(executor.GetResultsAsArray(), partitionCount, useStriping)); }
public void Receive <TKey>(PartitionedStream <TOutput, TKey> partitionedStream) { this.m_mergeExecutor = MergeExecutor <TOutput> .Execute <TKey>(partitionedStream, this.m_forEffectMerge, this.m_mergeOptions, this.m_taskScheduler, this.m_isOrdered, this.m_cancellationState, this.m_queryId); }